@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
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach, type Mock } from 'vitest';
|
|
2
|
+
|
|
3
|
+
// MagicLinkService is the imperative shell — importing it pulls the full
|
|
4
|
+
// data-provider and communication stacks in at module load. Stub those out;
|
|
5
|
+
// @memberjunction/core stays real (Metadata, RunView, LogError).
|
|
6
|
+
vi.mock('@memberjunction/generic-database-provider', () => ({
|
|
7
|
+
UserCache: { Instance: { Users: [] } },
|
|
8
|
+
}));
|
|
9
|
+
vi.mock('@memberjunction/communication-engine', () => ({
|
|
10
|
+
CommunicationEngine: { Instance: {} },
|
|
11
|
+
}));
|
|
12
|
+
vi.mock('@memberjunction/communication-types', () => ({
|
|
13
|
+
Message: class {},
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('../config.js', () => ({
|
|
16
|
+
configInfo: {},
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
import { Metadata, RunView, type DatabaseProviderBase, type IMetadataProvider, type UserInfo } from '@memberjunction/core';
|
|
20
|
+
import type { MJMagicLinkInviteEntity } from '@memberjunction/core-entities';
|
|
21
|
+
import type { MagicLinkConfig } from '../config.js';
|
|
22
|
+
import { MagicLinkService } from '../auth/magicLink/MagicLinkService.js';
|
|
23
|
+
import { MAGIC_LINK_TOKEN_PREFIX, BuildConsumeInvitePostgresSQL } from '../auth/magicLink/magicLinkCore.js';
|
|
24
|
+
|
|
25
|
+
type Platform = 'sqlserver' | 'postgresql';
|
|
26
|
+
|
|
27
|
+
/** Provider surface consumeInvite/RedeemInvite touch, with real-shaped dialect behavior. */
|
|
28
|
+
interface FakeProvider {
|
|
29
|
+
PlatformKey: Platform;
|
|
30
|
+
MJCoreSchemaName: string;
|
|
31
|
+
Roles: { ID: string; Name: string }[];
|
|
32
|
+
Applications: { ID: string; Name: string; Path: string }[];
|
|
33
|
+
Dialect: { ProcedureCallSyntax: (schema: string, name: string, params: string[]) => string };
|
|
34
|
+
BuildParameterPlaceholder: (index: number) => string;
|
|
35
|
+
ExecuteSQL: Mock;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function makeProvider(platform: Platform): FakeProvider {
|
|
39
|
+
const isPg = platform === 'postgresql';
|
|
40
|
+
return {
|
|
41
|
+
PlatformKey: platform,
|
|
42
|
+
MJCoreSchemaName: '__mj',
|
|
43
|
+
Roles: [{ ID: 'role-1', Name: 'Magic Link Baseline' }],
|
|
44
|
+
Applications: [],
|
|
45
|
+
Dialect: {
|
|
46
|
+
ProcedureCallSyntax: isPg
|
|
47
|
+
? (s, n, p) => `SELECT * FROM ${s}."${n}"(${p.join(', ')})`
|
|
48
|
+
: (s, n, p) => `EXEC [${s}].[${n}] ${p.join(', ')}`,
|
|
49
|
+
},
|
|
50
|
+
BuildParameterPlaceholder: isPg ? (i) => `$${i + 1}` : (i) => `@p${i}`,
|
|
51
|
+
ExecuteSQL: vi.fn(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const INVITE_ID = '11111111-2222-3333-4444-555555555555';
|
|
56
|
+
|
|
57
|
+
function makeInvite(): MJMagicLinkInviteEntity {
|
|
58
|
+
return {
|
|
59
|
+
ID: INVITE_ID,
|
|
60
|
+
Status: 'Active',
|
|
61
|
+
UseCount: 0,
|
|
62
|
+
MaxUses: 1,
|
|
63
|
+
ExpiresAt: new Date(Date.now() + 3600_000),
|
|
64
|
+
RoleID: 'role-1',
|
|
65
|
+
CreatedByUserID: 'inviter-1',
|
|
66
|
+
ApplicationID: 'app-1',
|
|
67
|
+
Email: 'g@example.com',
|
|
68
|
+
} as unknown as MJMagicLinkInviteEntity;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Private surface of MagicLinkService the tests drive or stub. */
|
|
72
|
+
interface ServicePrivates {
|
|
73
|
+
consumeInvite: (invite: MJMagicLinkInviteEntity, provider: DatabaseProviderBase, contextUser: UserInfo) => Promise<string>;
|
|
74
|
+
resolveProvisioningContextUser: () => UserInfo | null;
|
|
75
|
+
isInviterActive: (id: string) => boolean;
|
|
76
|
+
recordRedemption: () => Promise<void>;
|
|
77
|
+
provisionUser: () => Promise<{ success: boolean; error?: string }>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
describe('MagicLinkService.consumeInvite (#4753)', () => {
|
|
81
|
+
let service: MagicLinkService;
|
|
82
|
+
let privates: ServicePrivates;
|
|
83
|
+
let invite: MJMagicLinkInviteEntity;
|
|
84
|
+
const contextUser = { ID: 'ctx-user' } as UserInfo;
|
|
85
|
+
|
|
86
|
+
beforeEach(() => {
|
|
87
|
+
service = new MagicLinkService('https://mj.example.com', {} as MagicLinkConfig);
|
|
88
|
+
privates = service as unknown as ServicePrivates;
|
|
89
|
+
invite = makeInvite();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
afterEach(() => {
|
|
93
|
+
Metadata.Provider = null as unknown as IMetadataProvider;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
async function consume(provider: FakeProvider): Promise<string> {
|
|
97
|
+
return privates.consumeInvite(invite, provider as unknown as DatabaseProviderBase, contextUser);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
it('SQL Server: calls spConsumeMagicLinkInvite with the ID bound by name, never interpolated', async () => {
|
|
101
|
+
const provider = makeProvider('sqlserver');
|
|
102
|
+
provider.ExecuteSQL.mockResolvedValue([{ ID: INVITE_ID }]);
|
|
103
|
+
await consume(provider);
|
|
104
|
+
|
|
105
|
+
expect(provider.ExecuteSQL).toHaveBeenCalledTimes(1);
|
|
106
|
+
const [sql, params, options, user] = provider.ExecuteSQL.mock.calls[0];
|
|
107
|
+
expect(sql).toBe('EXEC [__mj].[spConsumeMagicLinkInvite] @ID=@p0');
|
|
108
|
+
expect(params).toEqual([INVITE_ID]);
|
|
109
|
+
expect(options).toEqual(expect.objectContaining({ isMutation: true }));
|
|
110
|
+
expect(user).toBe(contextUser);
|
|
111
|
+
expect(sql).not.toContain(INVITE_ID);
|
|
112
|
+
expect(String(sql).toUpperCase()).not.toContain('UPDATE');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// PG has no spConsumeMagicLinkInvite function (the release-time converter does not emit
|
|
116
|
+
// procedures) and PG's runtime roles hold table DML, so PG keeps the direct guarded UPDATE.
|
|
117
|
+
it('PostgreSQL: runs the guarded UPDATE … RETURNING directly, with the ID bound as $1', async () => {
|
|
118
|
+
const provider = makeProvider('postgresql');
|
|
119
|
+
provider.ExecuteSQL.mockResolvedValue([{ ID: INVITE_ID }]);
|
|
120
|
+
await consume(provider);
|
|
121
|
+
|
|
122
|
+
expect(provider.ExecuteSQL).toHaveBeenCalledTimes(1);
|
|
123
|
+
const [sql, params, options, user] = provider.ExecuteSQL.mock.calls[0];
|
|
124
|
+
expect(sql).toBe(BuildConsumeInvitePostgresSQL('__mj.MagicLinkInvite'));
|
|
125
|
+
expect(sql).not.toContain('spConsumeMagicLinkInvite');
|
|
126
|
+
expect(params).toEqual([INVITE_ID]);
|
|
127
|
+
expect(options).toEqual(expect.objectContaining({ isMutation: true }));
|
|
128
|
+
expect(user).toBe(contextUser);
|
|
129
|
+
expect(sql).not.toContain(INVITE_ID);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("PostgreSQL: maps one row to 'won', zero rows to 'lost', and a thrown error to 'failed'", async () => {
|
|
133
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
134
|
+
const provider = makeProvider('postgresql');
|
|
135
|
+
provider.ExecuteSQL.mockResolvedValueOnce([{ ID: INVITE_ID }]).mockResolvedValueOnce([]).mockRejectedValueOnce(new Error('connection reset'));
|
|
136
|
+
|
|
137
|
+
expect(await consume(provider)).toBe('won');
|
|
138
|
+
expect(await consume(provider)).toBe('lost');
|
|
139
|
+
expect(await consume(provider)).toBe('failed');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("returns 'won' when exactly one row comes back", async () => {
|
|
143
|
+
const provider = makeProvider('sqlserver');
|
|
144
|
+
provider.ExecuteSQL.mockResolvedValue([{ ID: INVITE_ID }]);
|
|
145
|
+
expect(await consume(provider)).toBe('won');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("returns 'lost' when zero rows come back", async () => {
|
|
149
|
+
const provider = makeProvider('sqlserver');
|
|
150
|
+
provider.ExecuteSQL.mockResolvedValue([]);
|
|
151
|
+
expect(await consume(provider)).toBe('lost');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("returns 'failed' and logs the invite ID when ExecuteSQL throws", async () => {
|
|
155
|
+
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
156
|
+
const provider = makeProvider('sqlserver');
|
|
157
|
+
provider.ExecuteSQL.mockRejectedValue(new Error("The EXECUTE permission was denied on the object 'spConsumeMagicLinkInvite'"));
|
|
158
|
+
|
|
159
|
+
expect(await consume(provider)).toBe('failed');
|
|
160
|
+
const logged = errorSpy.mock.calls.map((call) => call.map(String).join(' '));
|
|
161
|
+
expect(logged.some((line) => line.includes(INVITE_ID) && line.includes('spConsumeMagicLinkInvite'))).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("returns 'failed' when ExecuteSQL returns a non-array", async () => {
|
|
165
|
+
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
166
|
+
const provider = makeProvider('sqlserver');
|
|
167
|
+
provider.ExecuteSQL.mockResolvedValue(undefined);
|
|
168
|
+
|
|
169
|
+
expect(await consume(provider)).toBe('failed');
|
|
170
|
+
const logged = errorSpy.mock.calls.map((call) => call.map(String).join(' '));
|
|
171
|
+
expect(logged.some((line) => line.includes(INVITE_ID))).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('MagicLinkService.RedeemInvite consume outcome mapping (#4753)', () => {
|
|
176
|
+
let service: MagicLinkService;
|
|
177
|
+
let provider: FakeProvider;
|
|
178
|
+
let provisionUser: Mock;
|
|
179
|
+
const contextUser = { ID: 'ctx-user' } as UserInfo;
|
|
180
|
+
const rawToken = MAGIC_LINK_TOKEN_PREFIX + 'x';
|
|
181
|
+
|
|
182
|
+
beforeEach(() => {
|
|
183
|
+
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
184
|
+
provider = makeProvider('sqlserver');
|
|
185
|
+
Metadata.Provider = provider as unknown as IMetadataProvider;
|
|
186
|
+
|
|
187
|
+
service = new MagicLinkService('https://mj.example.com', {} as MagicLinkConfig);
|
|
188
|
+
const privates = service as unknown as ServicePrivates;
|
|
189
|
+
vi.spyOn(RunView.prototype, 'RunView').mockResolvedValue({ Success: true, Results: [makeInvite()] } as Awaited<ReturnType<RunView['RunView']>>);
|
|
190
|
+
vi.spyOn(privates, 'resolveProvisioningContextUser').mockReturnValue(contextUser);
|
|
191
|
+
vi.spyOn(privates, 'isInviterActive').mockReturnValue(true);
|
|
192
|
+
vi.spyOn(privates, 'recordRedemption').mockResolvedValue(undefined);
|
|
193
|
+
provisionUser = vi.fn().mockResolvedValue({ success: false, error: 'stop-here' });
|
|
194
|
+
privates.provisionUser = provisionUser;
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
afterEach(() => {
|
|
198
|
+
Metadata.Provider = null as unknown as IMetadataProvider;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('RedeemInvite maps a failed consume to server_error, not consumed, and never provisions', async () => {
|
|
202
|
+
provider.ExecuteSQL.mockRejectedValue(new Error("The EXECUTE permission was denied on the object 'spConsumeMagicLinkInvite'"));
|
|
203
|
+
const result = await service.RedeemInvite(rawToken);
|
|
204
|
+
|
|
205
|
+
expect(result).toEqual(expect.objectContaining({ success: false, errorCode: 'server_error' }));
|
|
206
|
+
expect(provisionUser).not.toHaveBeenCalled();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('RedeemInvite still reports consumed when the race is lost', async () => {
|
|
210
|
+
provider.ExecuteSQL.mockResolvedValue([]);
|
|
211
|
+
const result = await service.RedeemInvite(rawToken);
|
|
212
|
+
|
|
213
|
+
expect(result).toEqual(expect.objectContaining({ success: false, errorCode: 'consumed' }));
|
|
214
|
+
expect(provisionUser).not.toHaveBeenCalled();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('RedeemInvite proceeds to provisioning when the consume wins', async () => {
|
|
218
|
+
provider.ExecuteSQL.mockResolvedValue([{ ID: INVITE_ID }]);
|
|
219
|
+
const result = await service.RedeemInvite(rawToken);
|
|
220
|
+
|
|
221
|
+
expect(provisionUser).toHaveBeenCalledTimes(1);
|
|
222
|
+
expect(result).toEqual(expect.objectContaining({ success: false, errorCode: 'provisioning_failed' }));
|
|
223
|
+
});
|
|
224
|
+
});
|
|
@@ -43,8 +43,8 @@ vi.mock('@memberjunction/core-entities', async (importOriginal) => {
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
import {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
RegisterMeetingRecordingFile,
|
|
47
|
+
ResolveMeetingConversation,
|
|
48
48
|
type MeetingRecordingEgressResult,
|
|
49
49
|
} from '../resolvers/meetingRecordingRegistration';
|
|
50
50
|
|
|
@@ -124,7 +124,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
124
124
|
.mockResolvedValueOnce({ Success: true, Results: [{ ID: 'conv-existing' }] });
|
|
125
125
|
|
|
126
126
|
const { provider, created } = makeProvider();
|
|
127
|
-
const result = await
|
|
127
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
128
128
|
|
|
129
129
|
expect(result.Success).toBe(true);
|
|
130
130
|
expect(result.RecordingFileID).toBe('file-123');
|
|
@@ -153,7 +153,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
153
153
|
it('prefers matching the conversation by EgressID when present', async () => {
|
|
154
154
|
runViewMock.mockResolvedValueOnce({ Success: true, Results: [{ ID: 'conv-by-egress' }] });
|
|
155
155
|
const { provider } = makeProvider();
|
|
156
|
-
const result = await
|
|
156
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
157
157
|
expect(result.ConversationID).toBe('conv-by-egress');
|
|
158
158
|
// Only the EgressID lookup ran (no fall-through to room-name lookup).
|
|
159
159
|
expect(runViewMock).toHaveBeenCalledTimes(1);
|
|
@@ -162,7 +162,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
162
162
|
it('creates a Meeting-Room Conversation when none exists', async () => {
|
|
163
163
|
runViewMock.mockResolvedValue({ Success: true, Results: [] }); // neither lookup matches
|
|
164
164
|
const { provider, created } = makeProvider();
|
|
165
|
-
const result = await
|
|
165
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
166
166
|
expect(result.Success).toBe(true);
|
|
167
167
|
const conv = created.conversation[0];
|
|
168
168
|
expect(conv.fields.Type).toBe('Meeting Room');
|
|
@@ -173,7 +173,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
173
173
|
it('returns a graceful failure when the storage provider is not configured', async () => {
|
|
174
174
|
delete process.env.MJ_MEETING_RECORDING_STORAGE_PROVIDER;
|
|
175
175
|
const { provider } = makeProvider();
|
|
176
|
-
const result = await
|
|
176
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
177
177
|
expect(result.Success).toBe(false);
|
|
178
178
|
expect(result.ErrorMessage).toMatch(/MJ_MEETING_RECORDING_STORAGE_PROVIDER/);
|
|
179
179
|
expect(result.RecordingFileID).toBeUndefined();
|
|
@@ -182,14 +182,14 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
182
182
|
it('returns a graceful failure when no account is linked to the configured provider', async () => {
|
|
183
183
|
storage.accountsByProvider = new Map(); // no accounts for prov-sink
|
|
184
184
|
const { provider } = makeProvider();
|
|
185
|
-
const result = await
|
|
185
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
186
186
|
expect(result.Success).toBe(false);
|
|
187
187
|
expect(result.ErrorMessage).toMatch(/No active MJStorage account/i);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
it('returns a graceful failure when the egress has no output yet', async () => {
|
|
191
191
|
const { provider } = makeProvider();
|
|
192
|
-
const result = await
|
|
192
|
+
const result = await RegisterMeetingRecordingFile({ ...egress, OutputLocation: undefined }, user, provider);
|
|
193
193
|
expect(result.Success).toBe(false);
|
|
194
194
|
expect(result.ErrorMessage).toMatch(/no output/i);
|
|
195
195
|
});
|
|
@@ -204,7 +204,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
204
204
|
runViewMock.mockResolvedValueOnce({ Success: true, Results: [{ ID: 'conv-1' }] });
|
|
205
205
|
|
|
206
206
|
const { provider, created } = makeProvider();
|
|
207
|
-
const result = await
|
|
207
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
208
208
|
|
|
209
209
|
expect(result.Success).toBe(true);
|
|
210
210
|
// Bytes were read from the sink and uploaded into the canonical provider.
|
|
@@ -221,7 +221,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
221
221
|
process.env.MJ_MEETING_RECORDING_CANONICAL_STORAGE_PROVIDER = 'prov-sink'; // same as sink
|
|
222
222
|
runViewMock.mockResolvedValueOnce({ Success: true, Results: [{ ID: 'conv-1' }] });
|
|
223
223
|
const { provider, created } = makeProvider();
|
|
224
|
-
const result = await
|
|
224
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
225
225
|
expect(result.Success).toBe(true);
|
|
226
226
|
expect(storage.getObject).not.toHaveBeenCalled();
|
|
227
227
|
expect(created.file[0].fields.ProviderID).toBe('prov-sink');
|
|
@@ -231,7 +231,7 @@ describe('registerMeetingRecordingFile', () => {
|
|
|
231
231
|
it('fails gracefully (no throw) when the Files row save fails', async () => {
|
|
232
232
|
runViewMock.mockResolvedValueOnce({ Success: true, Results: [{ ID: 'conv-1' }] });
|
|
233
233
|
const { provider } = makeProvider({ fileSaveOk: false });
|
|
234
|
-
const result = await
|
|
234
|
+
const result = await RegisterMeetingRecordingFile(egress, user, provider);
|
|
235
235
|
expect(result.Success).toBe(false);
|
|
236
236
|
expect(result.ErrorMessage).toMatch(/Files row/i);
|
|
237
237
|
});
|
|
@@ -241,7 +241,7 @@ describe('resolveMeetingConversation', () => {
|
|
|
241
241
|
it('falls back to creating a conversation when neither lookup matches', async () => {
|
|
242
242
|
runViewMock.mockResolvedValue({ Success: true, Results: [] });
|
|
243
243
|
const { provider, created } = makeProvider();
|
|
244
|
-
const id = await
|
|
244
|
+
const id = await ResolveMeetingConversation(egress, user, provider);
|
|
245
245
|
expect(id).toBe('conv-new');
|
|
246
246
|
expect(created.conversation).toHaveLength(1);
|
|
247
247
|
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tests for the SIGHUP operator control that hard-reloads metadata in a running MJAPI.
|
|
5
|
+
* What matters: a signal triggers exactly one refresh, a burst of signals does not stack
|
|
6
|
+
* reloads, and a failing refresh never rejects out of a process signal listener.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { logStatusMock, logErrorMock } = vi.hoisted(() => ({
|
|
10
|
+
logStatusMock: vi.fn(),
|
|
11
|
+
logErrorMock: vi.fn()
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock('@memberjunction/core', () => ({
|
|
15
|
+
LogStatus: logStatusMock,
|
|
16
|
+
LogError: logErrorMock
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
import { CreateMetadataRefreshSignalHandler, METADATA_REFRESH_SIGNAL } from '../metadataRefreshSignal.js';
|
|
20
|
+
|
|
21
|
+
describe('CreateMetadataRefreshSignalHandler', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
logStatusMock.mockReset();
|
|
24
|
+
logErrorMock.mockReset();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('uses SIGHUP, not SIGUSR1 (reserved by the Node inspector)', () => {
|
|
28
|
+
expect(METADATA_REFRESH_SIGNAL).toBe('SIGHUP');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('runs the refresh once per signal', async () => {
|
|
32
|
+
const refresh = vi.fn(async () => true);
|
|
33
|
+
const handler = CreateMetadataRefreshSignalHandler(refresh);
|
|
34
|
+
|
|
35
|
+
await handler();
|
|
36
|
+
await handler();
|
|
37
|
+
|
|
38
|
+
expect(refresh).toHaveBeenCalledTimes(2);
|
|
39
|
+
expect(logErrorMock).not.toHaveBeenCalled();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('ignores a signal that arrives while a refresh is still running', async () => {
|
|
43
|
+
let finish: (ok: boolean) => void = () => {};
|
|
44
|
+
const refresh = vi.fn(async () => true)
|
|
45
|
+
.mockImplementationOnce(() => new Promise<boolean>((resolve) => { finish = resolve; }));
|
|
46
|
+
const handler = CreateMetadataRefreshSignalHandler(refresh);
|
|
47
|
+
|
|
48
|
+
const first = handler();
|
|
49
|
+
await handler(); // arrives mid-refresh
|
|
50
|
+
finish(true);
|
|
51
|
+
await first;
|
|
52
|
+
|
|
53
|
+
expect(refresh).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(logStatusMock).toHaveBeenCalledWith(expect.stringContaining('already running'));
|
|
55
|
+
|
|
56
|
+
await handler(); // in-flight flag cleared after completion
|
|
57
|
+
expect(refresh).toHaveBeenCalledTimes(2);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('logs, does not reject, and re-arms when the refresh throws', async () => {
|
|
61
|
+
const refresh = vi.fn(async (): Promise<boolean> => { throw new Error('db down'); });
|
|
62
|
+
const handler = CreateMetadataRefreshSignalHandler(refresh);
|
|
63
|
+
|
|
64
|
+
await expect(handler()).resolves.toBeUndefined();
|
|
65
|
+
expect(logErrorMock).toHaveBeenCalledTimes(1);
|
|
66
|
+
|
|
67
|
+
await handler();
|
|
68
|
+
expect(refresh).toHaveBeenCalledTimes(2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('logs an error when the refresh reports failure', async () => {
|
|
72
|
+
const handler = CreateMetadataRefreshSignalHandler(async () => false);
|
|
73
|
+
|
|
74
|
+
await handler();
|
|
75
|
+
|
|
76
|
+
expect(logErrorMock).toHaveBeenCalledWith(expect.stringContaining('reported failure'));
|
|
77
|
+
});
|
|
78
|
+
});
|