@memberjunction/external-data-sources 0.0.0 → 5.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/BaseExternalDataSourceDriver.d.ts +34 -0
  2. package/dist/BaseExternalDataSourceDriver.d.ts.map +1 -0
  3. package/dist/BaseExternalDataSourceDriver.js +181 -0
  4. package/dist/BaseExternalDataSourceDriver.js.map +1 -0
  5. package/dist/BaseSqlExternalDataSourceDriver.d.ts +29 -0
  6. package/dist/BaseSqlExternalDataSourceDriver.d.ts.map +1 -0
  7. package/dist/BaseSqlExternalDataSourceDriver.js +112 -0
  8. package/dist/BaseSqlExternalDataSourceDriver.js.map +1 -0
  9. package/dist/ExternalDataSourceReadRouterImpl.d.ts +14 -0
  10. package/dist/ExternalDataSourceReadRouterImpl.d.ts.map +1 -0
  11. package/dist/ExternalDataSourceReadRouterImpl.js +163 -0
  12. package/dist/ExternalDataSourceReadRouterImpl.js.map +1 -0
  13. package/dist/ExternalDataSourceRouter.d.ts +22 -0
  14. package/dist/ExternalDataSourceRouter.d.ts.map +1 -0
  15. package/dist/ExternalDataSourceRouter.js +103 -0
  16. package/dist/ExternalDataSourceRouter.js.map +1 -0
  17. package/dist/index.d.ts +8 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +8 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/sqlReadOnlyScreen.d.ts +4 -0
  22. package/dist/sqlReadOnlyScreen.d.ts.map +1 -0
  23. package/dist/sqlReadOnlyScreen.js +75 -0
  24. package/dist/sqlReadOnlyScreen.js.map +1 -0
  25. package/dist/temporal.d.ts +5 -0
  26. package/dist/temporal.d.ts.map +1 -0
  27. package/dist/temporal.js +17 -0
  28. package/dist/temporal.js.map +1 -0
  29. package/dist/types.d.ts +48 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +4 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +33 -7
  34. package/README.md +0 -45
@@ -0,0 +1,34 @@
1
+ import { UserInfo, ExternalSchemaDescriptor } from "@memberjunction/core";
2
+ import { MJExternalDataSourceEntity } from "@memberjunction/core-entities";
3
+ import { ResolvedCredential } from "@memberjunction/credentials";
4
+ import { ExternalConnectionTestResult, ExternalViewParams, ExternalViewResult, ExternalQueryParameter, ExternalQueryResult, ExternalRow } from "./types.js";
5
+ export declare abstract class BaseExternalDataSourceDriver<TConnection = unknown> {
6
+ abstract TestConnection(dataSource: MJExternalDataSourceEntity, contextUser?: UserInfo): Promise<ExternalConnectionTestResult>;
7
+ abstract IntrospectSchema(dataSource: MJExternalDataSourceEntity, schemaName: string | undefined, contextUser?: UserInfo): Promise<ExternalSchemaDescriptor>;
8
+ abstract RunView<TRow extends ExternalRow = ExternalRow>(dataSource: MJExternalDataSourceEntity, params: ExternalViewParams, contextUser?: UserInfo): Promise<ExternalViewResult<TRow>>;
9
+ abstract LoadSingle<TRow extends ExternalRow = ExternalRow>(dataSource: MJExternalDataSourceEntity, objectName: string, primaryKeys: readonly ExternalQueryParameter[], contextUser?: UserInfo): Promise<TRow | null>;
10
+ abstract RunNativeQuery<TRow extends ExternalRow = ExternalRow>(dataSource: MJExternalDataSourceEntity, queryText: string, params: ExternalQueryParameter[] | undefined, contextUser?: UserInfo): Promise<ExternalQueryResult<TRow>>;
11
+ protected abstract getConnection(dataSource: MJExternalDataSourceEntity, contextUser?: UserInfo): Promise<TConnection>;
12
+ protected resolveCredential<TCred extends Record<string, string> = Record<string, string>>(dataSource: MJExternalDataSourceEntity, contextUser?: UserInfo): Promise<ResolvedCredential<TCred> | null>;
13
+ protected parseConnectionConfig<TConfig = Record<string, unknown>>(dataSource: MJExternalDataSourceEntity): TConfig;
14
+ protected assertSecureTransport(opts: {
15
+ host: string | undefined;
16
+ tlsEnabled: boolean;
17
+ allowInsecure: boolean | undefined;
18
+ dataSourceName: string;
19
+ }): void;
20
+ protected isLocalHost(host: string | undefined): boolean;
21
+ protected errorText(e: unknown): string;
22
+ protected redactConnectionSecrets(message: string): string;
23
+ protected normalizeValue(v: unknown): unknown;
24
+ private deepNormalizeForJson;
25
+ protected normalizeRows<TRow extends Record<string, unknown>>(rows: TRow[]): TRow[];
26
+ protected abstract invalidateConnection(dataSourceId: string, expectedIdentity?: unknown): Promise<void>;
27
+ protected peekConnection(_dataSourceId: string): unknown;
28
+ CloseConnection(dataSourceId: string): Promise<void>;
29
+ protected withConnectionRetry<T>(dataSource: MJExternalDataSourceEntity, op: () => Promise<T>): Promise<T>;
30
+ protected isAuthError(e: unknown): boolean;
31
+ private static readonly AuthErrorCodes;
32
+ private extractErrorCode;
33
+ }
34
+ //# sourceMappingURL=BaseExternalDataSourceDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseExternalDataSourceDriver.d.ts","sourceRoot":"","sources":["../src/BaseExternalDataSourceDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ import { CredentialEngine } from "@memberjunction/credentials";
2
+ import { redactConnectionSecrets, } from "./types.js";
3
+ export class BaseExternalDataSourceDriver {
4
+ async resolveCredential(dataSource, contextUser) {
5
+ if (!dataSource.CredentialID) {
6
+ return null;
7
+ }
8
+ await CredentialEngine.Instance.Config(false, contextUser);
9
+ return CredentialEngine.Instance.getCredential('', {
10
+ credentialId: dataSource.CredentialID,
11
+ contextUser,
12
+ subsystem: 'ExternalDataSources',
13
+ });
14
+ }
15
+ parseConnectionConfig(dataSource) {
16
+ if (!dataSource.ConnectionConfig) {
17
+ return {};
18
+ }
19
+ try {
20
+ return JSON.parse(dataSource.ConnectionConfig);
21
+ }
22
+ catch {
23
+ throw new Error(`ExternalDataSource '${dataSource.Name}' has invalid ConnectionConfig JSON.`);
24
+ }
25
+ }
26
+ assertSecureTransport(opts) {
27
+ if (opts.tlsEnabled || opts.allowInsecure === true) {
28
+ return;
29
+ }
30
+ if (!this.isLocalHost(opts.host)) {
31
+ const host = (opts.host ?? '').trim().toLowerCase().replace(/^\[|\]$/g, '');
32
+ throw new Error(`Refusing to connect to external data source '${opts.dataSourceName}' at '${host || '<unspecified host>'}' over an unencrypted connection. ` +
33
+ `Enable TLS in ConnectionConfig, or set "allowInsecureTransport": true to explicitly accept a plaintext connection.`);
34
+ }
35
+ }
36
+ isLocalHost(host) {
37
+ const h = (host ?? '').trim().toLowerCase().replace(/^\[|\]$/g, '');
38
+ return (h === 'localhost' ||
39
+ h.endsWith('.localhost') ||
40
+ h === '::1' ||
41
+ /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h));
42
+ }
43
+ errorText(e) {
44
+ const raw = e instanceof Error ? e.message : String(e);
45
+ return this.redactConnectionSecrets(raw);
46
+ }
47
+ redactConnectionSecrets(message) {
48
+ return redactConnectionSecrets(message);
49
+ }
50
+ normalizeValue(v) {
51
+ if (v === null || v === undefined)
52
+ return v;
53
+ if (typeof v === 'bigint')
54
+ return v.toString();
55
+ if (v instanceof Date || Buffer.isBuffer(v))
56
+ return v;
57
+ if (typeof v === 'object') {
58
+ const bsonType = v._bsontype;
59
+ if (bsonType) {
60
+ switch (bsonType) {
61
+ case 'Long':
62
+ case 'Decimal128':
63
+ case 'ObjectId':
64
+ case 'ObjectID':
65
+ return v.toString();
66
+ case 'Binary': {
67
+ const bin = v;
68
+ return bin.buffer ?? (typeof bin.value === 'function' ? bin.value(true) : v);
69
+ }
70
+ case 'Double':
71
+ case 'Int32':
72
+ return v.valueOf();
73
+ default:
74
+ return v.toString();
75
+ }
76
+ }
77
+ return JSON.stringify(this.deepNormalizeForJson(v));
78
+ }
79
+ return v;
80
+ }
81
+ deepNormalizeForJson(v) {
82
+ if (v === null || v === undefined)
83
+ return v;
84
+ if (typeof v === 'bigint')
85
+ return v.toString();
86
+ if (v instanceof Date)
87
+ return v;
88
+ if (Buffer.isBuffer(v))
89
+ return v.toString('base64');
90
+ if (typeof v === 'object') {
91
+ const bsonType = v._bsontype;
92
+ if (bsonType) {
93
+ switch (bsonType) {
94
+ case 'Long':
95
+ case 'Decimal128':
96
+ case 'ObjectId':
97
+ case 'ObjectID':
98
+ return v.toString();
99
+ case 'Binary': {
100
+ const bin = v;
101
+ const buf = bin.buffer ?? (typeof bin.value === 'function' ? bin.value(true) : undefined);
102
+ return Buffer.isBuffer(buf) ? buf.toString('base64') : v.toString();
103
+ }
104
+ case 'Double':
105
+ case 'Int32':
106
+ return v.valueOf();
107
+ default:
108
+ return v.toString();
109
+ }
110
+ }
111
+ if (Array.isArray(v)) {
112
+ return v.map((x) => this.deepNormalizeForJson(x));
113
+ }
114
+ const out = {};
115
+ for (const k in v) {
116
+ out[k] = this.deepNormalizeForJson(v[k]);
117
+ }
118
+ return out;
119
+ }
120
+ return v;
121
+ }
122
+ normalizeRows(rows) {
123
+ for (const row of rows) {
124
+ for (const k in row) {
125
+ row[k] = this.normalizeValue(row[k]);
126
+ }
127
+ }
128
+ return rows;
129
+ }
130
+ peekConnection(_dataSourceId) {
131
+ return undefined;
132
+ }
133
+ async CloseConnection(dataSourceId) {
134
+ await this.invalidateConnection(dataSourceId);
135
+ }
136
+ async withConnectionRetry(dataSource, op) {
137
+ const identity = this.peekConnection(dataSource.ID);
138
+ try {
139
+ return await op();
140
+ }
141
+ catch (e) {
142
+ if (!this.isAuthError(e)) {
143
+ throw e;
144
+ }
145
+ try {
146
+ await this.invalidateConnection(dataSource.ID, identity);
147
+ }
148
+ catch { }
149
+ return await op();
150
+ }
151
+ }
152
+ isAuthError(e) {
153
+ const code = this.extractErrorCode(e);
154
+ if (code && BaseExternalDataSourceDriver.AuthErrorCodes.has(code)) {
155
+ return true;
156
+ }
157
+ const msg = (e instanceof Error ? e.message : String(e)).toLowerCase();
158
+ return (msg.includes('authentic') ||
159
+ msg.includes('authoriz') ||
160
+ msg.includes('credential') ||
161
+ msg.includes('login failed') ||
162
+ msg.includes('access denied') ||
163
+ msg.includes('28p01') ||
164
+ msg.includes('28000'));
165
+ }
166
+ static { this.AuthErrorCodes = new Set([
167
+ '28P01', '28000', '1044', '1045', '1698', '4060', '18452', '18456', '18470', '1017', '1031',
168
+ ]); }
169
+ extractErrorCode(e) {
170
+ if (e && typeof e === 'object') {
171
+ const err = e;
172
+ for (const c of [err.code, err.errno, err.errorNum, err.number]) {
173
+ if (c != null && c !== '') {
174
+ return String(c).toUpperCase();
175
+ }
176
+ }
177
+ }
178
+ return undefined;
179
+ }
180
+ }
181
+ //# sourceMappingURL=BaseExternalDataSourceDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseExternalDataSourceDriver.js","sourceRoot":"","sources":["../src/BaseExternalDataSourceDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { ExternalObjectType, ExternalSchemaRelationship } from "@memberjunction/core";
2
+ import { MJExternalDataSourceEntity } from "@memberjunction/core-entities";
3
+ import { BaseExternalDataSourceDriver } from "./BaseExternalDataSourceDriver.js";
4
+ import { ExternalFkRow, ExternalViewParams, ExternalQueryParameter } from "./types.js";
5
+ import { type SqlDialectKey } from "./sqlReadOnlyScreen.js";
6
+ export declare abstract class BaseSqlExternalDataSourceDriver<TConnection = unknown> extends BaseExternalDataSourceDriver<TConnection> {
7
+ protected abstract quoteIdent(name: string): string;
8
+ protected sqlDialectKey(): SqlDialectKey;
9
+ protected screenReadOnlyNativeQuery(sql: string): void;
10
+ protected normalizeForReadOnlyParse(sql: string): string;
11
+ protected buildPrimaryKeyWhere(primaryKeys: readonly ExternalQueryParameter[], placeholder: (index: number) => string): {
12
+ clause: string;
13
+ values: Array<ExternalQueryParameter["value"]>;
14
+ };
15
+ protected screenReadOnlyClause(clause: string, kind: "where" | "orderby"): void;
16
+ protected abstract orderAndPageClause(params: ExternalViewParams): string;
17
+ protected selectTopClause(_params: ExternalViewParams): string;
18
+ protected quoteLiteral(value: string): string;
19
+ protected buildIncrementalPredicate(params: ExternalViewParams): string | undefined;
20
+ protected formatIncrementalLiteral(value: string): string;
21
+ protected effectiveWhere(params: ExternalViewParams): string | undefined;
22
+ protected buildCountSql(target: string, params: ExternalViewParams): string;
23
+ protected buildSelectSql(target: string, params: ExternalViewParams): string;
24
+ protected applyDefaultOrderBy(params: ExternalViewParams): ExternalViewParams;
25
+ protected mapObjectType(objectType: string): ExternalObjectType;
26
+ protected qualifyObject(dataSource: MJExternalDataSourceEntity, objectName: string): string;
27
+ protected groupForeignKeys(fkRows: ExternalFkRow[]): Map<string, ExternalSchemaRelationship[]>;
28
+ }
29
+ //# sourceMappingURL=BaseSqlExternalDataSourceDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseSqlExternalDataSourceDriver.d.ts","sourceRoot":"","sources":["../src/BaseSqlExternalDataSourceDriver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAmD,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAiB1G,8BAAsB,+BAA+B,CAAC,WAAW,GAAG,OAAO,CAAE,SAAQ,4BAA4B,CAAC,WAAW,CAAC;IAE5H,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQnD,SAAS,CAAC,aAAa,IAAI,aAAa;IAWxC,SAAS,CAAC,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAYtD,SAAS,CAAC,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAWxD,SAAS,CAAC,oBAAoB,CAC5B,WAAW,EAAE,SAAS,sBAAsB,EAAE,EAC9C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GACrC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAA;KAAE;IAoBrE,SAAS,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAQ/E,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAMzE,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM;IAK9D,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAU7C,SAAS,CAAC,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS;IAanF,SAAS,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAUzD,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS;IAmBxE,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAa3E,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAyB5E,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB;IAS7E,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB;IAK/D,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAe3F,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CAoB/F"}
@@ -0,0 +1,112 @@
1
+ import { BaseExternalDataSourceDriver } from "./BaseExternalDataSourceDriver.js";
2
+ import { assertReadOnlyNativeQuery, assertReadOnlyClause } from "./sqlReadOnlyScreen.js";
3
+ export class BaseSqlExternalDataSourceDriver extends BaseExternalDataSourceDriver {
4
+ sqlDialectKey() {
5
+ return 'ansi';
6
+ }
7
+ screenReadOnlyNativeQuery(sql) {
8
+ assertReadOnlyNativeQuery(this.normalizeForReadOnlyParse(sql), this.sqlDialectKey());
9
+ }
10
+ normalizeForReadOnlyParse(sql) {
11
+ return sql;
12
+ }
13
+ buildPrimaryKeyWhere(primaryKeys, placeholder) {
14
+ if (primaryKeys.length === 0) {
15
+ throw new Error("buildPrimaryKeyWhere requires at least one primary-key value.");
16
+ }
17
+ const parts = [];
18
+ const values = [];
19
+ primaryKeys.forEach((pk, i) => {
20
+ parts.push(`${this.quoteIdent(pk.name)} = ${placeholder(i)}`);
21
+ values.push(pk.value);
22
+ });
23
+ return { clause: parts.join(" AND "), values };
24
+ }
25
+ screenReadOnlyClause(clause, kind) {
26
+ assertReadOnlyClause(clause, this.sqlDialectKey(), kind);
27
+ }
28
+ selectTopClause(_params) {
29
+ return '';
30
+ }
31
+ quoteLiteral(value) {
32
+ return `'${value.replace(/'/g, "''")}'`;
33
+ }
34
+ buildIncrementalPredicate(params) {
35
+ if (!params.incrementalSince) {
36
+ return undefined;
37
+ }
38
+ return `${this.quoteIdent(params.incrementalSince.Field)} >= ${this.formatIncrementalLiteral(params.incrementalSince.Value)}`;
39
+ }
40
+ formatIncrementalLiteral(value) {
41
+ return this.quoteLiteral(value);
42
+ }
43
+ effectiveWhere(params) {
44
+ const incremental = this.buildIncrementalPredicate(params);
45
+ const filter = params.filter && params.filter.trim().length > 0 ? params.filter : undefined;
46
+ if (filter && incremental) {
47
+ return `(${filter}) AND ${incremental}`;
48
+ }
49
+ return filter ?? incremental;
50
+ }
51
+ buildCountSql(target, params) {
52
+ const where = this.effectiveWhere(params);
53
+ return `SELECT COUNT(*) AS cnt FROM ${target}${where ? ` WHERE ${where}` : ''}`;
54
+ }
55
+ buildSelectSql(target, params) {
56
+ if (params.filter && params.filter.trim().length > 0) {
57
+ this.screenReadOnlyClause(params.filter, 'where');
58
+ }
59
+ if (params.orderBy) {
60
+ this.screenReadOnlyClause(params.orderBy, 'orderby');
61
+ }
62
+ const projection = params.fields?.length ? params.fields.map((f) => this.quoteIdent(f)).join(', ') : '*';
63
+ const effectiveParams = this.applyDefaultOrderBy(params);
64
+ const where = this.effectiveWhere(params);
65
+ let sql = `SELECT ${this.selectTopClause(effectiveParams)}${projection} FROM ${target}`;
66
+ if (where) {
67
+ sql += ` WHERE ${where}`;
68
+ }
69
+ sql += this.orderAndPageClause(effectiveParams);
70
+ return sql;
71
+ }
72
+ applyDefaultOrderBy(params) {
73
+ if (params.orderBy || !params.defaultOrderByColumns?.length) {
74
+ return params;
75
+ }
76
+ const quoted = params.defaultOrderByColumns.map((c) => this.quoteIdent(c)).join(', ');
77
+ return { ...params, orderBy: quoted };
78
+ }
79
+ mapObjectType(objectType) {
80
+ return objectType.toUpperCase() === 'VIEW' ? 'view' : 'table';
81
+ }
82
+ qualifyObject(dataSource, objectName) {
83
+ if (objectName.includes('.')) {
84
+ return objectName.split('.').map((p) => this.quoteIdent(p)).join('.');
85
+ }
86
+ if (dataSource.DefaultSchema) {
87
+ return `${this.quoteIdent(dataSource.DefaultSchema)}.${this.quoteIdent(objectName)}`;
88
+ }
89
+ return this.quoteIdent(objectName);
90
+ }
91
+ groupForeignKeys(fkRows) {
92
+ const byTable = new Map();
93
+ for (const r of fkRows) {
94
+ const constraints = byTable.get(r.table_name) ?? new Map();
95
+ const rel = constraints.get(r.constraint_name) ?? {
96
+ Name: r.constraint_name,
97
+ ReferencedObject: r.referenced_table,
98
+ ReferencedSchema: r.referenced_schema,
99
+ Columns: [],
100
+ };
101
+ rel.Columns.push({ Column: r.column_name, ReferencedColumn: r.referenced_column });
102
+ constraints.set(r.constraint_name, rel);
103
+ byTable.set(r.table_name, constraints);
104
+ }
105
+ const out = new Map();
106
+ for (const [table, constraints] of byTable) {
107
+ out.set(table, Array.from(constraints.values()));
108
+ }
109
+ return out;
110
+ }
111
+ }
112
+ //# sourceMappingURL=BaseSqlExternalDataSourceDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseSqlExternalDataSourceDriver.js","sourceRoot":"","sources":["../src/BaseSqlExternalDataSourceDriver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAiB1G,MAAM,OAAgB,+BAAuD,SAAQ,4BAAyC;IAUlH,aAAa;QACrB,OAAO,MAAM,CAAC;IAChB,CAAC;IASS,yBAAyB,CAAC,GAAW;QAC7C,yBAAyB,CAAC,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IACvF,CAAC;IAUS,yBAAyB,CAAC,GAAW;QAC7C,OAAO,GAAG,CAAC;IACb,CAAC;IASS,oBAAoB,CAC5B,WAA8C,EAC9C,WAAsC;QAItC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAA2C,EAAE,CAAC;QAC1D,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9D,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACjD,CAAC;IAOS,oBAAoB,CAAC,MAAc,EAAE,IAAyB;QACtE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,CAAC;IAC3D,CAAC;IAYS,eAAe,CAAC,OAA2B;QACnD,OAAO,EAAE,CAAC;IACZ,CAAC;IAGS,YAAY,CAAC,KAAa;QAClC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;IAC1C,CAAC;IAQS,yBAAyB,CAAC,MAA0B;QAC5D,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;IAChI,CAAC;IAQS,wBAAwB,CAAC,KAAa;QAC9C,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAQS,cAAc,CAAC,MAA0B;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC;QAI3D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5F,IAAI,MAAM,IAAI,WAAW,EAAE,CAAC;YAC1B,OAAO,IAAI,MAAM,SAAS,WAAW,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO,MAAM,IAAI,WAAW,CAAC;IAC/B,CAAC;IASS,aAAa,CAAC,MAAc,EAAE,MAA0B;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1C,OAAO,+BAA+B,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAClF,CAAC;IAUS,cAAc,CAAC,MAAc,EAAE,MAA0B;QACjE,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzG,MAAM,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,GAAG,GAAG,UAAU,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,GAAG,UAAU,SAAS,MAAM,EAAE,CAAC;QACxF,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,IAAI,UAAU,KAAK,EAAE,CAAC;QAC3B,CAAC;QACD,GAAG,IAAI,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAChD,OAAO,GAAG,CAAC;IACb,CAAC;IASS,mBAAmB,CAAC,MAA0B;QACtD,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,EAAE,CAAC;YAC5D,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtF,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAGS,aAAa,CAAC,UAAkB;QACxC,OAAO,UAAU,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,CAAC;IAGS,aAAa,CAAC,UAAsC,EAAE,UAAkB;QAChF,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,UAAU,CAAC,aAAa,EAAE,CAAC;YAC7B,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAOS,gBAAgB,CAAC,MAAuB;QAChD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmD,CAAC;QAC3E,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,IAAI,GAAG,EAAsC,CAAC;YAC/F,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI;gBAChD,IAAI,EAAE,CAAC,CAAC,eAAe;gBACvB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;gBACpC,gBAAgB,EAAE,CAAC,CAAC,iBAAiB;gBACrC,OAAO,EAAE,EAAE;aACZ,CAAC;YACF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACnF,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAwC,CAAC;QAC5D,KAAK,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,OAAO,EAAE,CAAC;YAC3C,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import { CompositeKey, EntityInfo, ExternalDataSourceReadRouter, ExternalSchemaDescriptor, IMetadataProvider, RunQueryParams, RunQueryResult, RunViewParams, RunViewResult, UserInfo } from "@memberjunction/core";
2
+ export declare class ExternalDataSourceReadRouterImpl extends ExternalDataSourceReadRouter {
3
+ RunViewExternal<T = unknown>(entity: EntityInfo, params: RunViewParams, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<RunViewResult<T>>;
4
+ LoadExternalRecord<T = unknown>(entity: EntityInfo, compositeKey: CompositeKey, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<RunViewResult<T>>;
5
+ RunQueryExternal(externalDataSourceID: string, queryID: string, queryName: string, sql: string, _params: RunQueryParams, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<RunQueryResult>;
6
+ GetCacheTTLSeconds(externalDataSourceID: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<number>;
7
+ IntrospectExternalSchema(externalDataSourceID: string, schemaName?: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<ExternalSchemaDescriptor>;
8
+ private resolveMaxRows;
9
+ private perSourceMaxRowLimit;
10
+ private failView;
11
+ private failQuery;
12
+ private errorText;
13
+ }
14
+ //# sourceMappingURL=ExternalDataSourceReadRouterImpl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalDataSourceReadRouterImpl.d.ts","sourceRoot":"","sources":["../src/ExternalDataSourceReadRouterImpl.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,EACb,aAAa,EACb,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAoC9B,qBACa,gCAAiC,SAAQ,4BAA4B;IACnE,eAAe,CAAC,CAAC,GAAG,OAAO,EACtC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,aAAa,EACrB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IA4Df,kBAAkB,CAAC,CAAC,GAAG,OAAO,EACzC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAkCf,gBAAgB,CAC3B,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,cAAc,EACvB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,cAAc,CAAC;IAwBb,kBAAkB,CAC7B,oBAAoB,EAAE,MAAM,EAC5B,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC;IAaL,wBAAwB,CACnC,oBAAoB,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,wBAAwB,CAAC;IAWpC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,SAAS;CAKlB"}
@@ -0,0 +1,163 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { RegisterClass } from "@memberjunction/global";
8
+ import { ExternalDataSourceReadRouter, } from "@memberjunction/core";
9
+ import { ExternalDataSourceRouter } from "./ExternalDataSourceRouter.js";
10
+ import { redactConnectionSecrets } from "./types.js";
11
+ const DEFAULT_EXTERNAL_CACHE_TTL_SECONDS = 300;
12
+ const DEFAULT_EXTERNAL_MAX_ROWS = 1000;
13
+ const HARD_MAX_EXTERNAL_ROWS = 50_000;
14
+ let ExternalDataSourceReadRouterImpl = class ExternalDataSourceReadRouterImpl extends ExternalDataSourceReadRouter {
15
+ async RunViewExternal(entity, params, contextUser, provider) {
16
+ const start = Date.now();
17
+ try {
18
+ const { driver, dataSource } = await ExternalDataSourceRouter.Instance.Resolve(entity.ExternalDataSourceID, contextUser, provider);
19
+ const offset = params.StartRow && params.StartRow > 0 ? params.StartRow : undefined;
20
+ const orderBy = params.OrderBy || undefined;
21
+ let defaultOrderByColumns;
22
+ if (!orderBy && offset != null) {
23
+ if (entity.PrimaryKeys.length > 0) {
24
+ defaultOrderByColumns = entity.PrimaryKeys.map((pk) => pk.Name);
25
+ }
26
+ else {
27
+ return this.failView(`External entity '${entity.Name}' has no primary key; offset pagination requires an explicit OrderBy for stable pages.`, Date.now() - start);
28
+ }
29
+ }
30
+ const viewParams = {
31
+ objectName: entity.ExternalObjectName || entity.BaseTable || entity.Name,
32
+ fields: params.Fields && params.Fields.length ? params.Fields : undefined,
33
+ filter: params.ExtraFilter || undefined,
34
+ orderBy,
35
+ defaultOrderByColumns,
36
+ maxRows: this.resolveMaxRows(params, entity, dataSource),
37
+ offset,
38
+ };
39
+ const res = await driver.RunView(dataSource, viewParams, contextUser);
40
+ if (!res.success) {
41
+ return this.failView(res.errorMessage ?? 'External RunView failed', Date.now() - start);
42
+ }
43
+ return {
44
+ Success: true,
45
+ Results: res.rows,
46
+ RowCount: res.rows.length,
47
+ TotalRowCount: res.totalRowCount ?? res.rows.length,
48
+ ExecutionTime: res.executionTimeMs,
49
+ ErrorMessage: '',
50
+ };
51
+ }
52
+ catch (e) {
53
+ return this.failView(this.errorText(e), Date.now() - start);
54
+ }
55
+ }
56
+ async LoadExternalRecord(entity, compositeKey, contextUser, provider) {
57
+ const start = Date.now();
58
+ try {
59
+ const { driver, dataSource } = await ExternalDataSourceRouter.Instance.Resolve(entity.ExternalDataSourceID, contextUser, provider);
60
+ const primaryKeys = compositeKey.KeyValuePairs.map((kv) => ({
61
+ name: kv.FieldName,
62
+ value: kv.Value,
63
+ }));
64
+ if (primaryKeys.length === 0) {
65
+ return this.failView(`Cannot load external record for '${entity.Name}': no primary key values were supplied.`, Date.now() - start);
66
+ }
67
+ const objectName = entity.ExternalObjectName || entity.BaseTable || entity.Name;
68
+ const row = await driver.LoadSingle(dataSource, objectName, primaryKeys, contextUser);
69
+ return {
70
+ Success: true,
71
+ Results: (row ? [row] : []),
72
+ RowCount: row ? 1 : 0,
73
+ TotalRowCount: row ? 1 : 0,
74
+ ExecutionTime: Date.now() - start,
75
+ ErrorMessage: '',
76
+ };
77
+ }
78
+ catch (e) {
79
+ return this.failView(this.errorText(e), Date.now() - start);
80
+ }
81
+ }
82
+ async RunQueryExternal(externalDataSourceID, queryID, queryName, sql, _params, contextUser, provider) {
83
+ const start = Date.now();
84
+ try {
85
+ const { driver, dataSource } = await ExternalDataSourceRouter.Instance.Resolve(externalDataSourceID, contextUser, provider);
86
+ const res = await driver.RunNativeQuery(dataSource, sql, undefined, contextUser);
87
+ if (!res.success) {
88
+ return this.failQuery(queryID, queryName, res.errorMessage ?? 'External query failed', Date.now() - start);
89
+ }
90
+ return {
91
+ Success: true,
92
+ QueryID: queryID,
93
+ QueryName: queryName,
94
+ Results: res.rows,
95
+ RowCount: res.rows.length,
96
+ TotalRowCount: res.rowCount,
97
+ ExecutionTime: res.executionTimeMs,
98
+ ErrorMessage: '',
99
+ };
100
+ }
101
+ catch (e) {
102
+ return this.failQuery(queryID, queryName, this.errorText(e), Date.now() - start);
103
+ }
104
+ }
105
+ async GetCacheTTLSeconds(externalDataSourceID, contextUser, provider) {
106
+ try {
107
+ const { dataSource } = await ExternalDataSourceRouter.Instance.Resolve(externalDataSourceID, contextUser, provider);
108
+ const ttl = dataSource.DefaultCacheTTLSeconds;
109
+ return typeof ttl === 'number' ? ttl : DEFAULT_EXTERNAL_CACHE_TTL_SECONDS;
110
+ }
111
+ catch {
112
+ return DEFAULT_EXTERNAL_CACHE_TTL_SECONDS;
113
+ }
114
+ }
115
+ async IntrospectExternalSchema(externalDataSourceID, schemaName, contextUser, provider) {
116
+ const { driver, dataSource } = await ExternalDataSourceRouter.Instance.Resolve(externalDataSourceID, contextUser, provider);
117
+ return driver.IntrospectSchema(dataSource, schemaName, contextUser);
118
+ }
119
+ resolveMaxRows(params, entity, dataSource) {
120
+ const requested = params.MaxRows && params.MaxRows > 0
121
+ ? params.MaxRows
122
+ : entity.UserViewMaxRows && entity.UserViewMaxRows > 0
123
+ ? entity.UserViewMaxRows
124
+ : DEFAULT_EXTERNAL_MAX_ROWS;
125
+ const ceiling = this.perSourceMaxRowLimit(dataSource) ?? HARD_MAX_EXTERNAL_ROWS;
126
+ return Math.min(requested, ceiling);
127
+ }
128
+ perSourceMaxRowLimit(dataSource) {
129
+ if (!dataSource.ConnectionConfig) {
130
+ return undefined;
131
+ }
132
+ try {
133
+ const cfg = JSON.parse(dataSource.ConnectionConfig);
134
+ return typeof cfg.maxRowLimit === 'number' && cfg.maxRowLimit > 0 ? cfg.maxRowLimit : undefined;
135
+ }
136
+ catch {
137
+ return undefined;
138
+ }
139
+ }
140
+ failView(errorMessage, executionTime) {
141
+ return { Success: false, Results: [], RowCount: 0, TotalRowCount: 0, ExecutionTime: executionTime, ErrorMessage: errorMessage };
142
+ }
143
+ failQuery(queryID, queryName, errorMessage, executionTime) {
144
+ return {
145
+ Success: false,
146
+ QueryID: queryID,
147
+ QueryName: queryName,
148
+ Results: [],
149
+ RowCount: 0,
150
+ TotalRowCount: 0,
151
+ ExecutionTime: executionTime,
152
+ ErrorMessage: errorMessage,
153
+ };
154
+ }
155
+ errorText(e) {
156
+ return redactConnectionSecrets(e instanceof Error ? e.message : String(e));
157
+ }
158
+ };
159
+ ExternalDataSourceReadRouterImpl = __decorate([
160
+ RegisterClass(ExternalDataSourceReadRouter, 'ExternalDataSourceReadRouter')
161
+ ], ExternalDataSourceReadRouterImpl);
162
+ export { ExternalDataSourceReadRouterImpl };
163
+ //# sourceMappingURL=ExternalDataSourceReadRouterImpl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalDataSourceReadRouterImpl.js","sourceRoot":"","sources":["../src/ExternalDataSourceReadRouterImpl.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAGL,4BAA4B,GAQ7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAA2D,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAG3G,MAAM,kCAAkC,GAAG,GAAG,CAAC;AAM/C,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAcvC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAW/B,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,4BAA4B;IACzE,KAAK,CAAC,eAAe,CAC1B,MAAkB,EAClB,MAAqB,EACrB,WAAsB,EACtB,QAA4B;QAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAC5E,MAAM,CAAC,oBAAoB,EAC3B,WAAW,EACX,QAAQ,CACT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YAQpF,MAAM,OAAO,GAAI,MAAM,CAAC,OAAkB,IAAI,SAAS,CAAC;YACxD,IAAI,qBAA2C,CAAC;YAChD,IAAI,CAAC,OAAO,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBAC/B,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClC,qBAAqB,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAClE,CAAC;qBAAM,CAAC;oBAGN,OAAO,IAAI,CAAC,QAAQ,CAClB,oBAAoB,MAAM,CAAC,IAAI,wFAAwF,EACvH,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CACnB,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,MAAM,UAAU,GAAuB;gBACrC,UAAU,EAAE,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI;gBACxE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACzE,MAAM,EAAG,MAAM,CAAC,WAAsB,IAAI,SAAS;gBACnD,OAAO;gBACP,qBAAqB;gBAIrB,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;gBACxD,MAAM;aACP,CAAC;YACF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAc,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;YACnF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC,QAAQ,CAAI,GAAG,CAAC,YAAY,IAAI,yBAAyB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;YAC7F,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,IAAI;gBAEb,OAAO,EAAE,GAAG,CAAC,IAAsB;gBACnC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;gBACzB,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM;gBACnD,aAAa,EAAE,GAAG,CAAC,eAAe;gBAClC,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,QAAQ,CAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,MAAkB,EAClB,YAA0B,EAC1B,WAAsB,EACtB,QAA4B;QAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAC5E,MAAM,CAAC,oBAAoB,EAC3B,WAAW,EACX,QAAQ,CACT,CAAC;YACF,MAAM,WAAW,GAA6B,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBACpF,IAAI,EAAE,EAAE,CAAC,SAAS;gBAClB,KAAK,EAAE,EAAE,CAAC,KAAK;aAChB,CAAC,CAAC,CAAC;YACJ,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC,QAAQ,CAClB,oCAAoC,MAAM,CAAC,IAAI,yCAAyC,EACxF,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CACnB,CAAC;YACJ,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC;YAChF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAc,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;YACnG,OAAO;gBACL,OAAO,EAAE,IAAI;gBAEb,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAmB;gBAC7C,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrB,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1B,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBACjC,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,QAAQ,CAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAC3B,oBAA4B,EAC5B,OAAe,EACf,SAAiB,EACjB,GAAW,EACX,OAAuB,EACvB,WAAsB,EACtB,QAA4B;QAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YAE5H,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAc,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YAC9F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,YAAY,IAAI,uBAAuB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;YAC7G,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,SAAS;gBACpB,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;gBACzB,aAAa,EAAE,GAAG,CAAC,QAAQ;gBAC3B,aAAa,EAAE,GAAG,CAAC,eAAe;gBAClC,YAAY,EAAE,EAAE;aACjB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,oBAA4B,EAC5B,WAAsB,EACtB,QAA4B;QAE5B,IAAI,CAAC;YACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YACpH,MAAM,GAAG,GAAG,UAAU,CAAC,sBAAsB,CAAC;YAE9C,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,kCAAkC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YAGP,OAAO,kCAAkC,CAAC;QAC5C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACnC,oBAA4B,EAC5B,UAAmB,EACnB,WAAsB,EACtB,QAA4B;QAE5B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC5H,OAAO,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACtE,CAAC;IAQO,cAAc,CAAC,MAAqB,EAAE,MAAkB,EAAE,UAAsC;QACtG,MAAM,SAAS,GACb,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC;YAClC,CAAC,CAAC,MAAM,CAAC,OAAO;YAChB,CAAC,CAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,GAAG,CAAC;gBACpD,CAAC,CAAC,MAAM,CAAC,eAAe;gBACxB,CAAC,CAAC,yBAAyB,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,IAAI,sBAAsB,CAAC;QAChF,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAGO,oBAAoB,CAAC,UAAsC;QACjE,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;YACjC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAA8B,CAAC;YACjF,OAAO,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QAClG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,QAAQ,CAAI,YAAoB,EAAE,aAAqB;QAC7D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IAClI,CAAC;IAEO,SAAS,CAAC,OAAe,EAAE,SAAiB,EAAE,YAAoB,EAAE,aAAqB;QAC/F,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,SAAS;YACpB,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,CAAC;YAChB,aAAa,EAAE,aAAa;YAC5B,YAAY,EAAE,YAAY;SAC3B,CAAC;IACJ,CAAC;IAEO,SAAS,CAAC,CAAU;QAG1B,OAAO,uBAAuB,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;CACF,CAAA;AAxNY,gCAAgC;IAD5C,aAAa,CAAC,4BAA4B,EAAE,8BAA8B,CAAC;GAC/D,gCAAgC,CAwN5C"}
@@ -0,0 +1,22 @@
1
+ import { BaseSingleton } from "@memberjunction/global";
2
+ import { BaseEntityEvent, IMetadataProvider, UserInfo } from "@memberjunction/core";
3
+ import { MJExternalDataSourceEntity, MJExternalDataSourceTypeEntity } from "@memberjunction/core-entities";
4
+ import { BaseExternalDataSourceDriver } from "./BaseExternalDataSourceDriver.js";
5
+ export interface ResolvedExternalDataSource {
6
+ dataSource: MJExternalDataSourceEntity;
7
+ dataSourceType: MJExternalDataSourceTypeEntity;
8
+ driver: BaseExternalDataSourceDriver;
9
+ }
10
+ export declare class ExternalDataSourceRouter extends BaseSingleton<ExternalDataSourceRouter> {
11
+ private driverCache;
12
+ private cacheInvalidationSubscribed;
13
+ protected constructor();
14
+ static get Instance(): ExternalDataSourceRouter;
15
+ Resolve(dataSourceId: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<ResolvedExternalDataSource>;
16
+ private createResolved;
17
+ private ensureCacheInvalidationSubscription;
18
+ protected handleEntityChange(event: BaseEntityEvent): Promise<void>;
19
+ ClearCache(dataSourceId?: string): Promise<void>;
20
+ private evictAndClose;
21
+ }
22
+ //# sourceMappingURL=ExternalDataSourceRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalDataSourceRouter.d.ts","sourceRoot":"","sources":["../src/ExternalDataSourceRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAyB,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAc,eAAe,EAAE,iBAAiB,EAAsB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACpH,OAAO,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAO9E,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,0BAA0B,CAAC;IACvC,cAAc,EAAE,8BAA8B,CAAC;IAC/C,MAAM,EAAE,4BAA4B,CAAC;CACtC;AAeD,qBAAa,wBAAyB,SAAQ,aAAa,CAAC,wBAAwB,CAAC;IAKnF,OAAO,CAAC,WAAW,CAA0D;IAG7E,OAAO,CAAC,2BAA2B,CAAS;IAE5C,SAAS;IAIT,WAAkB,QAAQ,IAAI,wBAAwB,CAErD;IAOY,OAAO,CAClB,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,0BAA0B,CAAC;YAkBxB,cAAc;IAyD5B,OAAO,CAAC,mCAAmC;cAkB3B,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB5D,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAS/C,aAAa;CAa5B"}
@@ -0,0 +1,103 @@
1
+ import { BaseSingleton, MJEventType, MJGlobal } from "@memberjunction/global";
2
+ import { BaseEntity, LogError, Metadata } from "@memberjunction/core";
3
+ import { BaseExternalDataSourceDriver } from "./BaseExternalDataSourceDriver.js";
4
+ const EXTERNAL_DATA_SOURCE_ENTITY = 'mj: external data sources';
5
+ const EXTERNAL_DATA_SOURCE_TYPE_ENTITY = 'mj: external data source types';
6
+ export class ExternalDataSourceRouter extends BaseSingleton {
7
+ constructor() {
8
+ super();
9
+ this.driverCache = new Map();
10
+ this.cacheInvalidationSubscribed = false;
11
+ }
12
+ static get Instance() {
13
+ return super.getInstance();
14
+ }
15
+ async Resolve(dataSourceId, contextUser, provider) {
16
+ this.ensureCacheInvalidationSubscription();
17
+ const existing = this.driverCache.get(dataSourceId);
18
+ if (existing) {
19
+ return existing;
20
+ }
21
+ const creating = this.createResolved(dataSourceId, contextUser, provider);
22
+ this.driverCache.set(dataSourceId, creating);
23
+ creating.catch(() => {
24
+ if (this.driverCache.get(dataSourceId) === creating) {
25
+ this.driverCache.delete(dataSourceId);
26
+ }
27
+ });
28
+ return creating;
29
+ }
30
+ async createResolved(dataSourceId, contextUser, provider) {
31
+ const md = provider ?? Metadata.Provider;
32
+ if (!md) {
33
+ throw new Error('No metadata provider available to resolve external data source.');
34
+ }
35
+ const dataSource = await md.GetEntityObject('MJ: External Data Sources', contextUser);
36
+ if (!(await dataSource.Load(dataSourceId))) {
37
+ throw new Error(`External data source '${dataSourceId}' not found.`);
38
+ }
39
+ if (dataSource.Status !== 'Active') {
40
+ throw new Error(`External data source '${dataSource.Name}' is ${dataSource.Status}; reads are disabled.`);
41
+ }
42
+ const dataSourceType = await md.GetEntityObject('MJ: External Data Source Types', contextUser);
43
+ if (!(await dataSourceType.Load(dataSource.TypeID))) {
44
+ throw new Error(`External data source type '${dataSource.TypeID}' (for '${dataSource.Name}') not found.`);
45
+ }
46
+ const cf = MJGlobal.Instance.ClassFactory;
47
+ if (!cf.GetRegistration(BaseExternalDataSourceDriver, dataSourceType.DriverClass)) {
48
+ throw new Error(`No external data source driver registered for DriverClass '${dataSourceType.DriverClass}' ` +
49
+ `(data source '${dataSource.Name}'). Ensure the driver package is installed and its @RegisterClass key matches.`);
50
+ }
51
+ const driver = cf.CreateInstance(BaseExternalDataSourceDriver, dataSourceType.DriverClass);
52
+ return { dataSource, dataSourceType, driver };
53
+ }
54
+ ensureCacheInvalidationSubscription() {
55
+ if (this.cacheInvalidationSubscribed) {
56
+ return;
57
+ }
58
+ this.cacheInvalidationSubscribed = true;
59
+ MJGlobal.Instance.GetEventListener(false).subscribe((event) => {
60
+ if (event.event === MJEventType.ComponentEvent && event.eventCode === BaseEntity.BaseEventCode) {
61
+ this.handleEntityChange(event.args).catch((e) => LogError(e));
62
+ }
63
+ });
64
+ }
65
+ async handleEntityChange(event) {
66
+ if (!event) {
67
+ return;
68
+ }
69
+ const entityName = (event.baseEntity?.EntityInfo?.Name ?? event.entityName ?? '').toLowerCase().trim();
70
+ if (entityName === EXTERNAL_DATA_SOURCE_TYPE_ENTITY) {
71
+ await this.ClearCache();
72
+ return;
73
+ }
74
+ if (entityName === EXTERNAL_DATA_SOURCE_ENTITY) {
75
+ const id = event.type !== 'remote-invalidate'
76
+ ? event.baseEntity?.ID
77
+ : undefined;
78
+ await (id ? this.ClearCache(id) : this.ClearCache());
79
+ }
80
+ }
81
+ async ClearCache(dataSourceId) {
82
+ if (dataSourceId) {
83
+ await this.evictAndClose(dataSourceId);
84
+ }
85
+ else {
86
+ await Promise.all(Array.from(this.driverCache.keys()).map((id) => this.evictAndClose(id)));
87
+ }
88
+ }
89
+ async evictAndClose(dataSourceId) {
90
+ const entry = this.driverCache.get(dataSourceId);
91
+ this.driverCache.delete(dataSourceId);
92
+ if (!entry) {
93
+ return;
94
+ }
95
+ try {
96
+ const { driver } = await entry;
97
+ await driver.CloseConnection(dataSourceId);
98
+ }
99
+ catch {
100
+ }
101
+ }
102
+ }
103
+ //# sourceMappingURL=ExternalDataSourceRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalDataSourceRouter.js","sourceRoot":"","sources":["../src/ExternalDataSourceRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export * from "./types.js";
2
+ export * from "./temporal.js";
3
+ export * from "./sqlReadOnlyScreen.js";
4
+ export * from "./BaseExternalDataSourceDriver.js";
5
+ export * from "./BaseSqlExternalDataSourceDriver.js";
6
+ export * from "./ExternalDataSourceRouter.js";
7
+ export * from "./ExternalDataSourceReadRouterImpl.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAG3C,cAAc,oCAAoC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./types.js";
2
+ export * from "./temporal.js";
3
+ export * from "./sqlReadOnlyScreen.js";
4
+ export * from "./BaseExternalDataSourceDriver.js";
5
+ export * from "./BaseSqlExternalDataSourceDriver.js";
6
+ export * from "./ExternalDataSourceRouter.js";
7
+ export * from "./ExternalDataSourceReadRouterImpl.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAG3C,cAAc,oCAAoC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type SqlDialectKey = "sqlserver" | "ansi";
2
+ export declare function assertReadOnlyNativeQuery(sql: string, dialectKey: SqlDialectKey): void;
3
+ export declare function assertReadOnlyClause(clause: string, dialectKey: SqlDialectKey, kind: "where" | "orderby"): void;
4
+ //# sourceMappingURL=sqlReadOnlyScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlReadOnlyScreen.d.ts","sourceRoot":"","sources":["../src/sqlReadOnlyScreen.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,MAAM,CAAC;AA6EjD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,GAAG,IAAI,CAqDtF;AAmBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CA6B/G"}
@@ -0,0 +1,75 @@
1
+ import { SQLParser } from "@memberjunction/sql-parser";
2
+ import { SQLServerDialect, PostgreSQLDialect } from "@memberjunction/sql-dialect";
3
+ function dialectFor(key) {
4
+ return key === "sqlserver" ? new SQLServerDialect() : new PostgreSQLDialect();
5
+ }
6
+ const WRITE_NODE_TYPES = new Set([
7
+ "insert", "update", "delete", "merge", "replace", "drop", "create", "alter", "truncate",
8
+ "rename", "call", "exec", "execute", "grant", "revoke", "use", "load", "copy", "do",
9
+ ]);
10
+ function astContainsWriteNode(node) {
11
+ if (!node || typeof node !== "object") {
12
+ return false;
13
+ }
14
+ if (Array.isArray(node)) {
15
+ return node.some(astContainsWriteNode);
16
+ }
17
+ const obj = node;
18
+ const type = obj.type;
19
+ if (typeof type === "string" && WRITE_NODE_TYPES.has(type.toLowerCase())) {
20
+ return true;
21
+ }
22
+ return Object.values(obj).some(astContainsWriteNode);
23
+ }
24
+ function isSingleTypedStatement(ast) {
25
+ const statements = Array.isArray(ast) ? ast : [ast];
26
+ if (statements.length !== 1) {
27
+ return false;
28
+ }
29
+ const stmt = statements[0];
30
+ return !!stmt && typeof stmt === "object" && typeof stmt.type === "string";
31
+ }
32
+ export function assertReadOnlyNativeQuery(sql, dialectKey) {
33
+ const dialect = dialectFor(dialectKey);
34
+ if (SQLParser.HasStackedStatements(sql, dialect)) {
35
+ throw new Error("External native query rejected: multiple statements are not allowed against a read-only external data source.");
36
+ }
37
+ const leadingTrimmed = sql.replace(/^(?:\s+|--[^\n]*\n?|\/\*[\s\S]*?\*\/)+/, "");
38
+ if (/^(grant|revoke|deny)\b/i.test(leadingTrimmed)) {
39
+ throw new Error("External native query rejected: permission (GRANT/REVOKE/DENY) statements are not permitted — External Data Sources are read-only.");
40
+ }
41
+ const parser = new SQLParser(sql, dialect);
42
+ if (!parser.IsValid) {
43
+ throw new Error("External native query rejected: SQL could not be parsed/validated as read-only — refusing under uncertainty (External Data Sources are read-only).");
44
+ }
45
+ if (parser.HasWriteStatement) {
46
+ throw new Error("External native query rejected: write/DDL statements are not permitted — External Data Sources are read-only.");
47
+ }
48
+ if (parser.StatementKind === "select-into") {
49
+ throw new Error("External native query rejected: SELECT ... INTO creates a table — External Data Sources are read-only.");
50
+ }
51
+ const ast = parser.AST;
52
+ if (astContainsWriteNode(ast)) {
53
+ throw new Error("External native query rejected: a write/DDL statement nested in a CTE or subquery is not permitted — External Data Sources are read-only.");
54
+ }
55
+ if (!isSingleTypedStatement(ast)) {
56
+ throw new Error("External native query rejected: only a single, well-formed read statement is allowed — refusing under uncertainty (External Data Sources are read-only).");
57
+ }
58
+ }
59
+ export function assertReadOnlyClause(clause, dialectKey, kind) {
60
+ if (/--|\/\*|\*\//.test(clause)) {
61
+ throw new Error(`External ${kind} clause rejected: SQL comment markers are not allowed.`);
62
+ }
63
+ if (/;/.test(clause)) {
64
+ throw new Error(`External ${kind} clause rejected: statement separators are not allowed.`);
65
+ }
66
+ const wrapped = kind === "where"
67
+ ? `SELECT 1 FROM __mj_clause_screen WHERE (${clause})`
68
+ : `SELECT 1 FROM __mj_clause_screen ORDER BY ${clause}`;
69
+ const dialect = dialectFor(dialectKey);
70
+ const parser = new SQLParser(wrapped, dialect);
71
+ if (!parser.IsValid || parser.HasWriteStatement || parser.StatementKind !== "select") {
72
+ throw new Error(`External ${kind} clause rejected: not a safe read-only ${kind} fragment — refusing under uncertainty.`);
73
+ }
74
+ }
75
+ //# sourceMappingURL=sqlReadOnlyScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlReadOnlyScreen.js","sourceRoot":"","sources":["../src/sqlReadOnlyScreen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const ISO_8601_DATETIME_RE: RegExp;
2
+ export declare function isIso8601DateTime(value: string): boolean;
3
+ export declare function iso8601Zone(value: string): string | null;
4
+ export declare function parseIso8601AsUtc(value: string): Date | null;
5
+ //# sourceMappingURL=temporal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.d.ts","sourceRoot":"","sources":["../src/temporal.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,oBAAoB,QAA2E,CAAC;AAG7G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxD;AAQD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAO5D"}
@@ -0,0 +1,17 @@
1
+ export const ISO_8601_DATETIME_RE = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(\.\d+)?(Z|[+-]\d{2}:?\d{2})?$/;
2
+ export function isIso8601DateTime(value) {
3
+ return ISO_8601_DATETIME_RE.test(value);
4
+ }
5
+ export function iso8601Zone(value) {
6
+ const m = ISO_8601_DATETIME_RE.exec(value);
7
+ return m ? (m[4] ?? null) : null;
8
+ }
9
+ export function parseIso8601AsUtc(value) {
10
+ if (!isIso8601DateTime(value)) {
11
+ return null;
12
+ }
13
+ const normalized = iso8601Zone(value) ? value : `${value}Z`;
14
+ const d = new Date(normalized);
15
+ return Number.isNaN(d.getTime()) ? null : d;
16
+ }
17
+ //# sourceMappingURL=temporal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temporal.js","sourceRoot":"","sources":["../src/temporal.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,oBAAoB,GAAG,wEAAwE,CAAC;AAG7G,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1C,CAAC;AAGD,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC;AAQD,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;IAC5D,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,48 @@
1
+ export type ExternalRow = Record<string, unknown>;
2
+ export interface ExternalConnectionTestResult {
3
+ success: boolean;
4
+ message: string;
5
+ testedAt: Date;
6
+ latencyMs?: number;
7
+ }
8
+ export interface ExternalViewParams {
9
+ objectName: string;
10
+ fields?: string[];
11
+ filter?: string;
12
+ orderBy?: string;
13
+ defaultOrderByColumns?: readonly string[];
14
+ maxRows?: number;
15
+ offset?: number;
16
+ incrementalSince?: {
17
+ Field: string;
18
+ Value: string;
19
+ };
20
+ }
21
+ export interface ExternalViewResult<TRow extends ExternalRow = ExternalRow> {
22
+ success: boolean;
23
+ rows: TRow[];
24
+ totalRowCount?: number;
25
+ errorMessage?: string;
26
+ executionTimeMs: number;
27
+ }
28
+ export interface ExternalFkRow {
29
+ constraint_name: string;
30
+ table_name: string;
31
+ column_name: string;
32
+ referenced_table: string;
33
+ referenced_schema: string;
34
+ referenced_column: string;
35
+ }
36
+ export interface ExternalQueryParameter {
37
+ name: string;
38
+ value: string | number | boolean | Date | null;
39
+ }
40
+ export interface ExternalQueryResult<TRow extends ExternalRow = ExternalRow> {
41
+ success: boolean;
42
+ rows: TRow[];
43
+ rowCount: number;
44
+ errorMessage?: string;
45
+ executionTimeMs: number;
46
+ }
47
+ export declare function redactConnectionSecrets(message: string): string;
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAGlD,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,IAAI,CAAC;IAEf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,MAAM,WAAW,kBAAkB;IAEjC,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,MAAM,CAAC;IAQjB,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE1C,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAShB,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAGD,MAAM,WAAW,kBAAkB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,EAAE,CAAC;IAEb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAQD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAGD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;CAChD;AAGD,MAAM,WAAW,mBAAmB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW;IACzE,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,EAAE,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AASD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ export function redactConnectionSecrets(message) {
2
+ return message.replace(/([a-z][a-z0-9+.-]*:\/\/)[^@/\s]+@/gi, '$1***@');
3
+ }
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA6GA,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,OAAO,OAAO,CAAC,OAAO,CAAC,qCAAqC,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,36 @@
1
1
  {
2
2
  "name": "@memberjunction/external-data-sources",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @memberjunction/external-data-sources",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
3
+ "version": "5.45.1",
4
+ "description": "MemberJunction: External Data Sources live, runtime-proxied read access to remote data systems (Snowflake, Oracle, MongoDB, external SQL Server / PostgreSQL / MySQL) via pluggable @RegisterClass drivers.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "/dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc && tsc-alias -f",
13
+ "test": "vitest run"
14
+ },
15
+ "author": "MemberJunction.com",
16
+ "license": "ISC",
17
+ "dependencies": {
18
+ "@memberjunction/core": "5.45.1",
19
+ "@memberjunction/global": "5.45.1",
20
+ "@memberjunction/core-entities": "5.45.1",
21
+ "@memberjunction/credentials": "5.45.1",
22
+ "@memberjunction/sql-parser": "5.45.1",
23
+ "@memberjunction/sql-dialect": "5.45.1"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "24.10.11",
27
+ "tsc-alias": "^1.8.16",
28
+ "ts-node-dev": "^2.0.0",
29
+ "vitest": "^3.1.1",
30
+ "typescript": "^5.9.3"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/MemberJunction/MJ"
35
+ }
10
36
  }
package/README.md DELETED
@@ -1,45 +0,0 @@
1
- # @memberjunction/external-data-sources
2
-
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@memberjunction/external-data-sources`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**