@memberjunction/server 6.1.4 → 6.2.0-edge.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.d.ts +2 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionManager.js +2 -2
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
- package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
- package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +5 -1
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +2 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +20 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +20 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +8 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +21 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +65 -51
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +2 -2
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +2 -2
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
- package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.js +61 -61
- package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +12 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +4 -4
- package/dist/auth/principals.d.ts +2 -0
- package/dist/auth/principals.d.ts.map +1 -1
- package/dist/auth/principals.js +6 -2
- package/dist/auth/principals.js.map +1 -1
- package/dist/cache.d.ts +2 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +3 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +293 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +20 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -19
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.d.ts +2 -0
- package/dist/directives/Public.d.ts.map +1 -1
- package/dist/directives/Public.js +3 -1
- package/dist/directives/Public.js.map +1 -1
- package/dist/directives/RequireSystemUser.d.ts +2 -0
- package/dist/directives/RequireSystemUser.d.ts.map +1 -1
- package/dist/directives/RequireSystemUser.js +3 -1
- package/dist/directives/RequireSystemUser.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +266 -4
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +1304 -0
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +8 -2
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +7 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +3 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +8 -4
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +10 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +11 -3
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +27 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -6
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts +2 -0
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +5 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +4 -0
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +10 -2
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/logging/NoLog.d.ts +4 -0
- package/dist/logging/NoLog.d.ts.map +1 -1
- package/dist/logging/NoLog.js +10 -2
- package/dist/logging/NoLog.js.map +1 -1
- package/dist/logging/StartupLogger.d.ts +2 -0
- package/dist/logging/StartupLogger.d.ts.map +1 -1
- package/dist/logging/StartupLogger.js +5 -1
- package/dist/logging/StartupLogger.js.map +1 -1
- package/dist/logging/bootAudit.d.ts +11 -7
- package/dist/logging/bootAudit.d.ts.map +1 -1
- package/dist/logging/bootAudit.js +15 -7
- package/dist/logging/bootAudit.js.map +1 -1
- package/dist/logging/boundaryLogPayload.d.ts +4 -0
- package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
- package/dist/logging/boundaryLogPayload.js +5 -1
- package/dist/logging/boundaryLogPayload.js.map +1 -1
- package/dist/logging/secretRedactor.d.ts +2 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +8 -4
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/logging/shortenForLog.d.ts +2 -0
- package/dist/logging/shortenForLog.d.ts.map +1 -1
- package/dist/logging/shortenForLog.js +7 -3
- package/dist/logging/shortenForLog.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +8 -6
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/metadataRefreshSignal.d.ts +19 -0
- package/dist/metadataRefreshSignal.d.ts.map +1 -0
- package/dist/metadataRefreshSignal.js +45 -0
- package/dist/metadataRefreshSignal.js.map +1 -0
- package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
- package/dist/multiTenancy/index.d.ts +8 -0
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +21 -5
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +14 -10
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
- package/dist/realtimeWidget/WidgetSessionService.js +27 -27
- package/dist/realtimeWidget/host-identity.d.ts +5 -1
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
- package/dist/realtimeWidget/host-identity.js +11 -3
- package/dist/realtimeWidget/host-identity.js.map +1 -1
- package/dist/realtimeWidget/index.d.ts +2 -2
- package/dist/realtimeWidget/index.d.ts.map +1 -1
- package/dist/realtimeWidget/index.js +2 -2
- package/dist/realtimeWidget/index.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +16 -4
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +48 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +38 -10
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +3 -3
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -3
- package/dist/resolvers/GeoResolver.d.ts +2 -2
- package/dist/resolvers/GeoResolver.js +4 -4
- package/dist/resolvers/GetDataResolver.d.ts +14 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +43 -15
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
- package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
- package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
- package/dist/resolvers/ListOperationsResolver.js +68 -28
- package/dist/resolvers/ListOperationsResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +11 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +7 -3
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +2 -1
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +37 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +101 -11
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +74 -42
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +2 -2
- package/dist/resolvers/RunTestResolver.js +5 -5
- package/dist/resolvers/SearchEntitiesResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +3 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +53 -4
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
- package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.js +10 -2
- package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
- package/dist/resolvers/artifact-routing.d.ts +8 -8
- package/dist/resolvers/artifact-routing.js +2 -2
- package/dist/resolvers/artifact-routing.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +24 -8
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/resolvers/peaksSidecar.d.ts +4 -0
- package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
- package/dist/resolvers/peaksSidecar.js +10 -2
- package/dist/resolvers/peaksSidecar.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +28 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +20 -4
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +2 -0
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +10 -6
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +15 -3
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts +6 -4
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +15 -11
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
- package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
- package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +5 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +24 -8
- package/dist/rest/UploadTokenManager.d.ts.map +1 -1
- package/dist/rest/UploadTokenManager.js +53 -21
- package/dist/rest/UploadTokenManager.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +20 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +20 -4
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/mediaRange.d.ts +4 -0
- package/dist/rest/mediaRange.d.ts.map +1 -1
- package/dist/rest/mediaRange.js +10 -2
- package/dist/rest/mediaRange.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +4 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +13 -7
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +2 -0
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +5 -1
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/dist/services/MJStorageBlobStore.d.ts +41 -0
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -0
- package/dist/services/MJStorageBlobStore.js +160 -0
- package/dist/services/MJStorageBlobStore.js.map +1 -0
- package/dist/services/TaskGraphActionRunner.d.ts +13 -8
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +16 -15
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +12 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +19 -8
- package/dist/util.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/FileResolverPeaks.test.ts +13 -13
- package/src/__tests__/ListOperationsResolver.test.ts +17 -17
- package/src/__tests__/MediaStreamHandler.test.ts +28 -28
- package/src/__tests__/NoLog.test.ts +11 -11
- package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
- package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
- package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +229 -0
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
- package/src/__tests__/SearchEntitiesResolver.readOnlyFallback.test.ts +78 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +290 -0
- package/src/__tests__/WidgetSessionService.test.ts +8 -4
- package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
- package/src/__tests__/bootAudit.test.ts +11 -11
- package/src/__tests__/boundaryLogPayload.test.ts +6 -6
- package/src/__tests__/databaseAbstraction.test.ts +12 -6
- package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
- package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
- package/src/__tests__/magicLink.test.ts +73 -134
- package/src/__tests__/magicLinkService.consume.test.ts +224 -0
- package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
- package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
- package/src/__tests__/multiTenancy.security.test.ts +40 -40
- package/src/__tests__/multiTenancy.test.ts +18 -18
- package/src/__tests__/newUsers.test.ts +24 -23
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
- package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
- package/src/__tests__/secretRedactor.test.ts +12 -12
- package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
- package/src/__tests__/subscriptionRedaction.test.ts +5 -5
- package/src/__tests__/unifiedAuth.test.ts +15 -9
- package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
- package/src/__tests__/widget.test.ts +45 -45
- package/src/__tests__/widgetGuestElevation.test.ts +7 -7
- package/src/__tests__/widgetHostIdentity.test.ts +14 -14
- package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
- package/src/agentSessions/SessionManager.ts +2 -2
- package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
- package/src/auth/AuthProviderCatalogRouter.ts +6 -1
- package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
- package/src/auth/exampleNewUserSubClass.ts +2 -2
- package/src/auth/index.ts +43 -28
- package/src/auth/initializeProviders.ts +25 -5
- package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
- package/src/auth/magicLink/MagicLinkService.ts +71 -52
- package/src/auth/magicLink/index.ts +7 -7
- package/src/auth/magicLink/magicLinkCore.ts +96 -64
- package/src/auth/magicLink/redeemLanding.ts +14 -4
- package/src/auth/magicLink/types.ts +54 -54
- package/src/auth/newUsers.ts +1 -1
- package/src/auth/principals.ts +11 -2
- package/src/cache.ts +4 -1
- package/src/config.ts +14 -4
- package/src/context.ts +37 -24
- package/src/directives/Public.ts +4 -1
- package/src/directives/RequireSystemUser.ts +4 -1
- package/src/generated/graphql-schemas/__mj.ts +933 -5
- package/src/generic/CacheInvalidationResolver.ts +12 -4
- package/src/generic/FireAndForgetHeartbeat.ts +19 -14
- package/src/generic/PushStatusResolver.ts +21 -7
- package/src/generic/ResolverBase.ts +66 -5
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +34 -7
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/integration/EntityMapLifecycle.ts +20 -2
- package/src/logging/NoLog.ts +16 -2
- package/src/logging/StartupLogger.ts +6 -1
- package/src/logging/bootAudit.ts +26 -16
- package/src/logging/boundaryLogPayload.ts +8 -1
- package/src/logging/secretRedactor.ts +14 -9
- package/src/logging/shortenForLog.ts +8 -3
- package/src/logging/variablesLoggingMiddleware.ts +9 -6
- package/src/metadataRefreshSignal.ts +45 -0
- package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
- package/src/multiTenancy/index.ts +29 -5
- package/src/realtimeWidget/WidgetRouter.ts +15 -10
- package/src/realtimeWidget/WidgetSessionService.ts +76 -76
- package/src/realtimeWidget/host-identity.ts +24 -10
- package/src/realtimeWidget/index.ts +3 -3
- package/src/realtimeWidget/visitorIdentity.ts +39 -8
- package/src/realtimeWidget/widgetCore.ts +75 -10
- package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
- package/src/resolvers/AdhocQueryResolver.ts +3 -3
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +42 -42
- package/src/resolvers/GeoResolver.ts +4 -4
- package/src/resolvers/GetDataResolver.ts +50 -15
- package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
- package/src/resolvers/ListOperationsResolver.ts +78 -28
- package/src/resolvers/MCPResolver.ts +30 -15
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/QuerySystemUserResolver.ts +2 -1
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +126 -13
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +118 -76
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SearchEntitiesResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
- package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/TransactionGroupResolver.ts +57 -4
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
- package/src/resolvers/adhoc-query-helpers.ts +19 -2
- package/src/resolvers/artifact-routing.ts +19 -19
- package/src/resolvers/meetingRecordingRegistration.ts +44 -10
- package/src/resolvers/peaksSidecar.ts +12 -2
- package/src/rest/EntityCRUDHandler.ts +24 -4
- package/src/rest/MediaStreamHandler.ts +11 -6
- package/src/rest/OAuthCallbackHandler.ts +25 -7
- package/src/rest/RESTEndpointHandler.ts +20 -15
- package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
- package/src/rest/SignatureWebhookHandler.ts +6 -1
- package/src/rest/UploadTokenManager.ts +66 -30
- package/src/rest/ViewOperationsHandler.ts +24 -4
- package/src/rest/mediaRange.ts +16 -6
- package/src/rest/setupRESTEndpoints.ts +24 -12
- package/src/serverExtensionReservedRoots.ts +6 -1
- package/src/services/MJStorageBlobStore.ts +209 -0
- package/src/services/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- package/src/util.ts +22 -9
|
@@ -119,7 +119,7 @@ export interface CacheInvalidationFilterContext {
|
|
|
119
119
|
* roles, so this stays cheap enough to run per subscriber per event. It is not free: it runs for
|
|
120
120
|
* every connected socket on every save, so keep it free of I/O.
|
|
121
121
|
*/
|
|
122
|
-
export function
|
|
122
|
+
export function CacheInvalidationFilter(data: {
|
|
123
123
|
payload: CacheInvalidationPayload;
|
|
124
124
|
context: CacheInvalidationFilterContext | undefined;
|
|
125
125
|
}): boolean {
|
|
@@ -151,13 +151,21 @@ export function cacheInvalidationFilter(data: {
|
|
|
151
151
|
return entity.GetUserPermisions(user).CanRead;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/** @deprecated Use {@link CacheInvalidationFilter}. */
|
|
155
|
+
export function cacheInvalidationFilter(data: {
|
|
156
|
+
payload: CacheInvalidationPayload;
|
|
157
|
+
context: CacheInvalidationFilterContext | undefined;
|
|
158
|
+
}): boolean {
|
|
159
|
+
return CacheInvalidationFilter(data);
|
|
160
|
+
}
|
|
161
|
+
|
|
154
162
|
@Resolver()
|
|
155
163
|
export class CacheInvalidationResolver {
|
|
156
164
|
/**
|
|
157
165
|
* Subscription that broadcasts cache invalidation events to connected clients, so cross-server
|
|
158
166
|
* cache invalidation reaches browsers.
|
|
159
167
|
*
|
|
160
|
-
* Delivery is filtered only by ENTITY-level read permission (see {@link
|
|
168
|
+
* Delivery is filtered only by ENTITY-level read permission (see {@link CacheInvalidationFilter}).
|
|
161
169
|
* Every session that may read an entity at all still receives every event for it, from every
|
|
162
170
|
* other session and tenant.
|
|
163
171
|
*
|
|
@@ -184,9 +192,9 @@ export class CacheInvalidationResolver {
|
|
|
184
192
|
@Subscription(() => CacheInvalidationNotification, {
|
|
185
193
|
topics: CACHE_INVALIDATION_TOPIC,
|
|
186
194
|
filter: (data: { payload: CacheInvalidationPayload; context: CacheInvalidationFilterContext | undefined }) =>
|
|
187
|
-
|
|
195
|
+
CacheInvalidationFilter(data),
|
|
188
196
|
})
|
|
189
|
-
cacheInvalidation(
|
|
197
|
+
cacheInvalidation( // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
190
198
|
@Root() payload: CacheInvalidationPayload
|
|
191
199
|
): CacheInvalidationNotification {
|
|
192
200
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PubSubEngine } from 'type-graphql';
|
|
2
2
|
import { LogError } from '@memberjunction/core';
|
|
3
|
-
import {
|
|
3
|
+
import { PublishStatusUpdate } from './PushStatusResolver.js';
|
|
4
4
|
|
|
5
5
|
/** Default cadence for fire-and-forget liveness pulses (5 minutes). */
|
|
6
6
|
export const DEFAULT_PULSE_INTERVAL_MS = 5 * 60 * 1000;
|
|
@@ -15,38 +15,38 @@ export const HEARTBEAT_MESSAGE_TYPE = 'Heartbeat';
|
|
|
15
15
|
*/
|
|
16
16
|
export interface PulseStatus {
|
|
17
17
|
/** Primary key of the persisted run record (AIAgentRun, TestRun, TestSuiteRun). */
|
|
18
|
-
runId?: string;
|
|
18
|
+
runId?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
19
19
|
/** Current run status, e.g. 'Running'. */
|
|
20
|
-
status?: string;
|
|
20
|
+
status?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
21
21
|
/** Optional human-readable current step for UI display. */
|
|
22
|
-
currentStep?: string;
|
|
22
|
+
currentStep?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/** Handle returned by {@link startLivenessPulse}; call `stop()` when the work settles. */
|
|
26
26
|
export interface LivenessPulseHandle {
|
|
27
|
-
|
|
27
|
+
Stop(): void;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export interface LivenessPulseOptions {
|
|
31
31
|
/** PubSub engine used to publish on the shared push-status topic. */
|
|
32
|
-
pubSub: PubSubEngine;
|
|
32
|
+
pubSub: PubSubEngine; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
33
33
|
/** Session the client is subscribed on (used by the subscription filter). */
|
|
34
|
-
sessionId: string;
|
|
34
|
+
sessionId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
|
|
35
35
|
/**
|
|
36
36
|
* Authenticated user the operation belongs to (B49). Stamped on every pulse so the
|
|
37
37
|
* subscription filter binds delivery to identity, not just the client-chosen sessionId.
|
|
38
38
|
*/
|
|
39
|
-
ownerUserId: string;
|
|
39
|
+
ownerUserId: string; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
40
40
|
/** Resolver label echoed in the message envelope (e.g. 'RunAIAgentResolver'). */
|
|
41
|
-
resolver: string;
|
|
41
|
+
resolver: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
|
|
42
42
|
/** Pulse cadence in ms. Defaults to {@link DEFAULT_PULSE_INTERVAL_MS}. */
|
|
43
|
-
intervalMs?: number;
|
|
43
|
+
intervalMs?: number; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
44
44
|
/**
|
|
45
45
|
* Optional cheap status reader invoked on each tick. Should read from an
|
|
46
46
|
* in-memory ref, not the database. Errors are swallowed so a transient read
|
|
47
47
|
* never kills the pulse loop.
|
|
48
48
|
*/
|
|
49
|
-
readStatus?: () => PulseStatus | undefined;
|
|
49
|
+
readStatus?: () => PulseStatus | undefined; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -60,7 +60,7 @@ export interface LivenessPulseOptions {
|
|
|
60
60
|
* (`{ message: JSON.stringify({ resolver, type, status, data }), sessionId }`),
|
|
61
61
|
* so the client receives it through the same subscription with no special parsing.
|
|
62
62
|
*/
|
|
63
|
-
export function
|
|
63
|
+
export function StartLivenessPulse(options: LivenessPulseOptions): LivenessPulseHandle {
|
|
64
64
|
const { pubSub, sessionId, ownerUserId, resolver, readStatus } = options;
|
|
65
65
|
const intervalMs = options.intervalMs ?? DEFAULT_PULSE_INTERVAL_MS;
|
|
66
66
|
|
|
@@ -73,7 +73,7 @@ export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulse
|
|
|
73
73
|
LogError(`[LivenessPulse:${resolver}] readStatus failed: ${(e as Error).message}`);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
PublishStatusUpdate(pubSub, {
|
|
77
77
|
sessionId,
|
|
78
78
|
ownerUserId,
|
|
79
79
|
message: JSON.stringify({
|
|
@@ -86,6 +86,11 @@ export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulse
|
|
|
86
86
|
}, intervalMs);
|
|
87
87
|
|
|
88
88
|
return {
|
|
89
|
-
|
|
89
|
+
Stop: () => clearInterval(timer),
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
|
+
|
|
93
|
+
/** @deprecated Use {@link StartLivenessPulse}. */
|
|
94
|
+
export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulseHandle {
|
|
95
|
+
return StartLivenessPulse(options);
|
|
96
|
+
}
|
|
@@ -7,13 +7,13 @@ export const PUSH_STATUS_UPDATES_TOPIC = 'PUSH_STATUS_UPDATES';
|
|
|
7
7
|
@ObjectType()
|
|
8
8
|
export class PushStatusNotification {
|
|
9
9
|
@Field(() => String, { nullable: true })
|
|
10
|
-
message?: string;
|
|
10
|
+
message?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
11
11
|
|
|
12
12
|
@Field((_type) => Date)
|
|
13
|
-
date!: Date;
|
|
13
|
+
date!: Date; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
14
14
|
|
|
15
15
|
@Field((_type) => ID)
|
|
16
|
-
sessionId!: string;
|
|
16
|
+
sessionId!: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -55,7 +55,7 @@ export interface StatusUpdateParams {
|
|
|
55
55
|
* payload shape and the required-identity guarantee live in exactly one place. Adding a field to
|
|
56
56
|
* the push is a one-line change here; a new publisher physically cannot omit `ownerUserId`.
|
|
57
57
|
*/
|
|
58
|
-
export function
|
|
58
|
+
export function PublishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdateParams): void {
|
|
59
59
|
const payload: PushStatusNotificationPayload = {
|
|
60
60
|
sessionId: params.sessionId,
|
|
61
61
|
ownerUserId: params.ownerUserId,
|
|
@@ -64,6 +64,11 @@ export function publishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdatePa
|
|
|
64
64
|
pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, payload);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/** @deprecated Use {@link PublishStatusUpdate}. */
|
|
68
|
+
export function publishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdateParams): void {
|
|
69
|
+
return PublishStatusUpdate(pubSub, params);
|
|
70
|
+
}
|
|
71
|
+
|
|
67
72
|
/** Minimal shape of the subscription's connection context needed by the filter. */
|
|
68
73
|
export interface StatusUpdatesFilterContext {
|
|
69
74
|
userPayload?: UserPayload;
|
|
@@ -82,7 +87,7 @@ export interface StatusUpdatesFilterContext {
|
|
|
82
87
|
* `sessionId` is no longer sufficient. Fails CLOSED — a missing owner or connection identity never
|
|
83
88
|
* matches.
|
|
84
89
|
*/
|
|
85
|
-
export function
|
|
90
|
+
export function StatusUpdatesFilter(data: {
|
|
86
91
|
payload: PushStatusNotificationPayload;
|
|
87
92
|
args: PushStatusNotificationArgs;
|
|
88
93
|
context: StatusUpdatesFilterContext | undefined;
|
|
@@ -98,14 +103,23 @@ export function statusUpdatesFilter(data: {
|
|
|
98
103
|
return UUIDsEqual(payload.ownerUserId, connectionUserId);
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
/** @deprecated Use {@link StatusUpdatesFilter}. */
|
|
107
|
+
export function statusUpdatesFilter(data: {
|
|
108
|
+
payload: PushStatusNotificationPayload;
|
|
109
|
+
args: PushStatusNotificationArgs;
|
|
110
|
+
context: StatusUpdatesFilterContext | undefined;
|
|
111
|
+
}): boolean {
|
|
112
|
+
return StatusUpdatesFilter(data);
|
|
113
|
+
}
|
|
114
|
+
|
|
101
115
|
@Resolver()
|
|
102
116
|
export class PushStatusResolver {
|
|
103
117
|
@Subscription(() => PushStatusNotification, {
|
|
104
118
|
topics: PUSH_STATUS_UPDATES_TOPIC,
|
|
105
119
|
filter: (data: ResolverFilterData<PushStatusNotificationPayload, PushStatusNotificationArgs, StatusUpdatesFilterContext>) =>
|
|
106
|
-
|
|
120
|
+
StatusUpdatesFilter(data),
|
|
107
121
|
})
|
|
108
|
-
statusUpdates(
|
|
122
|
+
statusUpdates( // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
109
123
|
@Root() { message }: PushStatusNotificationPayload,
|
|
110
124
|
@Arg('sessionId', () => String) sessionId: string
|
|
111
125
|
): PushStatusNotification {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
EntitySaveOptions,
|
|
11
11
|
IMetadataProvider,
|
|
12
12
|
IRunViewProvider,
|
|
13
|
+
KeyValuePair,
|
|
13
14
|
LogDebug,
|
|
14
15
|
LogError,
|
|
15
16
|
LogStatus,
|
|
@@ -39,7 +40,7 @@ import { MJEvent, MJEventType, MJGlobal, ENCRYPTED_SENTINEL, EscapeSQLString, Is
|
|
|
39
40
|
import { SQLParser } from '@memberjunction/sql-parser';
|
|
40
41
|
import { PostgreSQLDialect, SQLServerDialect, type SQLParserDialect } from '@memberjunction/sql-dialect';
|
|
41
42
|
import { EncryptionEngine } from '@memberjunction/encryption';
|
|
42
|
-
import { PUSH_STATUS_UPDATES_TOPIC,
|
|
43
|
+
import { PUSH_STATUS_UPDATES_TOPIC, PublishStatusUpdate } from './PushStatusResolver.js';
|
|
43
44
|
import { CACHE_INVALIDATION_TOPIC, MayBroadcastRecordData } from './CacheInvalidationResolver.js';
|
|
44
45
|
import { PubSubManager } from './PubSubManager.js';
|
|
45
46
|
import { FieldMapper } from '@memberjunction/graphql-dataprovider';
|
|
@@ -50,7 +51,7 @@ export class ResolverBase {
|
|
|
50
51
|
private static _cloudeventsHeaders = process.env.CLOUDEVENTS_HTTP_HEADERS ? JSON.parse(process.env.CLOUDEVENTS_HTTP_HEADERS) : {};
|
|
51
52
|
|
|
52
53
|
private static _eventSubscriptionKey: string = '___MJServer___ResolverBase___EventSubscriptions';
|
|
53
|
-
private get
|
|
54
|
+
private get eventSubscriptions(): Map<string, Subscription> {
|
|
54
55
|
// here we use the global object store instead of a static member becuase in some cases based on import code paths/bundling/etc, the static member
|
|
55
56
|
// could actually be duplicated and we'd end up with multiple instances of the same map, which would be bad.
|
|
56
57
|
const g = MJGlobal.Instance.GetGlobalObjectStore();
|
|
@@ -1479,7 +1480,7 @@ export class ResolverBase {
|
|
|
1479
1480
|
* `publishStatusUpdate()` function directly with an explicit `ownerUserId`.
|
|
1480
1481
|
*/
|
|
1481
1482
|
protected PublishStatusUpdate(pubSub: PubSubEngine, sessionId: string, message: string | undefined, userPayload: UserPayload): void {
|
|
1482
|
-
|
|
1483
|
+
PublishStatusUpdate(pubSub, {
|
|
1483
1484
|
sessionId,
|
|
1484
1485
|
ownerUserId: userPayload?.userRecord?.ID ?? '',
|
|
1485
1486
|
message,
|
|
@@ -1492,7 +1493,7 @@ export class ResolverBase {
|
|
|
1492
1493
|
// cause issues with multiple messages for the same event.
|
|
1493
1494
|
const uniqueKey = entityObject.EntityInfo.Name;
|
|
1494
1495
|
|
|
1495
|
-
if (!this.
|
|
1496
|
+
if (!this.eventSubscriptions.has(uniqueKey)) {
|
|
1496
1497
|
// listen for events from the entityObject in case it is a long running task and we can push messages back to the client via pubSub
|
|
1497
1498
|
LogDebug(`ResolverBase.ListenForEntityMessages: About to call MJGlobal.Instance.GetEventListener() to get the event listener subscription for ${uniqueKey}`);
|
|
1498
1499
|
const theSub = MJGlobal.Instance.GetEventListener(false).subscribe(async (event: MJEvent) => {
|
|
@@ -1525,10 +1526,66 @@ export class ResolverBase {
|
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
});
|
|
1528
|
-
this.
|
|
1529
|
+
this.eventSubscriptions.set(uniqueKey, theSub);
|
|
1529
1530
|
}
|
|
1530
1531
|
}
|
|
1531
1532
|
|
|
1533
|
+
/**
|
|
1534
|
+
* IS-A PROMOTION over the wire: an EXISTING parent record gaining a subtype — an Animal that is
|
|
1535
|
+
* now also a Dog. It arrives as the CHILD's create mutation carrying the existing parent's
|
|
1536
|
+
* primary key, because in IS-A the shared key is the relationship and the child has no key of
|
|
1537
|
+
* its own to mint. `NewRecord()` has just reset the whole chain to "new", so left alone the
|
|
1538
|
+
* parent would save as a CREATE: a second copy of a row that already exists (a unique-constraint
|
|
1539
|
+
* violation at best, a silently duplicated parent at worst).
|
|
1540
|
+
*
|
|
1541
|
+
* When a child create carries a complete primary key, bind the new child to the existing parent
|
|
1542
|
+
* row with `AttachToParent` (#3825): it loads the parent chain, so the parent saves as an UPDATE
|
|
1543
|
+
* and only the child is INSERTed. A key that matches no row leaves the fresh chain exactly as
|
|
1544
|
+
* `NewRecord()` built it — the ordinary whole-chain create. A non-IS-A entity, or a create with
|
|
1545
|
+
* no key, never gets past the guards.
|
|
1546
|
+
*
|
|
1547
|
+
* @returns true when the child was attached to an existing parent row.
|
|
1548
|
+
*/
|
|
1549
|
+
protected async attachToExistingParentIfPromotion(entityObject: BaseEntity, input: Record<string, unknown>): Promise<boolean> {
|
|
1550
|
+
if (!entityObject.EntityInfo.IsChildType) {
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
1553
|
+
const key = this.primaryKeyFromInput(entityObject.EntityInfo, input);
|
|
1554
|
+
if (!key) {
|
|
1555
|
+
return false;
|
|
1556
|
+
}
|
|
1557
|
+
const attached = await entityObject.AttachToParent(key);
|
|
1558
|
+
if (!attached) {
|
|
1559
|
+
// No parent row under that key: this is a whole-chain create on the CALLER's key (the
|
|
1560
|
+
// client mints the shared key at the root and sends it, so honoring it keeps the client's
|
|
1561
|
+
// in-memory chain and the stored rows on one key). AttachToParent restored the fresh chain,
|
|
1562
|
+
// but the root's ReadOnly key slot is no longer writable — a later SetMany would silently
|
|
1563
|
+
// keep the server-minted value — so re-seed the chain with the supplied key explicitly.
|
|
1564
|
+
entityObject.NewRecord(key);
|
|
1565
|
+
}
|
|
1566
|
+
return attached;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
/**
|
|
1570
|
+
* The entity's primary key as supplied on a mutation input, or null when any part of it is
|
|
1571
|
+
* missing. Composite keys are all-or-nothing: a half-specified key identifies nothing. An empty
|
|
1572
|
+
* string counts as missing, the same as null — it is never a valid key value, and a GUID or
|
|
1573
|
+
* string key that is "" identifies no row, so the create proceeds as a whole-chain create rather
|
|
1574
|
+
* than failing the lookup. A malformed non-empty key (e.g. a non-GUID for a uniqueidentifier)
|
|
1575
|
+
* is NOT swallowed: the load throws and the mutation fails loudly.
|
|
1576
|
+
*/
|
|
1577
|
+
protected primaryKeyFromInput(entityInfo: EntityInfo, input: Record<string, unknown>): CompositeKey | null {
|
|
1578
|
+
const pairs: KeyValuePair[] = [];
|
|
1579
|
+
for (const pk of entityInfo.PrimaryKeys) {
|
|
1580
|
+
const value = input[pk.Name] ?? input[pk.CodeName];
|
|
1581
|
+
if (value === null || value === undefined || value === '') {
|
|
1582
|
+
return null;
|
|
1583
|
+
}
|
|
1584
|
+
pairs.push(new KeyValuePair(pk.Name, value));
|
|
1585
|
+
}
|
|
1586
|
+
return pairs.length > 0 ? CompositeKey.FromKeyValuePairs(pairs) : null;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1532
1589
|
protected async CreateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine) {
|
|
1533
1590
|
// Check API key scope authorization for entity create operations
|
|
1534
1591
|
await this.CheckAPIKeyScopeAuthorization('entity:create', entityName, userPayload);
|
|
@@ -1546,6 +1603,10 @@ export class ResolverBase {
|
|
|
1546
1603
|
for (const key of Object.keys(input)) {
|
|
1547
1604
|
if (key !== 'RestoreContext___') fieldsForSet[key] = input[key];
|
|
1548
1605
|
}
|
|
1606
|
+
// IS-A promotion: bind the new child to its EXISTING parent row BEFORE the field
|
|
1607
|
+
// assignments, so values the client sent for parent fields land on the loaded parent
|
|
1608
|
+
// (as an update) instead of being wiped by the load.
|
|
1609
|
+
await this.attachToExistingParentIfPromotion(entityObject, fieldsForSet);
|
|
1549
1610
|
entityObject.SetMany(fieldsForSet);
|
|
1550
1611
|
|
|
1551
1612
|
// Reconstruct the client-side restore context, if any, on this server
|
|
@@ -45,13 +45,13 @@ export class AggregateExpressionInput {
|
|
|
45
45
|
@Field(() => String, {
|
|
46
46
|
description: 'SQL expression for the aggregate (e.g., "SUM(OrderTotal)", "COUNT(*)", "AVG(Price)")'
|
|
47
47
|
})
|
|
48
|
-
expression: string;
|
|
48
|
+
expression: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
49
49
|
|
|
50
50
|
@Field(() => String, {
|
|
51
51
|
nullable: true,
|
|
52
52
|
description: 'Optional alias for the result (used in error messages and debugging)'
|
|
53
53
|
})
|
|
54
|
-
alias?: string;
|
|
54
|
+
alias?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -60,22 +60,22 @@ export class AggregateExpressionInput {
|
|
|
60
60
|
@ObjectType()
|
|
61
61
|
export class AggregateResultOutput {
|
|
62
62
|
@Field(() => String, { description: 'The expression that was calculated' })
|
|
63
|
-
expression: string;
|
|
63
|
+
expression: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
64
64
|
|
|
65
65
|
@Field(() => String, { description: 'The alias (or expression if no alias provided)' })
|
|
66
|
-
alias: string;
|
|
66
|
+
alias: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
67
67
|
|
|
68
68
|
@Field(() => String, {
|
|
69
69
|
nullable: true,
|
|
70
70
|
description: 'The calculated value as a JSON string (preserves type information)'
|
|
71
71
|
})
|
|
72
|
-
value?: string;
|
|
72
|
+
value?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
73
73
|
|
|
74
74
|
@Field(() => String, {
|
|
75
75
|
nullable: true,
|
|
76
76
|
description: 'Error message if calculation failed'
|
|
77
77
|
})
|
|
78
|
-
error?: string;
|
|
78
|
+
error?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
//****************************************************************************
|
|
@@ -573,22 +573,22 @@ export class RunViewGenericInput {
|
|
|
573
573
|
@InputType()
|
|
574
574
|
export class RunViewCacheStatusInput {
|
|
575
575
|
@Field(() => String, { description: 'The maximum __mj_UpdatedAt value from cached results' })
|
|
576
|
-
maxUpdatedAt: string;
|
|
576
|
+
maxUpdatedAt: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
577
577
|
|
|
578
578
|
@Field(() => Int, { description: 'The number of rows in cached results' })
|
|
579
|
-
rowCount: number;
|
|
579
|
+
rowCount: number; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
580
580
|
}
|
|
581
581
|
|
|
582
582
|
@InputType()
|
|
583
583
|
export class RunViewWithCacheCheckInput {
|
|
584
584
|
@Field(() => RunDynamicViewInput, { description: 'The RunView parameters' })
|
|
585
|
-
params: RunDynamicViewInput;
|
|
585
|
+
params: RunDynamicViewInput; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
586
586
|
|
|
587
587
|
@Field(() => RunViewCacheStatusInput, {
|
|
588
588
|
nullable: true,
|
|
589
589
|
description: 'Optional cache status - if provided, server will check if cache is current'
|
|
590
590
|
})
|
|
591
|
-
cacheStatus?: RunViewCacheStatusInput;
|
|
591
|
+
cacheStatus?: RunViewCacheStatusInput; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
592
592
|
}
|
|
593
593
|
|
|
594
594
|
@ObjectType()
|
|
@@ -596,21 +596,21 @@ export class DifferentialDataOutput {
|
|
|
596
596
|
@Field(() => [RunViewGenericResultRow], {
|
|
597
597
|
description: 'Records that have been created or updated since the client\'s maxUpdatedAt'
|
|
598
598
|
})
|
|
599
|
-
updatedRows: RunViewGenericResultRow[];
|
|
599
|
+
updatedRows: RunViewGenericResultRow[]; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
600
600
|
|
|
601
601
|
@Field(() => [String], {
|
|
602
602
|
description: 'Primary key values (as concatenated strings) of records that have been deleted'
|
|
603
603
|
})
|
|
604
|
-
deletedRecordIDs: string[];
|
|
604
|
+
deletedRecordIDs: string[]; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
605
605
|
}
|
|
606
606
|
|
|
607
607
|
@ObjectType()
|
|
608
608
|
export class RunViewWithCacheCheckResultOutput {
|
|
609
609
|
@Field(() => Int, { description: 'The index of this view in the batch request' })
|
|
610
|
-
viewIndex: number;
|
|
610
|
+
viewIndex: number; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
611
611
|
|
|
612
612
|
@Field(() => String, { description: "'current', 'differential', 'stale', or 'error'" })
|
|
613
|
-
status: string;
|
|
613
|
+
status: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
614
614
|
|
|
615
615
|
@Field(() => [RunViewGenericResultRow], {
|
|
616
616
|
nullable: true,
|
|
@@ -622,34 +622,34 @@ export class RunViewWithCacheCheckResultOutput {
|
|
|
622
622
|
nullable: true,
|
|
623
623
|
description: 'Differential update data - only populated when status is differential'
|
|
624
624
|
})
|
|
625
|
-
differentialData?: DifferentialDataOutput;
|
|
625
|
+
differentialData?: DifferentialDataOutput; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
626
626
|
|
|
627
627
|
@Field(() => String, { nullable: true, description: 'Max __mj_UpdatedAt from results when stale or differential' })
|
|
628
|
-
maxUpdatedAt?: string;
|
|
628
|
+
maxUpdatedAt?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
629
629
|
|
|
630
630
|
@Field(() => Int, { nullable: true, description: 'Row count of results when stale or differential (total after applying delta)' })
|
|
631
|
-
rowCount?: number;
|
|
631
|
+
rowCount?: number; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
632
632
|
|
|
633
633
|
@Field(() => String, { nullable: true, description: 'Error message if status is error' })
|
|
634
|
-
errorMessage?: string;
|
|
634
|
+
errorMessage?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
635
635
|
|
|
636
636
|
@Field(() => [AggregateResultOutput], {
|
|
637
637
|
nullable: true,
|
|
638
638
|
description: 'Aggregate results when status is stale and aggregates were requested (B40 — previously never marshalled, so CacheLocal callers got no aggregates at all)'
|
|
639
639
|
})
|
|
640
|
-
aggregateResults?: AggregateResultOutput[];
|
|
640
|
+
aggregateResults?: AggregateResultOutput[]; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
641
641
|
}
|
|
642
642
|
|
|
643
643
|
@ObjectType()
|
|
644
644
|
export class RunViewsWithCacheCheckOutput {
|
|
645
645
|
@Field(() => Boolean, { description: 'Whether the overall operation succeeded' })
|
|
646
|
-
success: boolean;
|
|
646
|
+
success: boolean; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
647
647
|
|
|
648
648
|
@Field(() => [RunViewWithCacheCheckResultOutput], { description: 'Results for each view in the batch' })
|
|
649
|
-
results: RunViewWithCacheCheckResultOutput[];
|
|
649
|
+
results: RunViewWithCacheCheckResultOutput[]; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
650
650
|
|
|
651
651
|
@Field(() => String, { nullable: true, description: 'Overall error message if success is false' })
|
|
652
|
-
errorMessage?: string;
|
|
652
|
+
errorMessage?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
653
653
|
}
|
|
654
654
|
|
|
655
655
|
//****************************************************************************
|
|
@@ -2,7 +2,7 @@ import 'reflect-metadata';
|
|
|
2
2
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
3
3
|
import { PubSubEngine } from 'type-graphql';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
StartLivenessPulse,
|
|
6
6
|
DEFAULT_PULSE_INTERVAL_MS,
|
|
7
7
|
HEARTBEAT_MESSAGE_TYPE,
|
|
8
8
|
} from '../FireAndForgetHeartbeat';
|
|
@@ -31,14 +31,14 @@ describe('startLivenessPulse', () => {
|
|
|
31
31
|
|
|
32
32
|
it('does not publish before the first interval elapses', () => {
|
|
33
33
|
const pubSub = makePubSub();
|
|
34
|
-
|
|
34
|
+
StartLivenessPulse({ pubSub, sessionId: 's1', resolver: 'TestResolver' });
|
|
35
35
|
vi.advanceTimersByTime(DEFAULT_PULSE_INTERVAL_MS - 1);
|
|
36
36
|
expect(pubSub.publish).not.toHaveBeenCalled();
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('publishes a heartbeat on the push-status topic each interval', () => {
|
|
40
40
|
const pubSub = makePubSub();
|
|
41
|
-
|
|
41
|
+
StartLivenessPulse({ pubSub, sessionId: 's1', resolver: 'TestResolver', intervalMs: 1000 });
|
|
42
42
|
|
|
43
43
|
vi.advanceTimersByTime(3000);
|
|
44
44
|
|
|
@@ -52,7 +52,7 @@ describe('startLivenessPulse', () => {
|
|
|
52
52
|
|
|
53
53
|
it('includes the enriched status snapshot from readStatus', () => {
|
|
54
54
|
const pubSub = makePubSub();
|
|
55
|
-
|
|
55
|
+
StartLivenessPulse({
|
|
56
56
|
pubSub,
|
|
57
57
|
sessionId: 's1',
|
|
58
58
|
resolver: 'RunAIAgentResolver',
|
|
@@ -68,7 +68,7 @@ describe('startLivenessPulse', () => {
|
|
|
68
68
|
|
|
69
69
|
it('publishes an empty data object when readStatus throws (loop survives)', () => {
|
|
70
70
|
const pubSub = makePubSub();
|
|
71
|
-
|
|
71
|
+
StartLivenessPulse({
|
|
72
72
|
pubSub,
|
|
73
73
|
sessionId: 's1',
|
|
74
74
|
resolver: 'RunAIAgentResolver',
|
|
@@ -87,12 +87,12 @@ describe('startLivenessPulse', () => {
|
|
|
87
87
|
|
|
88
88
|
it('stops publishing after stop() is called', () => {
|
|
89
89
|
const pubSub = makePubSub();
|
|
90
|
-
const handle =
|
|
90
|
+
const handle = StartLivenessPulse({ pubSub, sessionId: 's1', resolver: 'TestResolver', intervalMs: 1000 });
|
|
91
91
|
|
|
92
92
|
vi.advanceTimersByTime(2000);
|
|
93
93
|
expect(pubSub.publish).toHaveBeenCalledTimes(2);
|
|
94
94
|
|
|
95
|
-
handle.
|
|
95
|
+
handle.Stop();
|
|
96
96
|
vi.advanceTimersByTime(5000);
|
|
97
97
|
expect(pubSub.publish).toHaveBeenCalledTimes(2);
|
|
98
98
|
});
|
package/src/index.ts
CHANGED
|
@@ -32,7 +32,7 @@ import { RealtimeProxyServer } from './realtimeProxy/RealtimeProxyServer.js';
|
|
|
32
32
|
import buildApolloServer from './apolloServer/index.js';
|
|
33
33
|
import { configInfo, configFilePath, dbDatabase, dbHost, dbPort, dbUsername, graphqlPort, graphqlRootPath, mj_core_schema, websiteRunFromPackage, RESTApiOptions } from './config.js';
|
|
34
34
|
import { default as jwt } from 'jsonwebtoken';
|
|
35
|
-
import { contextFunction,
|
|
35
|
+
import { contextFunction, CreateUnifiedAuthMiddleware, getUserPayload } from './context.js';
|
|
36
36
|
import { UserPayload } from './types.js';
|
|
37
37
|
import { requireSystemUserDirective, publicDirective } from './directives/index.js';
|
|
38
38
|
import { variablesLoggingMiddleware } from './logging/variablesLoggingMiddleware.js';
|
|
@@ -67,6 +67,8 @@ import { RegisterRSUProgressBridge } from './integration/RSUProgressBridge.js';
|
|
|
67
67
|
import { ClientToolRequestManager, AgentRunWatchdog } from '@memberjunction/ai-agents';
|
|
68
68
|
import { SessionJanitor } from './agentSessions/index.js';
|
|
69
69
|
import { StartTaskGraphDispatcher } from './services/StartTaskGraphDispatcher.js';
|
|
70
|
+
import { GetAttachmentService } from '@memberjunction/aiengine';
|
|
71
|
+
import { MJStorageBlobStore } from './services/MJStorageBlobStore.js';
|
|
70
72
|
import { CACHE_INVALIDATION_TOPIC, MayBroadcastRecordData, ConfigureRecordDataBroadcast } from './generic/CacheInvalidationResolver.js';
|
|
71
73
|
import { ConnectorFactory, IntegrationEngine, IntegrationSyncOptions } from '@memberjunction/integration-engine';
|
|
72
74
|
import { CronExpressionHelper } from '@memberjunction/scheduling-engine';
|
|
@@ -80,6 +82,7 @@ import {
|
|
|
80
82
|
import { ServerExtensionLoader, ServerExtensionConfig, mergeServerExtensionConfigs, prepareServerExtensionConfigs, describeServerExtensionMount, InstallMediaUpgradeDispatcher, IsGraphQLWsPath } from '@memberjunction/server-extensions-core';
|
|
81
83
|
import { coreReservedServerExtensionRoots } from './serverExtensionReservedRoots.js';
|
|
82
84
|
import { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
|
|
85
|
+
import { CreateMetadataRefreshSignalHandler, METADATA_REFRESH_SIGNAL } from './metadataRefreshSignal.js';
|
|
83
86
|
|
|
84
87
|
const cacheRefreshInterval = configInfo.databaseSettings.metadataCacheRefreshInterval;
|
|
85
88
|
|
|
@@ -97,10 +100,15 @@ export { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
|
|
|
97
100
|
* CodeGenLib). This wrapper keeps the public `getDbType()` symbol that
|
|
98
101
|
* MJServer consumers (and the broader stack) already import.
|
|
99
102
|
*/
|
|
100
|
-
export function
|
|
103
|
+
export function GetDbType(): DatabasePlatform {
|
|
101
104
|
return resolveDbPlatformFromEnv() ?? 'sqlserver';
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
/** @deprecated Use {@link GetDbType}. */
|
|
108
|
+
export function getDbType(): DatabasePlatform {
|
|
109
|
+
return GetDbType();
|
|
110
|
+
}
|
|
111
|
+
|
|
104
112
|
export { MaxLength } from 'class-validator';
|
|
105
113
|
export * from 'type-graphql';
|
|
106
114
|
// Named re-export so Open App generated resolvers get a live ESM binding for
|
|
@@ -261,7 +269,10 @@ const localPath = (p: string) => {
|
|
|
261
269
|
return resolvedPath;
|
|
262
270
|
};
|
|
263
271
|
|
|
264
|
-
export const
|
|
272
|
+
export const CreateApp = (): Application => express();
|
|
273
|
+
|
|
274
|
+
/** @deprecated Use {@link CreateApp}. */
|
|
275
|
+
export const createApp = CreateApp;
|
|
265
276
|
|
|
266
277
|
/**
|
|
267
278
|
* Resolves the MJServer package version for the startup summary header.
|
|
@@ -281,7 +292,18 @@ function resolveServerVersion(): string | undefined {
|
|
|
281
292
|
}
|
|
282
293
|
}
|
|
283
294
|
|
|
284
|
-
|
|
295
|
+
// Bind MJStorage as the conversation-attachment blob store. The attachment service itself no longer
|
|
296
|
+
// imports `@memberjunction/storage` — that dependency made it unusable from any browser or React
|
|
297
|
+
// Native client, which is why the same attachment rules had been reimplemented three times.
|
|
298
|
+
//
|
|
299
|
+
// This runs at module load, not inside `serve()`, so that merely importing MJServer is enough: any
|
|
300
|
+
// entry point that reaches the attachment service — a resolver under test, a script, a worker that
|
|
301
|
+
// never calls `serve()` — finds storage already bound rather than degrading to "storage is not
|
|
302
|
+
// available on this host". The store is stateless and configures `FileStorageEngine` on use, so
|
|
303
|
+
// there is no ordering hazard in binding this early.
|
|
304
|
+
GetAttachmentService().BlobStore = new MJStorageBlobStore();
|
|
305
|
+
|
|
306
|
+
export const Serve = async (resolverPaths: Array<string>, app: Application = CreateApp(), options?: MJServerOptions): Promise<void> => {
|
|
285
307
|
const t0 = performance.now();
|
|
286
308
|
// Level-gated startup logger. Resolves verbosity from telemetry.level (single
|
|
287
309
|
// operator knob). At `standard` (default), per-phase timings are collapsed into
|
|
@@ -307,8 +329,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
307
329
|
console.log({ combinedResolverPaths, paths, cwd: process.cwd() });
|
|
308
330
|
}
|
|
309
331
|
|
|
310
|
-
|
|
311
|
-
const dbType =
|
|
332
|
+
const setupComplete$ = new ReplaySubject(1);
|
|
333
|
+
const dbType = GetDbType();
|
|
312
334
|
const dataSources: DataSourceInfo[] = [];
|
|
313
335
|
|
|
314
336
|
if (dbType === 'postgresql') {
|
|
@@ -1377,7 +1399,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
1377
1399
|
startupLog.LogIf('verbose', `[Auth] Public provider catalog registered at ${AUTH_CATALOG_MOUNT_PATH}/providers`);
|
|
1378
1400
|
|
|
1379
1401
|
// ─── Unified auth middleware (replaces both REST authMiddleware and contextFunction auth) ─────
|
|
1380
|
-
app.use(
|
|
1402
|
+
app.use(CreateUnifiedAuthMiddleware(dataSources));
|
|
1381
1403
|
|
|
1382
1404
|
// ─── Post-auth middleware from BaseServerMiddleware plugins ─────
|
|
1383
1405
|
// Middleware here has access to the authenticated user via req.userPayload.
|
|
@@ -1666,6 +1688,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
1666
1688
|
|
|
1667
1689
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
1668
1690
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
1691
|
+
// Operator control: `kill -HUP <pid>` hard-reloads metadata from the DB — see metadataRefreshSignal.ts
|
|
1692
|
+
process.on(METADATA_REFRESH_SIGNAL, CreateMetadataRefreshSignalHandler(() => Metadata.Provider.Refresh())); // global-provider-ok: operator-triggered refresh of the global cache that per-request providers adopt from
|
|
1669
1693
|
|
|
1670
1694
|
// Handle unhandled promise rejections to prevent server crashes
|
|
1671
1695
|
process.on('unhandledRejection', (reason, promise) => {
|
|
@@ -1676,6 +1700,9 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
1676
1700
|
});
|
|
1677
1701
|
};
|
|
1678
1702
|
|
|
1703
|
+
/** @deprecated Use {@link Serve}. */
|
|
1704
|
+
export const serve = Serve;
|
|
1705
|
+
|
|
1679
1706
|
/**
|
|
1680
1707
|
* Age at which an unprocessed `MJ: RSU Pending Works` row is reported as stranded.
|
|
1681
1708
|
* A row older than this survived at least one full restart cycle without being completed.
|
|
@@ -133,7 +133,7 @@ interface WorkItem {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/** Registers the post-sync custom-column promotion hook on the IntegrationEngine singleton. */
|
|
136
|
-
export function
|
|
136
|
+
export function RegisterIntegrationCustomColumnPromoter(): void {
|
|
137
137
|
IntegrationEngine.Instance.SetPostSyncSchemaPromotionCallback(async (ctx) => {
|
|
138
138
|
const user = ctx.ContextUser as UserInfo;
|
|
139
139
|
const provider = ctx.Provider as IMetadataProvider | undefined;
|
|
@@ -164,6 +164,11 @@ export function registerIntegrationCustomColumnPromoter(): void {
|
|
|
164
164
|
LogStatusEx({ message: '[CustomColumnPromoter] Registered post-sync custom-column promotion hook (auto-promote opt-in, default OFF).', verboseOnly: true });
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/** @deprecated Use {@link RegisterIntegrationCustomColumnPromoter}. */
|
|
168
|
+
export function registerIntegrationCustomColumnPromoter(): void {
|
|
169
|
+
return RegisterIntegrationCustomColumnPromoter();
|
|
170
|
+
}
|
|
171
|
+
|
|
167
172
|
/** Reads the per-connection `autoPromoteCustomColumns` flag (default false = capture-only, on-demand promotion). */
|
|
168
173
|
async function readAutoPromoteFlag(companyIntegrationID: string, user: UserInfo, provider?: IMetadataProvider): Promise<boolean> {
|
|
169
174
|
try {
|