@memberjunction/server 6.1.0-edge.1 → 6.1.0-edge.3
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.
- package/LICENSE +180 -4
- package/dist/auth/AuthProviderCatalogRouter.d.ts +31 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.js +69 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -0
- package/dist/auth/AuthProviderEngine.d.ts +96 -0
- package/dist/auth/AuthProviderEngine.d.ts.map +1 -0
- package/dist/auth/AuthProviderEngine.js +245 -0
- package/dist/auth/AuthProviderEngine.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +11 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +65 -18
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +64 -1
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +117 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +1 -1
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.js +1 -1
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -35
- package/dist/config.js.map +1 -1
- package/dist/context.js +2 -2
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +540 -1595
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2755 -16857
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +20 -4
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +58 -21
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +31 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +183 -54
- package/dist/index.js.map +1 -1
- package/dist/integration/RSUProgressBridge.d.ts +83 -0
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -0
- package/dist/integration/RSUProgressBridge.js +230 -0
- package/dist/integration/RSUProgressBridge.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +52 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.js +50 -0
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -0
- package/dist/logging/secretRedactor.d.ts +9 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +39 -0
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/middleware/BaseServerMiddleware.d.ts +5 -0
- package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
- package/dist/middleware/BaseServerMiddleware.js +5 -0
- package/dist/middleware/BaseServerMiddleware.js.map +1 -1
- package/dist/providerConfigUnits.d.ts +20 -0
- package/dist/providerConfigUnits.d.ts.map +1 -0
- package/dist/providerConfigUnits.js +22 -0
- package/dist/providerConfigUnits.js.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.js +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +12 -0
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.js +1 -1
- package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +34 -4
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +218 -28
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +85 -3
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +302 -82
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +5 -4
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +29 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +12 -3
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +33 -14
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +5 -0
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +20 -7
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +2 -2
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +18 -0
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +75 -0
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +19 -17
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +66 -67
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/currentUserRoles.d.ts +19 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -0
- package/dist/resolvers/currentUserRoles.js +36 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -0
- package/dist/rest/MediaAccessKeys.d.ts +17 -0
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +42 -1
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +3 -2
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +83 -2
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +49 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +130 -44
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +1 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +90 -0
- package/dist/rest/UploadTokenManager.d.ts.map +1 -0
- package/dist/rest/UploadTokenManager.js +156 -0
- package/dist/rest/UploadTokenManager.js.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts +26 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js +55 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts +48 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.js +132 -0
- package/dist/services/IntegrationSyncWorkerService.js.map +1 -0
- package/dist/services/ScheduledJobsService.js +1 -1
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.d.ts +0 -10
- package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +37 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +34 -0
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphActionRunner.js +95 -0
- package/dist/services/TaskGraphActionRunner.js.map +1 -0
- package/dist/services/TaskGraphAgentRunner.d.ts +20 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +53 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +12 -1
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/TaskGraphPromptRunner.d.ts +31 -0
- package/dist/services/TaskGraphPromptRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphPromptRunner.js +134 -0
- package/dist/services/TaskGraphPromptRunner.js.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.js +1 -1
- package/dist/telephony/RingCentralTelephonyService.js.map +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js.map +1 -1
- package/dist/telephony/VonageTelephonyRouter.js +1 -1
- package/dist/telephony/VonageTelephonyRouter.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +91 -91
- package/src/__tests__/APIKeyScopeAuth.test.ts +475 -0
- package/src/__tests__/AuthProviderEngine.test.ts +278 -0
- package/src/__tests__/EntityCRUDHandler.test.ts +378 -0
- package/src/__tests__/IntegrationSyncWorkerService.test.ts +275 -0
- package/src/__tests__/OAuthCallbackHandler.openRedirect.test.ts +117 -0
- package/src/__tests__/OAuthCallbackHandler.xss.test.ts +4 -1
- package/src/__tests__/RESTEndpointHandler.test.ts +672 -0
- package/src/__tests__/RSUProgressBridge.test.ts +250 -0
- package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +1 -1
- package/src/__tests__/ResolverBase.frozenRecordMapping.test.ts +133 -0
- package/src/__tests__/ResolverBase.transportMapping.test.ts +289 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +114 -0
- package/src/__tests__/SessionManager.test.ts +1 -1
- package/src/__tests__/UserResolver.currentUser.test.ts +87 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +277 -0
- package/src/__tests__/WidgetSessionService.test.ts +1 -1
- package/src/__tests__/config-units.test.ts +74 -0
- package/src/__tests__/databaseAbstraction.test.ts +1 -1
- package/src/__tests__/initializeProviders.refresh.test.ts +146 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +1 -1
- package/src/__tests__/mjapi-bootstrap.test.ts +0 -6
- package/src/__tests__/newUsers.test.ts +726 -0
- package/src/__tests__/resolverBase.rls.test.ts +3 -0
- package/src/__tests__/secretRedactor.failOpen.test.ts +135 -0
- package/src/__tests__/uploadTokenManager.test.ts +159 -0
- package/src/__tests__/widgetGuestElevation.test.ts +1 -1
- package/src/auth/AuthProviderCatalogRouter.ts +76 -0
- package/src/auth/AuthProviderEngine.ts +253 -0
- package/src/auth/exampleNewUserSubClass.ts +1 -1
- package/src/auth/index.ts +69 -21
- package/src/auth/initializeProviders.ts +128 -7
- package/src/auth/magicLink/MagicLinkService.ts +1 -1
- package/src/auth/newUsers.ts +1 -1
- package/src/config.ts +55 -36
- package/src/context.ts +2 -2
- package/src/generated/generated.ts +2038 -10529
- package/src/generic/ResolverBase.ts +63 -21
- package/src/generic/RunViewResolver.ts +31 -0
- package/src/index.ts +199 -56
- package/src/integration/RSUProgressBridge.ts +248 -0
- package/src/integration/SchemaRefreshLaunch.ts +77 -0
- package/src/logging/secretRedactor.ts +43 -0
- package/src/middleware/BaseServerMiddleware.ts +5 -0
- package/src/providerConfigUnits.ts +21 -0
- package/src/realtimeWidget/WidgetSessionService.ts +1 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -1
- package/src/resolvers/ActionResolver.ts +13 -0
- package/src/resolvers/ComponentRegistryResolver.ts +1 -1
- package/src/resolvers/EntityPermissionResolver.ts +1 -1
- package/src/resolvers/FileResolver.ts +200 -40
- package/src/resolvers/IntegrationDiscoveryResolver.ts +328 -70
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +25 -11
- package/src/resolvers/QuerySystemUserResolver.ts +28 -13
- package/src/resolvers/RealtimeClientSessionResolver.ts +13 -0
- package/src/resolvers/RunAIAgentResolver.ts +21 -6
- package/src/resolvers/SearchEntitiesResolver.ts +1 -1
- package/src/resolvers/SqlLoggingConfigResolver.ts +1 -2
- package/src/resolvers/SyncRolesUsersResolver.ts +2 -2
- package/src/resolvers/TaskGraphFrameResolver.ts +67 -0
- package/src/resolvers/UserFavoriteResolver.ts +1 -1
- package/src/resolvers/UserResolver.ts +99 -60
- package/src/resolvers/currentUserRoles.ts +47 -0
- package/src/rest/MediaAccessKeys.ts +47 -1
- package/src/rest/MediaStreamHandler.ts +98 -3
- package/src/rest/OAuthCallbackHandler.ts +150 -42
- package/src/rest/SignatureWebhookHandler.ts +1 -1
- package/src/rest/UploadTokenManager.ts +211 -0
- package/src/services/DurableEntityActionTaskSubmitter.ts +78 -0
- package/src/services/IntegrationSyncWorkerService.ts +141 -0
- package/src/services/ScheduledJobsService.ts +1 -1
- package/src/services/StartTaskGraphDispatcher.ts +38 -1
- package/src/services/TaskGraphActionRunner.ts +99 -0
- package/src/services/TaskGraphAgentRunner.ts +58 -1
- package/src/services/TaskGraphContinuationDeliverer.ts +11 -1
- package/src/services/TaskGraphPromptRunner.ts +144 -0
- package/src/telephony/RingCentralTelephonyService.ts +1 -1
- package/src/telephony/TwilioTelephonyRouter.ts +1 -1
- package/src/telephony/VonageTelephonyRouter.ts +1 -1
- package/src/types.ts +6 -0
|
@@ -20,7 +20,8 @@ import {
|
|
|
20
20
|
UserInfo,
|
|
21
21
|
} from '@memberjunction/core';
|
|
22
22
|
import { MJAuditLogEntity, MJErrorLogEntity, MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
23
|
-
import { SQLServerDataProvider
|
|
23
|
+
import { SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';
|
|
24
|
+
import { UserCache } from '@memberjunction/generic-database-provider';
|
|
24
25
|
import { PubSubEngine, AuthorizationError } from 'type-graphql';
|
|
25
26
|
import { GraphQLError } from 'graphql';
|
|
26
27
|
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
@@ -62,16 +63,28 @@ export class ResolverBase {
|
|
|
62
63
|
* - AllowDecryptInAPI=false + SendEncryptedValue=true: Keep encrypted ciphertext
|
|
63
64
|
* - AllowDecryptInAPI=false + SendEncryptedValue=false: Replace with sentinel
|
|
64
65
|
*
|
|
66
|
+
* Returns a COPY — `dataObject` is never written to. Callers routinely pass rows straight
|
|
67
|
+
* from `findBy`/`RunView`, which are the server cache's own objects held by reference, and
|
|
68
|
+
* `LocalCacheManager` deep-freezes them. Renaming in place therefore threw
|
|
69
|
+
* `Cannot add property _mj__CreatedAt, object is not extensible` on every `UserByEmail` /
|
|
70
|
+
* `UserByID` / `UserByEmployeeID` call and on every generated single-record resolver whose
|
|
71
|
+
* entity has caching enabled. (Before the freeze it did something worse but quieter: it
|
|
72
|
+
* rewrote the cached row's keys, so later readers were served transport-shaped rows that
|
|
73
|
+
* `BaseEntity.SetMany` rejects.) Copying here fixes every call site at once and makes the
|
|
74
|
+
* hazard unreachable for future ones.
|
|
75
|
+
*
|
|
65
76
|
* @param entityName - The entity name
|
|
66
|
-
* @param dataObject - The data object with field values
|
|
77
|
+
* @param dataObject - The data object with field values. Not modified.
|
|
67
78
|
* @param contextUser - Optional user context for decryption (required for encrypted fields)
|
|
68
|
-
* @returns
|
|
79
|
+
* @returns A new object in transport shape, or null when there is nothing to map
|
|
69
80
|
*/
|
|
70
81
|
protected async MapFieldNamesToCodeNames(entityName: string, dataObject: any, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<any> {
|
|
71
82
|
// Return null for empty objects (e.g. when no rows found due to RLS filtering)
|
|
72
83
|
if (!dataObject || Object.keys(dataObject).length === 0) {
|
|
73
84
|
return null;
|
|
74
85
|
}
|
|
86
|
+
// Shallow copy up front so every write below lands on our object, never the caller's.
|
|
87
|
+
dataObject = { ...dataObject };
|
|
75
88
|
|
|
76
89
|
// for the given entity name provided, check to see if there are any fields
|
|
77
90
|
// where the code name is different from the field name, and for just those
|
|
@@ -184,14 +197,21 @@ export class ResolverBase {
|
|
|
184
197
|
return true;
|
|
185
198
|
}
|
|
186
199
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Array form of {@link MapFieldNamesToCodeNames}. Returns a NEW array of NEW objects; neither
|
|
202
|
+
* the input array nor its rows are modified. Both matter: the cache freezes the array as well
|
|
203
|
+
* as the rows it contains, so collecting the mapped copies (rather than mapping in place and
|
|
204
|
+
* returning the original) is what makes this safe on cache-served input.
|
|
205
|
+
*/
|
|
206
|
+
protected async ArrayMapFieldNamesToCodeNames(entityName: string, dataObjectArray: any[], contextUser?: UserInfo, provider?: IMetadataProvider): Promise<any[]> {
|
|
207
|
+
if (!dataObjectArray || dataObjectArray.length === 0) {
|
|
208
|
+
return dataObjectArray;
|
|
193
209
|
}
|
|
194
|
-
|
|
210
|
+
const mapped: any[] = [];
|
|
211
|
+
for (const element of dataObjectArray) {
|
|
212
|
+
mapped.push(await this.MapFieldNamesToCodeNames(entityName, element, contextUser, provider));
|
|
213
|
+
}
|
|
214
|
+
return mapped;
|
|
195
215
|
}
|
|
196
216
|
|
|
197
217
|
/**
|
|
@@ -388,7 +408,8 @@ export class ResolverBase {
|
|
|
388
408
|
viewInput.AfterKey
|
|
389
409
|
? CompositeKey.FromKeyValuePairs((viewInput.AfterKey as { KeyValuePairs: { FieldName: string; Value: string }[] }).KeyValuePairs)
|
|
390
410
|
: undefined,
|
|
391
|
-
viewInput.BypassCache
|
|
411
|
+
viewInput.BypassCache,
|
|
412
|
+
viewInput.DataSource
|
|
392
413
|
);
|
|
393
414
|
}
|
|
394
415
|
else {
|
|
@@ -431,7 +452,8 @@ export class ResolverBase {
|
|
|
431
452
|
viewInput.StartRow,
|
|
432
453
|
viewInput.Aggregates,
|
|
433
454
|
undefined,
|
|
434
|
-
viewInput.BypassCache
|
|
455
|
+
viewInput.BypassCache,
|
|
456
|
+
viewInput.DataSource
|
|
435
457
|
);
|
|
436
458
|
} catch (err) {
|
|
437
459
|
console.log(err);
|
|
@@ -477,7 +499,8 @@ export class ResolverBase {
|
|
|
477
499
|
viewInput.StartRow,
|
|
478
500
|
viewInput.Aggregates,
|
|
479
501
|
undefined,
|
|
480
|
-
viewInput.BypassCache
|
|
502
|
+
viewInput.BypassCache,
|
|
503
|
+
viewInput.DataSource
|
|
481
504
|
);
|
|
482
505
|
} catch (err) {
|
|
483
506
|
console.log(err);
|
|
@@ -551,6 +574,7 @@ export class ResolverBase {
|
|
|
551
574
|
userPayload,
|
|
552
575
|
aggregates: viewInput.Aggregates,
|
|
553
576
|
bypassCache: viewInput.BypassCache,
|
|
577
|
+
dataSource: viewInput.DataSource,
|
|
554
578
|
});
|
|
555
579
|
} catch (err) {
|
|
556
580
|
LogError(err);
|
|
@@ -747,7 +771,8 @@ export class ResolverBase {
|
|
|
747
771
|
startRow: number | undefined,
|
|
748
772
|
aggregates?: AggregateExpression[],
|
|
749
773
|
afterKey?: CompositeKey,
|
|
750
|
-
bypassCache?: boolean
|
|
774
|
+
bypassCache?: boolean,
|
|
775
|
+
dataSource?: 'Live' | 'Materialized'
|
|
751
776
|
) {
|
|
752
777
|
try {
|
|
753
778
|
if (!viewInfo || !userPayload) return null;
|
|
@@ -817,6 +842,7 @@ export class ResolverBase {
|
|
|
817
842
|
ResultType: rt,
|
|
818
843
|
Aggregates: aggregates,
|
|
819
844
|
BypassCache: bypassCache,
|
|
845
|
+
DataSource: dataSource,
|
|
820
846
|
},
|
|
821
847
|
user
|
|
822
848
|
);
|
|
@@ -826,12 +852,27 @@ export class ResolverBase {
|
|
|
826
852
|
LogStatus(`[ResolverBase] RunView result aggregate info: entityName=${viewInfo.Entity}, hasAggregateResults=${!!result?.AggregateResults}, aggregateResultCount=${result?.AggregateResults?.length || 0}, aggregateExecutionTime=${result?.AggregateExecutionTime}, aggregateResults=${JSON.stringify(result?.AggregateResults)}`);
|
|
827
853
|
}
|
|
828
854
|
|
|
829
|
-
// Process results for GraphQL transport
|
|
855
|
+
// Process results for GraphQL transport.
|
|
856
|
+
//
|
|
857
|
+
// Map onto COPIES, never in place. `FieldMapper.MapFields` renames keys by
|
|
858
|
+
// mutating (`obj[mapped] = obj[k]; delete obj[k]`), and these rows are the
|
|
859
|
+
// provider's own result objects — which the server cache holds BY REFERENCE
|
|
860
|
+
// under a reference-sharing storage provider. Mapping them in place rewrote
|
|
861
|
+
// `__mj_CreatedAt` to the transport alias `_mj__CreatedAt` inside the live
|
|
862
|
+
// cache, and because that cache is process-wide, one GraphQL response made
|
|
863
|
+
// every later read hand back transport-shaped rows that `BaseEntity.SetMany`
|
|
864
|
+
// rejects. `ArrayFilterEncryptedFieldsForAPI` mutates too, so it must also
|
|
865
|
+
// see the copies. (FileResolver already maps a spread copy.)
|
|
866
|
+
//
|
|
867
|
+
// These copies are LOAD-BEARING, not merely defensive: LocalCacheManager now
|
|
868
|
+
// deep-freezes cached rows (see ILocalStorageProvider.SharesReferences), so
|
|
869
|
+
// mapping in place would throw rather than silently corrupt. `{ ...r }` is a
|
|
870
|
+
// SHALLOW copy, which is sufficient here because the only post-map mutators
|
|
871
|
+
// rename top-level keys and redact scalar fields — and the cache's freeze is
|
|
872
|
+
// deep, so a nested value can no longer be reached through the copy either.
|
|
830
873
|
const mapper = new FieldMapper();
|
|
831
874
|
if (result?.Success && result.Results?.length) {
|
|
832
|
-
|
|
833
|
-
mapper.MapFields(r);
|
|
834
|
-
}
|
|
875
|
+
result.Results = result.Results.map(r => mapper.MapFields({ ...r }));
|
|
835
876
|
// Filter encrypted fields before sending to API client
|
|
836
877
|
await this.ArrayFilterEncryptedFieldsForAPI(
|
|
837
878
|
viewInfo.Entity,
|
|
@@ -937,6 +978,7 @@ export class ResolverBase {
|
|
|
937
978
|
ResultType: rt,
|
|
938
979
|
Aggregates: param.aggregates,
|
|
939
980
|
BypassCache: param.bypassCache,
|
|
981
|
+
DataSource: param.dataSource,
|
|
940
982
|
});
|
|
941
983
|
}
|
|
942
984
|
|
|
@@ -948,9 +990,9 @@ export class ResolverBase {
|
|
|
948
990
|
for (let i = 0; i < runViewResults.length; i++) {
|
|
949
991
|
const runViewResult = runViewResults[i];
|
|
950
992
|
if (runViewResult?.Success && runViewResult.Results?.length) {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
}
|
|
993
|
+
// Copy-then-map, same reason as the single-view path above: these rows
|
|
994
|
+
// are cache-held references and MapFields renames keys in place.
|
|
995
|
+
runViewResult.Results = runViewResult.Results.map(r => mapper.MapFields({ ...r }));
|
|
954
996
|
// Filter encrypted fields before sending to API client
|
|
955
997
|
// Use the corresponding param's entity name
|
|
956
998
|
const entityName = params[i]?.viewInfo?.Entity;
|
|
@@ -177,6 +177,13 @@ export class RunViewByIDInput {
|
|
|
177
177
|
'Optional, when true bypasses ALL server-side caching for this view run — the pre-check cache lookup is skipped and the result is not stored in the cache. Use for maintenance/audit queries that must see true database state, or to force-refresh views whose filters reference rows the server cache invalidator cannot follow (e.g., cross-entity subqueries against vwListDetails).',
|
|
178
178
|
})
|
|
179
179
|
BypassCache?: boolean;
|
|
180
|
+
|
|
181
|
+
@Field(() => String, {
|
|
182
|
+
nullable: true,
|
|
183
|
+
description:
|
|
184
|
+
"Optional source-of-truth selector for a base-view materialization: 'Live' (default) reads the entity's live base view; 'Materialized' reads its materialized snapshot wrapper view (materialized_vw<CodeName>). Only request 'Materialized' for an entity that actually has a base-view materialization: it resolves to the wrapper view by naming convention with NO existence check or fallback, so requesting it for a non-materialized entity targets a view that does not exist and the query errors.",
|
|
185
|
+
})
|
|
186
|
+
DataSource?: 'Live' | 'Materialized';
|
|
180
187
|
}
|
|
181
188
|
|
|
182
189
|
@InputType()
|
|
@@ -291,6 +298,13 @@ export class RunViewByNameInput {
|
|
|
291
298
|
'Optional, when true bypasses ALL server-side caching for this view run — the pre-check cache lookup is skipped and the result is not stored in the cache. Use for maintenance/audit queries that must see true database state, or to force-refresh views whose filters reference rows the server cache invalidator cannot follow (e.g., cross-entity subqueries against vwListDetails).',
|
|
292
299
|
})
|
|
293
300
|
BypassCache?: boolean;
|
|
301
|
+
|
|
302
|
+
@Field(() => String, {
|
|
303
|
+
nullable: true,
|
|
304
|
+
description:
|
|
305
|
+
"Optional source-of-truth selector for a base-view materialization: 'Live' (default) reads the entity's live base view; 'Materialized' reads its materialized snapshot wrapper view (materialized_vw<CodeName>). Only request 'Materialized' for an entity that actually has a base-view materialization: it resolves to the wrapper view by naming convention with NO existence check or fallback, so requesting it for a non-materialized entity targets a view that does not exist and the query errors.",
|
|
306
|
+
})
|
|
307
|
+
DataSource?: 'Live' | 'Materialized';
|
|
294
308
|
}
|
|
295
309
|
|
|
296
310
|
@InputType()
|
|
@@ -391,6 +405,13 @@ export class RunDynamicViewInput {
|
|
|
391
405
|
'Optional, when true bypasses ALL server-side caching for this view run — the pre-check cache lookup is skipped and the result is not stored in the cache. Use for maintenance/audit queries that must see true database state, or to force-refresh views whose filters reference rows the server cache invalidator cannot follow (e.g., cross-entity subqueries against vwListDetails).',
|
|
392
406
|
})
|
|
393
407
|
BypassCache?: boolean;
|
|
408
|
+
|
|
409
|
+
@Field(() => String, {
|
|
410
|
+
nullable: true,
|
|
411
|
+
description:
|
|
412
|
+
"Optional source-of-truth selector for a base-view materialization: 'Live' (default) reads the entity's live base view; 'Materialized' reads its materialized snapshot wrapper view (materialized_vw<CodeName>). Only request 'Materialized' for an entity that actually has a base-view materialization: it resolves to the wrapper view by naming convention with NO existence check or fallback, so requesting it for a non-materialized entity targets a view that does not exist and the query errors.",
|
|
413
|
+
})
|
|
414
|
+
DataSource?: 'Live' | 'Materialized';
|
|
394
415
|
}
|
|
395
416
|
|
|
396
417
|
@InputType()
|
|
@@ -520,6 +541,13 @@ export class RunViewGenericInput {
|
|
|
520
541
|
'Optional, when true bypasses ALL server-side caching for this view run — the pre-check cache lookup is skipped and the result is not stored in the cache. Use for maintenance/audit queries that must see true database state, or to force-refresh views whose filters reference rows the server cache invalidator cannot follow (e.g., cross-entity subqueries against vwListDetails).',
|
|
521
542
|
})
|
|
522
543
|
BypassCache?: boolean;
|
|
544
|
+
|
|
545
|
+
@Field(() => String, {
|
|
546
|
+
nullable: true,
|
|
547
|
+
description:
|
|
548
|
+
"Optional source-of-truth selector for a base-view materialization: 'Live' (default) reads the entity's live base view; 'Materialized' reads its materialized snapshot wrapper view (materialized_vw<CodeName>). Only request 'Materialized' for an entity that actually has a base-view materialization: it resolves to the wrapper view by naming convention with NO existence check or fallback, so requesting it for a non-materialized entity targets a view that does not exist and the query errors.",
|
|
549
|
+
})
|
|
550
|
+
DataSource?: 'Live' | 'Materialized';
|
|
523
551
|
}
|
|
524
552
|
|
|
525
553
|
//****************************************************************************
|
|
@@ -1082,6 +1110,9 @@ export class RunViewResolver extends ResolverBase {
|
|
|
1082
1110
|
// Forward the aggregate request to the engine (B40) — omitted here as well as in the
|
|
1083
1111
|
// client's input map, so aggregates never reached InternalRunView on this transport.
|
|
1084
1112
|
Aggregates: item.params.Aggregates,
|
|
1113
|
+
// DataSource must be forwarded on this transport too (same as the InternalRunView/RunViews maps):
|
|
1114
|
+
// otherwise a CacheLocal batch's DataSource:'Materialized' request silently reads the live view.
|
|
1115
|
+
DataSource: item.params.DataSource,
|
|
1085
1116
|
AfterKey: item.params.AfterKey
|
|
1086
1117
|
? CompositeKey.FromKeyValuePairs(item.params.AfterKey.KeyValuePairs)
|
|
1087
1118
|
: undefined,
|