Line data Source code
1 : import type { CatalogNameDefaults } from '@ankoh/dashql-core';
2 :
3 : import type { ConnectionParams, HyperConnectionParams, SalesforceConnectionParams, TrinoConnectionParams } from './connection_params.js';
4 : import type { ConnectionStateDetailsVariant } from './connection_state_details.js';
5 : import type { ConnectionAction, ConnectionState } from './connection_state.js';
6 : import type { HyperConnectionDetails } from './hyper/hyper_connection_state.js';
7 : import type { SalesforceConnectionStateDetails } from './salesforce/salesforce_connection_state.js';
8 : import type { TrinoConnectionStateDetails } from './trino/trino_connection_state.js';
9 : import { ConnectorType, type ConnectorInfo } from './connector_info.js';
10 : import type { QueryExecutionArgs } from './query_execution_args.js';
11 : import type { QueryExecutionResponseStream } from '../query/query_execution_state.js';
12 : import type { ClientFunctionHostTarget } from './clfn/clfn_runtime.js';
13 : import type { ClientFunctionSpec } from './clfn/clfn_spec.js';
14 : import { HYPER_CONNECTOR_DESCRIPTOR } from './hyper/hyper_connector_descriptor.js';
15 : import { SALESFORCE_CONNECTOR_DESCRIPTOR, DBCOM_CONNECTOR_DESCRIPTOR } from './salesforce/salesforce_connector_descriptor.js';
16 : import { TRINO_CONNECTOR_DESCRIPTOR } from './trino/trino_connector_descriptor.js';
17 :
18 : /// The params of the connectors by the field of the connection params that holds them
19 : export interface ConnectorParamsMap {
20 : /// Direct-to-Hyper connections
21 : hyper: HyperConnectionParams;
22 : /// Salesforce Data Cloud connections
23 : salesforce: SalesforceConnectionParams;
24 : /// Database.com connections, they share the params of Salesforce Data Cloud connections
25 : dbcom: SalesforceConnectionParams;
26 : /// Trino connections
27 : trino: TrinoConnectionParams;
28 : }
29 : /// The details of the connection state of the connectors
30 : interface ConnectorDetailsMap {
31 : /// Direct-to-Hyper connections
32 : hyper: HyperConnectionDetails;
33 : /// Salesforce Data Cloud connections
34 : salesforce: SalesforceConnectionStateDetails;
35 : /// Database.com connections
36 : dbcom: SalesforceConnectionStateDetails;
37 : /// Trino connections
38 : trino: TrinoConnectionStateDetails;
39 : }
40 : /// The field of the connection params that holds the params of a connector, e.g. `{ hyper: ... }`
41 : export type ConnectorParamsKey = keyof ConnectorParamsMap;
42 :
43 : /// The client functions that a connector enables on its connections
44 : export interface ClientFunctionBinding<Details = unknown> {
45 : /// Load the spec, only when a connection needs it
46 : loadSpec(): Promise<ClientFunctionSpec>;
47 : /// Where a host that the spec names is on a connection, and the credentials for it
48 : resolveHost(details: Details, host: string): Promise<ClientFunctionHostTarget>;
49 : /// The values of the variables in the base paths of the spec. They need no login, `EXPLAIN` prints them.
50 : variables(details: Details): Record<string, string>;
51 : }
52 :
53 : /// What the connection layer knows about a connector.
54 : ///
55 : /// Every connector describes itself once, operations on connections look up the connector instead
56 : /// of switching on its type. The params and details of the connection state always hold the params
57 : /// of the connector under its key, generic operations convert between them through `paramsKey`.
58 : export interface ConnectorDescriptor<K extends ConnectorParamsKey = ConnectorParamsKey> {
59 : /// The connector info
60 : info: ConnectorInfo;
61 : /// The field of the connection params that holds the params of the connector
62 : paramsKey: K;
63 : /// The variant type of the details of the connection state
64 : detailsType: ConnectionStateDetailsVariant['type'];
65 : /// The params of a new connection
66 : defaultParams(): ConnectorParamsMap[K];
67 : /// Create the details of the connection state
68 : createDetails(params: ConnectorParamsMap[K]): ConnectorDetailsMap[K];
69 : /// Apply an action of the connector to the connection state, null if the action is not one of its own
70 : reduce(state: ConnectionState, action: ConnectionAction): ConnectionState | null;
71 : /// Remove the raw form rows, they belong only to the local draft
72 : withoutDraftRows(params: ConnectorParamsMap[K]): ConnectorParamsMap[K];
73 : /// Strip the secrets before the params are shared, the login hint only if `withLoginHint` is false
74 : sanitizeForSharing(params: ConnectorParamsMap[K], withLoginHint: boolean): ConnectorParamsMap[K];
75 : /// The login hint (the account username or login) of the params, null if there is none
76 : loginHint(params: ConnectorParamsMap[K]): string | null;
77 : /// The params that identify the results of a query in the query result cache
78 : cacheSignature(params: ConnectorParamsMap[K]): unknown;
79 : /// The database and schema of the relations that unqualified statements create or drop.
80 : /// They match the names that the catalog loader gives the relations of the connection.
81 : catalogNameDefaults(details: ConnectorDetailsMap[K]): CatalogNameDefaults;
82 : /// Execute a query on the channel of a connection, a channel override of the connector wins
83 : executeQuery(details: ConnectorDetailsMap[K], args: QueryExecutionArgs, abort?: AbortSignal): Promise<QueryExecutionResponseStream>;
84 : /// The number of statements of a session run that a connection executes at once
85 : maxConcurrentQueries(details: ConnectorDetailsMap[K]): number;
86 : /// Does the catalog of a connection outlive the page? The relations of a database that is created anew with
87 : /// every page load and the catalog changes of its statements are neither persisted nor restored.
88 : catalogIsDurable(params: ConnectorParamsMap[K]): boolean;
89 : /// Can the queries of a connection read the data files that are attached to a session?
90 : readsAttachments(details: ConnectorDetailsMap[K]): boolean;
91 : /// The client functions of the connections, undefined if they have none
92 : clientFunctions?: ClientFunctionBinding<ConnectorDetailsMap[K]>;
93 : }
94 :
95 : /// The connectors by connector type
96 1 : export const CONNECTOR_DESCRIPTORS: Record<ConnectorType, ConnectorDescriptor> = {
97 1 : [ConnectorType.HYPER]: HYPER_CONNECTOR_DESCRIPTOR,
98 1 : [ConnectorType.SALESFORCE_DATA_CLOUD]: SALESFORCE_CONNECTOR_DESCRIPTOR,
99 1 : [ConnectorType.TRINO]: TRINO_CONNECTOR_DESCRIPTOR,
100 1 : [ConnectorType.DBCOM]: DBCOM_CONNECTOR_DESCRIPTOR,
101 1 : };
102 1 : const DESCRIPTORS = Object.values(CONNECTOR_DESCRIPTORS);
103 :
104 : /// The connector of connection params
105 1 : export function connectorOfParams(params: ConnectionParams): ConnectorDescriptor {
106 1 : return DESCRIPTORS.find(connector => connector.paramsKey in params)!;
107 1 : }
108 :
109 : /// The connector of the details of a connection state
110 1 : export function connectorOfDetails(details: ConnectionStateDetailsVariant): ConnectorDescriptor {
111 1 : return DESCRIPTORS.find(connector => connector.detailsType === details.type)!;
112 1 : }
113 :
114 : /// The params of the connector of connection params
115 1 : export function connectorParams(connector: ConnectorDescriptor, params: ConnectionParams): ConnectorParamsMap[ConnectorParamsKey] {
116 1 : return (params as Partial<ConnectorParamsMap>)[connector.paramsKey]!;
117 1 : }
118 :
119 : /// The connection params that hold the params of a connector
120 1 : export function connectionParamsOf(connector: ConnectorDescriptor, params: ConnectorParamsMap[ConnectorParamsKey]): ConnectionParams {
121 1 : return { [connector.paramsKey]: params } as unknown as ConnectionParams;
122 1 : }
123 :
124 : /// The details of a connection state with connection params
125 1 : export function connectionStateDetailsOf(connector: ConnectorDescriptor, params: ConnectorParamsMap[ConnectorParamsKey]): ConnectionStateDetailsVariant {
126 1 : return { type: connector.detailsType, value: connector.createDetails(params) } as ConnectionStateDetailsVariant;
127 1 : }
128 :
129 : /// The database and schema of the relations that unqualified statements create or drop on a connection
130 1 : export function catalogNameDefaults(details: ConnectionStateDetailsVariant): CatalogNameDefaults {
131 1 : return connectorOfDetails(details).catalogNameDefaults(details.value);
132 1 : }
133 :
134 : /// Can the queries of a connection read the data files that are attached to a session?
135 1 : export function connectionReadsAttachments(details: ConnectionStateDetailsVariant | null | undefined): boolean {
136 1 : return details != null && connectorOfDetails(details).readsAttachments(details.value);
137 1 : }
|