@memberjunction/core 6.2.0-edge.5 → 6.2.0-edge.7

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 (148) hide show
  1. package/dist/generic/BaseEntitySaveQueue.d.ts +15 -0
  2. package/dist/generic/BaseEntitySaveQueue.d.ts.map +1 -1
  3. package/dist/generic/BaseEntitySaveQueue.js +21 -0
  4. package/dist/generic/BaseEntitySaveQueue.js.map +1 -1
  5. package/dist/generic/EntityFieldRules.d.ts.map +1 -1
  6. package/dist/generic/EntityFieldRules.js +1 -0
  7. package/dist/generic/EntityFieldRules.js.map +1 -1
  8. package/dist/generic/alternateBaseViews.d.ts +119 -0
  9. package/dist/generic/alternateBaseViews.d.ts.map +1 -0
  10. package/dist/generic/alternateBaseViews.js +223 -0
  11. package/dist/generic/alternateBaseViews.js.map +1 -0
  12. package/dist/generic/baseEngine.d.ts +171 -17
  13. package/dist/generic/baseEngine.d.ts.map +1 -1
  14. package/dist/generic/baseEngine.js +722 -117
  15. package/dist/generic/baseEngine.js.map +1 -1
  16. package/dist/generic/baseEngineRegistry.d.ts.map +1 -1
  17. package/dist/generic/baseEngineRegistry.js +2 -1
  18. package/dist/generic/baseEngineRegistry.js.map +1 -1
  19. package/dist/generic/baseEntity.d.ts +216 -21
  20. package/dist/generic/baseEntity.d.ts.map +1 -1
  21. package/dist/generic/baseEntity.js +969 -100
  22. package/dist/generic/baseEntity.js.map +1 -1
  23. package/dist/generic/baseRemotableOperation.d.ts +95 -6
  24. package/dist/generic/baseRemotableOperation.d.ts.map +1 -1
  25. package/dist/generic/baseRemotableOperation.js +112 -8
  26. package/dist/generic/baseRemotableOperation.js.map +1 -1
  27. package/dist/generic/contextTokens.d.ts +136 -0
  28. package/dist/generic/contextTokens.d.ts.map +1 -0
  29. package/dist/generic/contextTokens.js +319 -0
  30. package/dist/generic/contextTokens.js.map +1 -0
  31. package/dist/generic/databaseProviderBase.d.ts +103 -5
  32. package/dist/generic/databaseProviderBase.d.ts.map +1 -1
  33. package/dist/generic/databaseProviderBase.js +381 -52
  34. package/dist/generic/databaseProviderBase.js.map +1 -1
  35. package/dist/generic/embeddedRecord.d.ts +6 -0
  36. package/dist/generic/embeddedRecord.d.ts.map +1 -1
  37. package/dist/generic/embeddedRecord.js +15 -1
  38. package/dist/generic/embeddedRecord.js.map +1 -1
  39. package/dist/generic/entityCompanion.d.ts +7 -0
  40. package/dist/generic/entityCompanion.d.ts.map +1 -1
  41. package/dist/generic/entityCompanion.js +8 -0
  42. package/dist/generic/entityCompanion.js.map +1 -1
  43. package/dist/generic/entityInfo.d.ts +234 -9
  44. package/dist/generic/entityInfo.d.ts.map +1 -1
  45. package/dist/generic/entityInfo.js +592 -77
  46. package/dist/generic/entityInfo.js.map +1 -1
  47. package/dist/generic/entityValueFieldSecurity.d.ts +139 -0
  48. package/dist/generic/entityValueFieldSecurity.d.ts.map +1 -0
  49. package/dist/generic/entityValueFieldSecurity.js +250 -0
  50. package/dist/generic/entityValueFieldSecurity.js.map +1 -0
  51. package/dist/generic/externalDataSourceReadRouter.d.ts +10 -0
  52. package/dist/generic/externalDataSourceReadRouter.d.ts.map +1 -1
  53. package/dist/generic/externalDataSourceReadRouter.js +12 -0
  54. package/dist/generic/externalDataSourceReadRouter.js.map +1 -1
  55. package/dist/generic/fieldSecuritySQLGate.d.ts +359 -0
  56. package/dist/generic/fieldSecuritySQLGate.d.ts.map +1 -0
  57. package/dist/generic/fieldSecuritySQLGate.js +902 -0
  58. package/dist/generic/fieldSecuritySQLGate.js.map +1 -0
  59. package/dist/generic/indexRestrictedFields.d.ts +47 -0
  60. package/dist/generic/indexRestrictedFields.d.ts.map +1 -0
  61. package/dist/generic/indexRestrictedFields.js +129 -0
  62. package/dist/generic/indexRestrictedFields.js.map +1 -0
  63. package/dist/generic/interfaces.d.ts +64 -2
  64. package/dist/generic/interfaces.d.ts.map +1 -1
  65. package/dist/generic/interfaces.js.map +1 -1
  66. package/dist/generic/listMembershipFilter.d.ts +5 -0
  67. package/dist/generic/listMembershipFilter.d.ts.map +1 -0
  68. package/dist/generic/listMembershipFilter.js +23 -0
  69. package/dist/generic/listMembershipFilter.js.map +1 -0
  70. package/dist/generic/localCacheManager.d.ts +126 -14
  71. package/dist/generic/localCacheManager.d.ts.map +1 -1
  72. package/dist/generic/localCacheManager.js +348 -48
  73. package/dist/generic/localCacheManager.js.map +1 -1
  74. package/dist/generic/logging.d.ts.map +1 -1
  75. package/dist/generic/logging.js +7 -1
  76. package/dist/generic/logging.js.map +1 -1
  77. package/dist/generic/metadata.d.ts +3 -2
  78. package/dist/generic/metadata.d.ts.map +1 -1
  79. package/dist/generic/metadata.js +5 -2
  80. package/dist/generic/metadata.js.map +1 -1
  81. package/dist/generic/platformSQL.d.ts +54 -0
  82. package/dist/generic/platformSQL.d.ts.map +1 -1
  83. package/dist/generic/platformSQL.js +55 -0
  84. package/dist/generic/platformSQL.js.map +1 -1
  85. package/dist/generic/providerBase.d.ts +408 -57
  86. package/dist/generic/providerBase.d.ts.map +1 -1
  87. package/dist/generic/providerBase.js +1051 -310
  88. package/dist/generic/providerBase.js.map +1 -1
  89. package/dist/generic/queryInfo.d.ts +13 -0
  90. package/dist/generic/queryInfo.d.ts.map +1 -1
  91. package/dist/generic/queryInfo.js +13 -0
  92. package/dist/generic/queryInfo.js.map +1 -1
  93. package/dist/generic/queryInfoInterfaces.d.ts +8 -0
  94. package/dist/generic/queryInfoInterfaces.d.ts.map +1 -1
  95. package/dist/generic/queryTemplateContext.d.ts +49 -0
  96. package/dist/generic/queryTemplateContext.d.ts.map +1 -0
  97. package/dist/generic/queryTemplateContext.js +113 -0
  98. package/dist/generic/queryTemplateContext.js.map +1 -0
  99. package/dist/generic/recordChangeFieldSecurity.d.ts.map +1 -1
  100. package/dist/generic/recordChangeFieldSecurity.js +13 -2
  101. package/dist/generic/recordChangeFieldSecurity.js.map +1 -1
  102. package/dist/generic/relatedRecordCollection.d.ts +18 -0
  103. package/dist/generic/relatedRecordCollection.d.ts.map +1 -1
  104. package/dist/generic/relatedRecordCollection.js +55 -7
  105. package/dist/generic/relatedRecordCollection.js.map +1 -1
  106. package/dist/generic/remoteOperationDispatch.d.ts.map +1 -1
  107. package/dist/generic/remoteOperationDispatch.js +14 -2
  108. package/dist/generic/remoteOperationDispatch.js.map +1 -1
  109. package/dist/generic/runQuery.d.ts +42 -0
  110. package/dist/generic/runQuery.d.ts.map +1 -1
  111. package/dist/generic/runQuery.js +14 -0
  112. package/dist/generic/runQuery.js.map +1 -1
  113. package/dist/generic/runQuerySQLFilterImplementations.d.ts +33 -6
  114. package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -1
  115. package/dist/generic/runQuerySQLFilterImplementations.js +119 -29
  116. package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -1
  117. package/dist/generic/saveEntityGraphOperation.d.ts.map +1 -1
  118. package/dist/generic/saveEntityGraphOperation.js +3 -0
  119. package/dist/generic/saveEntityGraphOperation.js.map +1 -1
  120. package/dist/generic/securityInfo.d.ts +11 -0
  121. package/dist/generic/securityInfo.d.ts.map +1 -1
  122. package/dist/generic/securityInfo.js +15 -0
  123. package/dist/generic/securityInfo.js.map +1 -1
  124. package/dist/generic/telemetryManager.d.ts +9 -0
  125. package/dist/generic/telemetryManager.d.ts.map +1 -1
  126. package/dist/generic/telemetryManager.js +5 -1
  127. package/dist/generic/telemetryManager.js.map +1 -1
  128. package/dist/generic/transportError.d.ts +41 -0
  129. package/dist/generic/transportError.d.ts.map +1 -0
  130. package/dist/generic/transportError.js +167 -0
  131. package/dist/generic/transportError.js.map +1 -0
  132. package/dist/generic/util.d.ts +12 -0
  133. package/dist/generic/util.d.ts.map +1 -1
  134. package/dist/generic/util.js +52 -3
  135. package/dist/generic/util.js.map +1 -1
  136. package/dist/index.d.ts +9 -0
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +9 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/views/runView.d.ts +102 -0
  141. package/dist/views/runView.d.ts.map +1 -1
  142. package/dist/views/runView.js +40 -0
  143. package/dist/views/runView.js.map +1 -1
  144. package/dist/views/viewProperties.d.ts +55 -0
  145. package/dist/views/viewProperties.d.ts.map +1 -0
  146. package/dist/views/viewProperties.js +258 -0
  147. package/dist/views/viewProperties.js.map +1 -0
  148. package/package.json +3 -3
@@ -0,0 +1,250 @@
1
+ import { CurrentFieldSecurityGeneration, FieldSecurityError, ReadableFieldsTransportKey } from './entityInfo.js';
2
+ import { RecordChangeFieldSecurityProjector } from './recordChangeFieldSecurity.js';
3
+ /**
4
+ * Returns `values` without the keys `denied` names, matched case- and whitespace-insensitively.
5
+ *
6
+ * `denied` is a denied-field set as {@link EntityInfo.GetDeniedReadFields} builds it: lowercased,
7
+ * holding both the `Name` and the `CodeName` of every denied field. Because the match is against
8
+ * the row's OWN keys, a row keyed by either spelling, in any case, is narrowed.
9
+ *
10
+ * Returns a shallow COPY when a key was removed and the original object by reference when none
11
+ * was, so a row that is already narrow costs nothing. The input is never modified, which is what
12
+ * makes this safe on frozen, shared cache rows.
13
+ */
14
+ export function OmitDeniedFieldKeys(values, denied) {
15
+ if (!values || typeof values !== 'object' || !denied || denied.size === 0) {
16
+ return values;
17
+ }
18
+ const source = values;
19
+ let copy = null;
20
+ for (const key of Object.keys(source)) {
21
+ if (!denied.has(key.trim().toLowerCase())) {
22
+ continue;
23
+ }
24
+ copy ??= { ...source };
25
+ delete copy[key];
26
+ }
27
+ return (copy ?? values);
28
+ }
29
+ /**
30
+ * Returns `values` without the keys `entity`'s own user may not read, for a payload built from
31
+ * that entity and sent to another tier (a graph save, a companion's wire form).
32
+ *
33
+ * The object already holds no denied value (its hydration points and `NewRecord` leave such
34
+ * fields not loaded), so `GetAll()` normally omits them by itself. This is the backstop for a key
35
+ * put back on the object without the readability check, which `SetMany` permits: the receiving
36
+ * tier refuses a restricted caller's input that names a field they may not read, so sending one
37
+ * fails the whole save.
38
+ *
39
+ * Returns the original object when nothing was removed, and a shallow copy otherwise.
40
+ */
41
+ export function OmitFieldsUnreadableByActiveUser(entity, values) {
42
+ if (!values || typeof values !== 'object') {
43
+ return values;
44
+ }
45
+ const source = values;
46
+ let copy = null;
47
+ for (const key of Object.keys(source)) {
48
+ if (entity.IsFieldReadableByActiveUser(key)) {
49
+ continue;
50
+ }
51
+ copy ??= { ...source };
52
+ delete copy[key];
53
+ }
54
+ return (copy ?? values);
55
+ }
56
+ /**
57
+ * The denied-READ set for `user` on `entityInfo`, or null when field security does not apply:
58
+ * it applies to neither the entity nor an IS-A ancestor, there is no user, or the user is denied nothing.
59
+ */
60
+ function deniedReadFieldsFor(entityInfo, user) {
61
+ if (!entityInfo.FieldLevelSecurityApplies) {
62
+ return null;
63
+ }
64
+ const denied = entityInfo.GetDeniedReadFields(user);
65
+ return denied.size > 0 ? denied : null;
66
+ }
67
+ /** The names of the fields a caller with this denied set may read, for {@link ReadableFieldsTransportKey}. */
68
+ function readableFieldNames(entityInfo, denied) {
69
+ return entityInfo.Fields
70
+ .filter((f) => !denied.has(f.Name.trim().toLowerCase()))
71
+ .map((f) => f.Name);
72
+ }
73
+ /** Field-security narrowing for one row: omission plus the optional readable-fields marker. */
74
+ function narrowRow(row, denied, readable) {
75
+ const narrowed = OmitDeniedFieldKeys(row, denied);
76
+ if (!readable) {
77
+ return narrowed;
78
+ }
79
+ const withMarker = narrowed === row
80
+ ? { ...row }
81
+ : narrowed;
82
+ withMarker[ReadableFieldsTransportKey] = readable;
83
+ return withMarker;
84
+ }
85
+ /**
86
+ * Projects a plain object of entity field values down to what `user` may READ.
87
+ *
88
+ * **The one output projection every transport uses**, so that no transport can apply only half
89
+ * of it. Three things are applied, matching what the GraphQL resolvers' field mapping does:
90
+ *
91
+ * 1. **Denied read fields are omitted**, under both the `Name` and `CodeName` spellings and in any
92
+ * case, because callers reach here with rows keyed either way. Omitted rather than nulled:
93
+ * a null is indistinguishable from a real value.
94
+ * 2. **{@link ReadableFieldsTransportKey}** is appended when `includeReadableFields` is set and
95
+ * the caller is denied something (see the option).
96
+ * 3. **The Record Changes payload projection**, which is keyed on the entity each ROW is about
97
+ * rather than on the entity being queried. `MJ: Record Changes` normally has field security
98
+ * off, so step 1 is a no-op for it, while its payload columns carry other entities' values.
99
+ *
100
+ * An entity object built for a restricted user does not hold denied values in the first place,
101
+ * so on that path this is defence in depth. It is the primary control for values that did not
102
+ * come from such an object: a system-identity load, a raw provider row, or a cached payload.
103
+ *
104
+ * Returns a COPY whenever anything changed, and the original object by reference when nothing
105
+ * did, so unrestricted callers pay nothing and frozen cache rows are never written to.
106
+ *
107
+ * @param provider Metadata source, used to resolve the per-row target entity for Record Changes.
108
+ * @param entityInfo The entity the values belong to. When absent the values are returned unchanged.
109
+ * @param values The field values. Never modified.
110
+ * **Fails open on a missing user.** With no `user` the values are returned unchanged, full width.
111
+ * That is deliberate: a browser or other single-user client has no per-call user to pass, and
112
+ * server-internal code running without one is trusted with full values. It also means a
113
+ * server-side transport that forgets to pass the caller sends everything, so every request-path
114
+ * caller must pass the requesting user.
115
+ *
116
+ * @param user The caller. When absent the values are returned unchanged (see above).
117
+ * @param options See {@link ProjectEntityValuesOptions}.
118
+ */
119
+ export function ProjectEntityValuesForUser(provider, entityInfo, values, user, options) {
120
+ if (!values || typeof values !== 'object' || !entityInfo || !user) {
121
+ return values;
122
+ }
123
+ const projected = ProjectEntityValueRowsForUser(provider, entityInfo, [values], user, options);
124
+ return projected?.[0] ?? values;
125
+ }
126
+ /**
127
+ * Array form of {@link ProjectEntityValuesForUser}. The denied set, the readable-fields list and
128
+ * the Record Changes projector are each built ONCE for the whole set: the projector memoizes its
129
+ * per-entity lookups for its own lifetime, and a denied set walks every field of the entity, so
130
+ * building either per row turns a per-request cost into a per-row one.
131
+ *
132
+ * Returns the ORIGINAL array when no row needed changing. Fails open on a missing user, as
133
+ * {@link ProjectEntityValuesForUser} does.
134
+ */
135
+ export function ProjectEntityValueRowsForUser(provider, entityInfo, rows, user, options) {
136
+ if (!rows?.length || !entityInfo || !user) {
137
+ return rows;
138
+ }
139
+ const denied = deniedReadFieldsFor(entityInfo, user);
140
+ const isRecordChanges = RecordChangeFieldSecurityProjector.IsRecordChangesEntity(entityInfo);
141
+ if (!denied && !isRecordChanges) {
142
+ return rows;
143
+ }
144
+ let projected = rows;
145
+ if (denied) {
146
+ const readable = options?.includeReadableFields ? readableFieldNames(entityInfo, denied) : null;
147
+ projected = rows.map((row) => narrowRow(row, denied, readable));
148
+ }
149
+ if (isRecordChanges) {
150
+ projected = new RecordChangeFieldSecurityProjector(provider, user).ProjectRows(projected);
151
+ }
152
+ return projected.some((row, i) => row !== rows[i]) ? projected : rows;
153
+ }
154
+ /**
155
+ * Keys a transport adds to client input that are not entity fields, and that
156
+ * {@link AssertClientInputWritableForUser} therefore must not treat as unknown.
157
+ */
158
+ export const ClientInputTransportKeys = [
159
+ 'OldValues___',
160
+ ReadableFieldsTransportKey,
161
+ 'RestoreContext___',
162
+ 'CloneContext___',
163
+ // The companion payload key, spelled out rather than imported: the module that defines it
164
+ // imports BaseEntity, which imports this module, and this array is built at load time.
165
+ 'Companions___',
166
+ '__typename',
167
+ ];
168
+ /**
169
+ * The wording for refusing a key in client input. Deliberately the SAME for a key that names a
170
+ * field the caller cannot read and a key that names no field at all, so the refusal cannot be
171
+ * used to learn which columns exist.
172
+ */
173
+ export function FieldSecurityClientInputMessage(key, entityName) {
174
+ return `Field '${key}' cannot be written on entity '${entityName}'.`;
175
+ }
176
+ /** {@link ClientInputTransportKeys}, lowercased and trimmed, as {@link AssertClientInputWritableForUser} matches them. */
177
+ const NORMALIZED_CLIENT_INPUT_TRANSPORT_KEYS = new Set(ClientInputTransportKeys.map((k) => k.trim().toLowerCase()));
178
+ const knownFieldKeysCache = new WeakMap();
179
+ /** Every key that names a field of `entityInfo` or of an IS-A ancestor, lowercased, by Name and CodeName. */
180
+ function knownFieldKeys(entityInfo) {
181
+ const fields = entityInfo.Fields;
182
+ const chain = entityInfo.ParentChain ?? [];
183
+ const generation = CurrentFieldSecurityGeneration();
184
+ const memo = knownFieldKeysCache.get(entityInfo);
185
+ if (memo && memo.fields === fields && memo.chain === chain && memo.generation === generation) {
186
+ return memo.keys;
187
+ }
188
+ const keys = new Set();
189
+ for (const entity of [entityInfo, ...chain]) {
190
+ for (const f of entity.Fields) {
191
+ keys.add(f.Name.trim().toLowerCase());
192
+ keys.add(f.CodeName.trim().toLowerCase());
193
+ }
194
+ }
195
+ knownFieldKeysCache.set(entityInfo, { fields, chain, generation, keys });
196
+ return keys;
197
+ }
198
+ /** Whether `normalized` is a transport key, built in or one the caller added. */
199
+ function isAllowedTransportKey(normalized, additional) {
200
+ return NORMALIZED_CLIENT_INPUT_TRANSPORT_KEYS.has(normalized) || (additional?.has(normalized) ?? false);
201
+ }
202
+ /**
203
+ * The write-side gate for transports that apply client input with `SetMany`: throws a
204
+ * {@link FieldSecurityError} when the input carries a key the caller may not send.
205
+ *
206
+ * Applies only to a caller who is denied at least one field on the entity. For that caller, a key
207
+ * is refused when it names a field they cannot READ, or when it names no field at all; both get
208
+ * the identical {@link FieldSecurityClientInputMessage}. Treating unknown keys the same way is
209
+ * what keeps the refusal from revealing whether a column exists: refusing only denied keys would
210
+ * answer "does `Salary` exist?" for any key a caller cares to try.
211
+ *
212
+ * Rejection rather than silent removal: a client holding a denied value can only have fabricated
213
+ * it, because no response it received contained one, so there is no legitimate request to save.
214
+ *
215
+ * Keys in {@link ClientInputTransportKeys}, and any in `options.additionalAllowedKeys`, are
216
+ * accepted. Matching is case- and whitespace-insensitive, by Name and CodeName, like `SetMany`.
217
+ * Callers who are denied nothing, or input for an entity without field security, are unaffected,
218
+ * so `SetMany`'s ordinary handling of unknown keys still applies to them.
219
+ *
220
+ * @param entityInfo The entity the input will be applied to.
221
+ * **Fails open on a missing user.** With no `user` the gate does nothing, so server-internal
222
+ * code, and a client with no per-call user, are unaffected. A server-side transport applying a
223
+ * request's input must therefore pass the requesting user, or nothing is checked.
224
+ *
225
+ * @param values The client input. Never modified.
226
+ * @param user The caller. When absent the gate does nothing (see above).
227
+ * @param options See {@link ClientInputGateOptions}.
228
+ */
229
+ export function AssertClientInputWritableForUser(entityInfo, values, user, options) {
230
+ if (!values || typeof values !== 'object' || !entityInfo || !user) {
231
+ return;
232
+ }
233
+ const denied = deniedReadFieldsFor(entityInfo, user);
234
+ if (!denied) {
235
+ return;
236
+ }
237
+ const extra = options?.additionalAllowedKeys;
238
+ const additional = extra && extra.length > 0 ? new Set(extra.map((k) => k.trim().toLowerCase())) : null;
239
+ const known = knownFieldKeys(entityInfo);
240
+ for (const key of Object.keys(values)) {
241
+ const normalized = key.trim().toLowerCase();
242
+ if (isAllowedTransportKey(normalized, additional)) {
243
+ continue;
244
+ }
245
+ if (denied.has(normalized) || !known.has(normalized)) {
246
+ throw new FieldSecurityError(key, entityInfo.Name, FieldSecurityClientInputMessage(key, entityInfo.Name));
247
+ }
248
+ }
249
+ }
250
+ //# sourceMappingURL=entityValueFieldSecurity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entityValueFieldSecurity.js","sourceRoot":"","sources":["../../src/generic/entityValueFieldSecurity.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,16 @@ export declare abstract class ExternalDataSourceReadRouter {
50
50
  * source, so this is cheap to call on the read hot path.
51
51
  */
52
52
  abstract GetCacheTTLSeconds(externalDataSourceID: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<number>;
53
+ /**
54
+ * The key of the SQL dialect an external data source speaks (as `@memberjunction/sql-dialect`
55
+ * registers it: `'mysql'`, `'snowflake'`, `'databricks'`, …), so a query on that source renders
56
+ * its template values with the source's own literal rules. Null for a source with no SQL
57
+ * dialect (a document store) or when the router cannot tell; the query then renders with the
58
+ * calling provider's platform.
59
+ *
60
+ * The base implementation returns null; the External Data Sources engine overrides it.
61
+ */
62
+ GetQueryDialectKey(_externalDataSourceID: string, _contextUser?: UserInfo, _provider?: IMetadataProvider): Promise<string | null>;
53
63
  /**
54
64
  * Introspect the schema of an external data source (its tables/views/collections and their
55
65
  * columns), delegating to the resolved driver's `IntrospectSchema`. Used by CodeGen to
@@ -1 +1 @@
1
- {"version":3,"file":"externalDataSourceReadRouter.d.ts","sourceRoot":"","sources":["../../src/generic/externalDataSourceReadRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE;;;;;;;;;;;;;;;GAeG;AACH,8BAAsB,4BAA4B;IAChD,oFAAoF;aACpE,eAAe,CAAC,CAAC,GAAG,OAAO,EACzC,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;IAE5B;;;;;;;OAOG;aACa,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAC5C,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;IAE5B;;;;;OAKG;aACa,gBAAgB,CAC9B,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,cAAc,CAAC;IAE1B;;;;;;;;OAQG;aACa,kBAAkB,CAChC,oBAAoB,EAAE,MAAM,EAC5B,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC;IAElB;;;;;;;OAOG;aACa,wBAAwB,CACtC,oBAAoB,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,wBAAwB,CAAC;CACrC"}
1
+ {"version":3,"file":"externalDataSourceReadRouter.d.ts","sourceRoot":"","sources":["../../src/generic/externalDataSourceReadRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE;;;;;;;;;;;;;;;GAeG;AACH,8BAAsB,4BAA4B;IAChD,oFAAoF;aACpE,eAAe,CAAC,CAAC,GAAG,OAAO,EACzC,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;IAE5B;;;;;;;OAOG;aACa,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAC5C,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;IAE5B;;;;;OAKG;aACa,gBAAgB,CAC9B,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,cAAc,CAAC;IAE1B;;;;;;;;OAQG;aACa,kBAAkB,CAChC,oBAAoB,EAAE,MAAM,EAC5B,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,MAAM,CAAC;IAElB;;;;;;;;OAQG;IACU,kBAAkB,CAC7B,qBAAqB,EAAE,MAAM,EAC7B,YAAY,CAAC,EAAE,QAAQ,EACvB,SAAS,CAAC,EAAE,iBAAiB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB;;;;;;;OAOG;aACa,wBAAwB,CACtC,oBAAoB,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,wBAAwB,CAAC;CACrC"}
@@ -15,5 +15,17 @@
15
15
  * clear error rather than fall through to MJ-DB SQL generation.
16
16
  */
17
17
  export class ExternalDataSourceReadRouter {
18
+ /**
19
+ * The key of the SQL dialect an external data source speaks (as `@memberjunction/sql-dialect`
20
+ * registers it: `'mysql'`, `'snowflake'`, `'databricks'`, …), so a query on that source renders
21
+ * its template values with the source's own literal rules. Null for a source with no SQL
22
+ * dialect (a document store) or when the router cannot tell; the query then renders with the
23
+ * calling provider's platform.
24
+ *
25
+ * The base implementation returns null; the External Data Sources engine overrides it.
26
+ */
27
+ async GetQueryDialectKey(_externalDataSourceID, _contextUser, _provider) {
28
+ return null;
29
+ }
18
30
  }
19
31
  //# sourceMappingURL=externalDataSourceReadRouter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"externalDataSourceReadRouter.js","sourceRoot":"","sources":["../../src/generic/externalDataSourceReadRouter.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAgB,4BAA4B;CAqEjD"}
1
+ {"version":3,"file":"externalDataSourceReadRouter.js","sourceRoot":"","sources":["../../src/generic/externalDataSourceReadRouter.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAgB,4BAA4B;IAuDhD;;;;;;;;OAQG;IACI,KAAK,CAAC,kBAAkB,CAC7B,qBAA6B,EAC7B,YAAuB,EACvB,SAA6B;QAE7B,OAAO,IAAI,CAAC;IACd,CAAC;CAgBF"}