@memberjunction/server 6.2.0-edge.0 → 6.2.0-edge.2
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/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 +346 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -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 +1021 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +7368 -2145
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +94 -4
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +122 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/DeleteOptionsInput.d.ts +8 -1
- package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
- package/dist/generic/DeleteOptionsInput.js +1 -1
- package/dist/generic/DeleteOptionsInput.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +18 -2
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +24 -6
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
- package/dist/generic/PushStatusResolver.d.ts +48 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +95 -4
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +18 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -55
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +120 -11
- 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/AgentRunStatusPublisher.d.ts +55 -0
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
- package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
- 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/MergeRecordsResolver.d.ts +7 -0
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +16 -2
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +44 -6
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +93 -37
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +8 -18
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +85 -184
- 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/RunDecisionResolver.d.ts +149 -0
- package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
- package/dist/resolvers/RunDecisionResolver.js +396 -0
- package/dist/resolvers/RunDecisionResolver.js.map +1 -0
- package/dist/resolvers/RunTestResolver.js +5 -5
- 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/VectorizeEntityResolver.d.ts +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.js +14 -10
- package/dist/resolvers/VectorizeEntityResolver.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/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 +6 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +13 -5
- package/dist/util.js.map +1 -1
- package/package.json +94 -92
- package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
- package/src/__tests__/DeleteOptionsInput.wireShape.test.ts +62 -0
- package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
- 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 +216 -2
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +398 -0
- package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
- package/src/__tests__/RunDecisionResolver.test.ts +699 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +131 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/VectorizeEntityResolver.test.ts +106 -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__/cacheInvalidationRecordData.test.ts +177 -0
- package/src/__tests__/conversationRunEvents.test.ts +399 -0
- 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__/orphanedConversationDetailReconciler.test.ts +283 -0
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusFanOut.test.ts +206 -0
- 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 +4 -3
- 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 +37 -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 +3674 -4
- package/src/generic/CacheInvalidationResolver.ts +148 -4
- package/src/generic/DeleteOptionsInput.ts +9 -2
- package/src/generic/FireAndForgetHeartbeat.ts +35 -16
- package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
- package/src/generic/PushStatusResolver.ts +118 -8
- package/src/generic/ResolverBase.ts +65 -57
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +137 -11
- 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/AgentRunStatusPublisher.ts +175 -0
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
- package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
- 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/MergeRecordsResolver.ts +14 -2
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +96 -38
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +134 -239
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunDecisionResolver.ts +435 -0
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/VectorizeEntityResolver.ts +16 -11
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
- 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/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- package/src/util.ts +16 -6
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';
|
|
@@ -61,6 +61,12 @@ import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
|
61
61
|
import { RedisLocalStorageProvider } from '@memberjunction/redis-provider';
|
|
62
62
|
import { GenericDatabaseProvider } from '@memberjunction/generic-database-provider';
|
|
63
63
|
import { PubSubManager } from './generic/PubSubManager.js';
|
|
64
|
+
import { ReconcileOrphanedConversationDetails } from './generic/OrphanedConversationDetailReconciler.js';
|
|
65
|
+
import {
|
|
66
|
+
PUSH_STATUS_UPDATES_TOPIC,
|
|
67
|
+
SetPushStatusPublishHook,
|
|
68
|
+
ParseReplicatedStatusUpdate,
|
|
69
|
+
} from './generic/PushStatusResolver.js';
|
|
64
70
|
import { IntegrationProgressEmitter } from '@memberjunction/integration-progress-artifacts';
|
|
65
71
|
import { PublishIntegrationProgress } from './resolvers/IntegrationProgressResolver.js';
|
|
66
72
|
import { RegisterRSUProgressBridge } from './integration/RSUProgressBridge.js';
|
|
@@ -69,7 +75,7 @@ import { SessionJanitor } from './agentSessions/index.js';
|
|
|
69
75
|
import { StartTaskGraphDispatcher } from './services/StartTaskGraphDispatcher.js';
|
|
70
76
|
import { GetAttachmentService } from '@memberjunction/aiengine';
|
|
71
77
|
import { MJStorageBlobStore } from './services/MJStorageBlobStore.js';
|
|
72
|
-
import { CACHE_INVALIDATION_TOPIC } from './generic/CacheInvalidationResolver.js';
|
|
78
|
+
import { CACHE_INVALIDATION_TOPIC, MayBroadcastRecordData, ConfigureRecordDataBroadcast } from './generic/CacheInvalidationResolver.js';
|
|
73
79
|
import { ConnectorFactory, IntegrationEngine, IntegrationSyncOptions } from '@memberjunction/integration-engine';
|
|
74
80
|
import { CronExpressionHelper } from '@memberjunction/scheduling-engine';
|
|
75
81
|
import {
|
|
@@ -82,6 +88,7 @@ import {
|
|
|
82
88
|
import { ServerExtensionLoader, ServerExtensionConfig, mergeServerExtensionConfigs, prepareServerExtensionConfigs, describeServerExtensionMount, InstallMediaUpgradeDispatcher, IsGraphQLWsPath } from '@memberjunction/server-extensions-core';
|
|
83
89
|
import { coreReservedServerExtensionRoots } from './serverExtensionReservedRoots.js';
|
|
84
90
|
import { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
|
|
91
|
+
import { CreateMetadataRefreshSignalHandler, METADATA_REFRESH_SIGNAL } from './metadataRefreshSignal.js';
|
|
85
92
|
|
|
86
93
|
const cacheRefreshInterval = configInfo.databaseSettings.metadataCacheRefreshInterval;
|
|
87
94
|
|
|
@@ -99,10 +106,15 @@ export { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
|
|
|
99
106
|
* CodeGenLib). This wrapper keeps the public `getDbType()` symbol that
|
|
100
107
|
* MJServer consumers (and the broader stack) already import.
|
|
101
108
|
*/
|
|
102
|
-
export function
|
|
109
|
+
export function GetDbType(): DatabasePlatform {
|
|
103
110
|
return resolveDbPlatformFromEnv() ?? 'sqlserver';
|
|
104
111
|
}
|
|
105
112
|
|
|
113
|
+
/** @deprecated Use {@link GetDbType}. */
|
|
114
|
+
export function getDbType(): DatabasePlatform {
|
|
115
|
+
return GetDbType();
|
|
116
|
+
}
|
|
117
|
+
|
|
106
118
|
export { MaxLength } from 'class-validator';
|
|
107
119
|
export * from 'type-graphql';
|
|
108
120
|
// Named re-export so Open App generated resolvers get a live ESM binding for
|
|
@@ -161,7 +173,9 @@ export * from './generic/refusalExtensions.js';
|
|
|
161
173
|
export * from './generic/RunViewResolver.js';
|
|
162
174
|
export * from './resolvers/RunTemplateResolver.js';
|
|
163
175
|
export * from './resolvers/RunAIPromptResolver.js';
|
|
176
|
+
export * from './resolvers/RunDecisionResolver.js';
|
|
164
177
|
export * from './resolvers/RunAIAgentResolver.js';
|
|
178
|
+
export { AgentRunStatusPublisher } from './resolvers/AgentRunStatusPublisher.js';
|
|
165
179
|
export * from './resolvers/VectorizeEntityResolver.js';
|
|
166
180
|
export * from './resolvers/SearchKnowledgeResolver.js';
|
|
167
181
|
export * from './resolvers/SearchKnowledgeStreamResolver.js';
|
|
@@ -218,6 +232,7 @@ export * from './rest/MediaAccessKeys.js';
|
|
|
218
232
|
export * from './rest/MediaStreamHandler.js';
|
|
219
233
|
export * from './resolvers/InfoResolver.js';
|
|
220
234
|
export * from './resolvers/PotentialDuplicateRecordResolver.js';
|
|
235
|
+
export * from './resolvers/DuplicateEntryCheckResolver.js';
|
|
221
236
|
export * from './resolvers/RunTestResolver.js';
|
|
222
237
|
export * from './resolvers/SearchEntitiesResolver.js';
|
|
223
238
|
export * from './resolvers/UserFavoriteResolver.js';
|
|
@@ -263,7 +278,10 @@ const localPath = (p: string) => {
|
|
|
263
278
|
return resolvedPath;
|
|
264
279
|
};
|
|
265
280
|
|
|
266
|
-
export const
|
|
281
|
+
export const CreateApp = (): Application => express();
|
|
282
|
+
|
|
283
|
+
/** @deprecated Use {@link CreateApp}. */
|
|
284
|
+
export const createApp = CreateApp;
|
|
267
285
|
|
|
268
286
|
/**
|
|
269
287
|
* Resolves the MJServer package version for the startup summary header.
|
|
@@ -283,6 +301,61 @@ function resolveServerVersion(): string | undefined {
|
|
|
283
301
|
}
|
|
284
302
|
}
|
|
285
303
|
|
|
304
|
+
/** How often to re-check for conversation details left behind by finished runs. */
|
|
305
|
+
const ORPHAN_DETAIL_SWEEP_INTERVAL_MS = 5 * 60_000;
|
|
306
|
+
|
|
307
|
+
/** Redis channel carrying replicated push-status updates between server instances. */
|
|
308
|
+
const PUSH_STATUS_FANOUT_CHANNEL = 'push-status-updates';
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Replicate push-status updates across server instances over Redis (MJ #4222).
|
|
312
|
+
*
|
|
313
|
+
* Outbound: every locally-published update is forwarded on a shared channel. Inbound: a message
|
|
314
|
+
* from another instance is republished onto THIS instance's local topic, where the normal
|
|
315
|
+
* subscription filter decides who receives it — so the identity gate (`ownerUserId` vs. the
|
|
316
|
+
* connection's authenticated user) still applies to a replicated message exactly as it does to a
|
|
317
|
+
* local one. The replica has no say in who sees what.
|
|
318
|
+
*
|
|
319
|
+
* Republishing goes straight to `PubSubManager`, never back through `publishStatusUpdate`, so an
|
|
320
|
+
* inbound message cannot be re-broadcast and loop. `SourceServerId` guards the remaining case: a
|
|
321
|
+
* publisher also receives its own message from Redis.
|
|
322
|
+
*/
|
|
323
|
+
async function wirePushStatusFanOut(redisProvider: RedisLocalStorageProvider, startupLog: StartupLogger): Promise<void> {
|
|
324
|
+
try {
|
|
325
|
+
await redisProvider.SubscribeToChannel(PUSH_STATUS_FANOUT_CHANNEL, (raw: string) => {
|
|
326
|
+
try {
|
|
327
|
+
const payload = ParseReplicatedStatusUpdate(raw, MJGlobal.Instance.ProcessUUID);
|
|
328
|
+
if (!payload) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
// Rebuilt as a plain record: the topic's publish signature takes an index-signature type,
|
|
332
|
+
// and listing the fields keeps the wire shape explicit at the one place it crosses hosts.
|
|
333
|
+
PubSubManager.Instance.Publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
334
|
+
sessionId: payload.sessionId,
|
|
335
|
+
ownerUserId: payload.ownerUserId,
|
|
336
|
+
message: payload.message,
|
|
337
|
+
SourceServerId: payload.SourceServerId,
|
|
338
|
+
});
|
|
339
|
+
} catch {
|
|
340
|
+
// A malformed message on a shared channel must not take down the subscriber.
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
SetPushStatusPublishHook((payload) => {
|
|
345
|
+
redisProvider.PublishMessage(PUSH_STATUS_FANOUT_CHANNEL, JSON.stringify(payload));
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Printed unconditionally, not verbose-gated. "Is fan-out actually on?" is the first question
|
|
349
|
+
// anyone debugging a hung conversation behind a load balancer asks, and a silent default left
|
|
350
|
+
// no way to answer it.
|
|
351
|
+
console.log('[MJAPI] Push-status updates: cross-instance fan-out enabled via Redis');
|
|
352
|
+
} catch (err) {
|
|
353
|
+
// Single-instance delivery still works, and the durable tail query covers the rest. Degraded,
|
|
354
|
+
// not broken — so this must not stop the server from starting.
|
|
355
|
+
console.warn(`Push-status fan-out unavailable: ${(err as Error).message}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
286
359
|
// Bind MJStorage as the conversation-attachment blob store. The attachment service itself no longer
|
|
287
360
|
// imports `@memberjunction/storage` — that dependency made it unusable from any browser or React
|
|
288
361
|
// Native client, which is why the same attachment rules had been reimplemented three times.
|
|
@@ -294,7 +367,7 @@ function resolveServerVersion(): string | undefined {
|
|
|
294
367
|
// there is no ordering hazard in binding this early.
|
|
295
368
|
GetAttachmentService().BlobStore = new MJStorageBlobStore();
|
|
296
369
|
|
|
297
|
-
export const
|
|
370
|
+
export const Serve = async (resolverPaths: Array<string>, app: Application = CreateApp(), options?: MJServerOptions): Promise<void> => {
|
|
298
371
|
const t0 = performance.now();
|
|
299
372
|
// Level-gated startup logger. Resolves verbosity from telemetry.level (single
|
|
300
373
|
// operator knob). At `standard` (default), per-phase timings are collapsed into
|
|
@@ -321,7 +394,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
321
394
|
}
|
|
322
395
|
|
|
323
396
|
const setupComplete$ = new ReplaySubject(1);
|
|
324
|
-
const dbType =
|
|
397
|
+
const dbType = GetDbType();
|
|
325
398
|
const dataSources: DataSourceInfo[] = [];
|
|
326
399
|
|
|
327
400
|
if (dbType === 'postgresql') {
|
|
@@ -711,6 +784,15 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
711
784
|
}
|
|
712
785
|
});
|
|
713
786
|
|
|
787
|
+
// Fan push-status updates across server instances (MJ #4222).
|
|
788
|
+
//
|
|
789
|
+
// Behind a load balancer the browser's WebSocket lives on one replica while the mutation that
|
|
790
|
+
// drives the agent can be handled by another. The push topic is an in-process PubSub, so a
|
|
791
|
+
// completion published on replica B never reaches a subscriber on replica A — the browser waits
|
|
792
|
+
// forever for an event that was delivered to nobody. Replicating progress and completion over
|
|
793
|
+
// Redis closes that, and the durable tail query remains the backstop if Redis is down.
|
|
794
|
+
await wirePushStatusFanOut(redisProvider, startupLog);
|
|
795
|
+
|
|
714
796
|
startupLog.LogIf('verbose', `Redis cache provider connected: ${process.env.REDIS_URL}`);
|
|
715
797
|
}
|
|
716
798
|
|
|
@@ -909,6 +991,11 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
909
991
|
// publish hook above so the first RSU event also reaches live subscribers.
|
|
910
992
|
RegisterRSUProgressBridge();
|
|
911
993
|
|
|
994
|
+
// Hand the resolver its allowlist before anything can publish. It cannot read configInfo itself:
|
|
995
|
+
// config.ts loads and validates at module scope, so importing it there would pull full config
|
|
996
|
+
// validation into every import chain that touches the resolver, unit tests included.
|
|
997
|
+
ConfigureRecordDataBroadcast(configInfo.cacheSettings?.recordDataBroadcastEntities);
|
|
998
|
+
|
|
912
999
|
// Global listener: broadcast CACHE_INVALIDATION to all browser clients whenever
|
|
913
1000
|
// ANY BaseEntity save/delete occurs on this server — regardless of whether it
|
|
914
1001
|
// originated from a GraphQL mutation or internal server-side code (agents, actions,
|
|
@@ -918,14 +1005,21 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
918
1005
|
if (event.event === MJEventType.ComponentEvent && event.eventCode === BaseEntity.BaseEventCode) {
|
|
919
1006
|
const beEvent = event.args as BaseEntityEvent;
|
|
920
1007
|
if (beEvent.type === 'save' || beEvent.type === 'delete') {
|
|
1008
|
+
const entityName = beEvent.baseEntity.EntityInfo.Name;
|
|
921
1009
|
PubSubManager.Instance.Publish(CACHE_INVALIDATION_TOPIC, {
|
|
922
|
-
entityName
|
|
1010
|
+
entityName,
|
|
923
1011
|
primaryKeyValues: JSON.stringify(beEvent.baseEntity.PrimaryKey.KeyValuePairs),
|
|
924
1012
|
action: beEvent.type,
|
|
925
1013
|
sourceServerId: MJGlobal.Instance.ProcessUUID,
|
|
926
1014
|
timestamp: new Date(),
|
|
927
1015
|
originSessionId: null,
|
|
928
|
-
|
|
1016
|
+
// Opt-in only: this event reaches every connected client unfiltered, and this listener
|
|
1017
|
+
// fires for server-internal saves too (agents, actions, orchestrator), which are exactly
|
|
1018
|
+
// the ones no browser session asked for.
|
|
1019
|
+
recordData:
|
|
1020
|
+
beEvent.type === 'save' && MayBroadcastRecordData(entityName)
|
|
1021
|
+
? JSON.stringify(beEvent.baseEntity.GetAll())
|
|
1022
|
+
: undefined,
|
|
929
1023
|
});
|
|
930
1024
|
}
|
|
931
1025
|
}
|
|
@@ -1054,6 +1148,15 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1054
1148
|
}
|
|
1055
1149
|
});
|
|
1056
1150
|
|
|
1151
|
+
// graphql-ws's ws integration takes its keepalive as a THIRD POSITIONAL argument to useServer,
|
|
1152
|
+
// defaulting to 12_000 when omitted. That default was doing real work here while being invisible
|
|
1153
|
+
// at the call site: the server pings every 12s and terminates the socket after an unanswered
|
|
1154
|
+
// pong, which is why MJAPI notices a half-open link in ~12-24s while the browser — whose
|
|
1155
|
+
// graphql-ws client does nothing on an unanswered pong — noticed nothing at all (MJ #4222).
|
|
1156
|
+
// Stated explicitly so the behaviour is visible and tunable, and so the next reader does not
|
|
1157
|
+
// conclude from the call site that no server-side heartbeat exists. Value unchanged.
|
|
1158
|
+
const WS_SERVER_KEEPALIVE_MS = 12_000;
|
|
1159
|
+
|
|
1057
1160
|
// Track per-connection expiry timers so we can clean them up on close
|
|
1058
1161
|
const expiryTimers = new WeakMap<object, ReturnType<typeof setTimeout>>();
|
|
1059
1162
|
|
|
@@ -1128,7 +1231,8 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1128
1231
|
console.error('WebSocket error:', errors);
|
|
1129
1232
|
},
|
|
1130
1233
|
},
|
|
1131
|
-
webSocketServer
|
|
1234
|
+
webSocketServer,
|
|
1235
|
+
WS_SERVER_KEEPALIVE_MS
|
|
1132
1236
|
);
|
|
1133
1237
|
|
|
1134
1238
|
const apolloServer = buildApolloServer(
|
|
@@ -1378,7 +1482,7 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1378
1482
|
startupLog.LogIf('verbose', `[Auth] Public provider catalog registered at ${AUTH_CATALOG_MOUNT_PATH}/providers`);
|
|
1379
1483
|
|
|
1380
1484
|
// ─── Unified auth middleware (replaces both REST authMiddleware and contextFunction auth) ─────
|
|
1381
|
-
app.use(
|
|
1485
|
+
app.use(CreateUnifiedAuthMiddleware(dataSources));
|
|
1382
1486
|
|
|
1383
1487
|
// ─── Post-auth middleware from BaseServerMiddleware plugins ─────
|
|
1384
1488
|
// Middleware here has access to the authenticated user via req.userPayload.
|
|
@@ -1559,8 +1663,25 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1559
1663
|
// instance is still heart-beating. The watchdog also self-registers for graceful-shutdown
|
|
1560
1664
|
// cancellation (via ShutdownRegistry) once it begins tracking this process's first live run.
|
|
1561
1665
|
if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
|
|
1562
|
-
|
|
1666
|
+
const sweepUser = resumeUser;
|
|
1667
|
+
const sweepProvider = Metadata.Provider; // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
|
|
1668
|
+
AgentRunWatchdog.SweepOrphanedRuns(sweepProvider, sweepUser)
|
|
1563
1669
|
.catch(err => console.warn(`[AgentRunWatchdog] Startup sweep failed: ${err}`));
|
|
1670
|
+
|
|
1671
|
+
// The watchdog repairs the RUN; nothing repaired the conversation detail, which is the row the
|
|
1672
|
+
// chat actually renders from (MJ #4222). A process that dies mid-run leaves a terminal run
|
|
1673
|
+
// beside a message that still claims to be generating, and it spins forever for anyone who
|
|
1674
|
+
// opens it. Runs at boot (closes restart orphans) and on a timer (closes mid-life orphans),
|
|
1675
|
+
// mirroring the watchdog's own two-phase shape.
|
|
1676
|
+
const reconcileOrphans = () =>
|
|
1677
|
+
ReconcileOrphanedConversationDetails(sweepProvider, sweepUser)
|
|
1678
|
+
.catch(err => console.warn(`[OrphanDetailReconciler] Pass failed: ${err}`));
|
|
1679
|
+
void reconcileOrphans();
|
|
1680
|
+
const orphanDetailTimer = setInterval(() => void reconcileOrphans(), ORPHAN_DETAIL_SWEEP_INTERVAL_MS);
|
|
1681
|
+
ShutdownRegistry.Instance.Register({
|
|
1682
|
+
ShutdownName: 'OrphanDetailReconciler',
|
|
1683
|
+
Shutdown: () => { clearInterval(orphanDetailTimer); },
|
|
1684
|
+
});
|
|
1564
1685
|
}
|
|
1565
1686
|
|
|
1566
1687
|
// Launch the AI Agent Session janitor: run own-host orphan recovery once at boot, then keep a
|
|
@@ -1667,6 +1788,8 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1667
1788
|
|
|
1668
1789
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
1669
1790
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
1791
|
+
// Operator control: `kill -HUP <pid>` hard-reloads metadata from the DB — see metadataRefreshSignal.ts
|
|
1792
|
+
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
|
|
1670
1793
|
|
|
1671
1794
|
// Handle unhandled promise rejections to prevent server crashes
|
|
1672
1795
|
process.on('unhandledRejection', (reason, promise) => {
|
|
@@ -1677,6 +1800,9 @@ const setupComplete$ = new ReplaySubject(1);
|
|
|
1677
1800
|
});
|
|
1678
1801
|
};
|
|
1679
1802
|
|
|
1803
|
+
/** @deprecated Use {@link Serve}. */
|
|
1804
|
+
export const serve = Serve;
|
|
1805
|
+
|
|
1680
1806
|
/**
|
|
1681
1807
|
* Age at which an unprocessed `MJ: RSU Pending Works` row is reported as stranded.
|
|
1682
1808
|
* 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 {
|
|
@@ -242,7 +242,7 @@ export interface SelectableSourceField {
|
|
|
242
242
|
* `null`/`undefined` selection means "all fields", which is not the same as an EMPTY selection —
|
|
243
243
|
* an empty array is a real (if unusual) choice, and still yields the keys.
|
|
244
244
|
*/
|
|
245
|
-
export function
|
|
245
|
+
export function SelectFieldsToMap<T extends SelectableSourceField>(
|
|
246
246
|
allFields: readonly T[],
|
|
247
247
|
selectedFieldNames: readonly string[] | null | undefined,
|
|
248
248
|
): T[] {
|
|
@@ -251,6 +251,14 @@ export function selectFieldsToMap<T extends SelectableSourceField>(
|
|
|
251
251
|
return allFields.filter(f => selected.has(f.Name.toLowerCase()) || f.IsPrimaryKey === true);
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/** @deprecated Use {@link SelectFieldsToMap}. */
|
|
255
|
+
export function selectFieldsToMap<T extends SelectableSourceField>(
|
|
256
|
+
allFields: readonly T[],
|
|
257
|
+
selectedFieldNames: readonly string[] | null | undefined,
|
|
258
|
+
): T[] {
|
|
259
|
+
return SelectFieldsToMap(allFields, selectedFieldNames);
|
|
260
|
+
}
|
|
261
|
+
|
|
254
262
|
/** One existing field map, reduced to what the reconciliation decision needs. */
|
|
255
263
|
export interface ExistingFieldMapRead {
|
|
256
264
|
SourceFieldName: string | null;
|
|
@@ -289,7 +297,7 @@ export interface FieldMapReconcilePlan {
|
|
|
289
297
|
* stopped reporting the column, so it returns to the state it had.
|
|
290
298
|
* - **Vanished column → `Inactive`, never deleted.** Retiring is reversible by the branch above.
|
|
291
299
|
*/
|
|
292
|
-
export function
|
|
300
|
+
export function DecideFieldMapReconcile(
|
|
293
301
|
activeFieldNames: readonly string[],
|
|
294
302
|
existing: readonly ExistingFieldMapRead[],
|
|
295
303
|
mapEnabled: boolean,
|
|
@@ -320,3 +328,13 @@ export function decideFieldMapReconcile(
|
|
|
320
328
|
}
|
|
321
329
|
return plan;
|
|
322
330
|
}
|
|
331
|
+
|
|
332
|
+
/** @deprecated Use {@link DecideFieldMapReconcile}. */
|
|
333
|
+
export function decideFieldMapReconcile(
|
|
334
|
+
activeFieldNames: readonly string[],
|
|
335
|
+
existing: readonly ExistingFieldMapRead[],
|
|
336
|
+
mapEnabled: boolean,
|
|
337
|
+
autoEnableNewColumns = true,
|
|
338
|
+
): FieldMapReconcilePlan {
|
|
339
|
+
return DecideFieldMapReconcile(activeFieldNames, existing, mapEnabled, autoEnableNewColumns);
|
|
340
|
+
}
|
package/src/logging/NoLog.ts
CHANGED
|
@@ -64,7 +64,7 @@ export function NoLog(target: object, propertyKey?: string | symbol, parameterIn
|
|
|
64
64
|
* Pass the resolver class itself (e.g. `MyResolver`) — the function reads from the
|
|
65
65
|
* prototype internally to match how type-graphql stores resolver metadata.
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
67
|
+
export function HasNoLogParameter(
|
|
68
68
|
resolverClass: Function,
|
|
69
69
|
methodName: string,
|
|
70
70
|
parameterIndex: number,
|
|
@@ -74,6 +74,15 @@ export function hasNoLogParameter(
|
|
|
74
74
|
return marks !== undefined && marks.has(parameterIndex);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** @deprecated Use {@link HasNoLogParameter}. */
|
|
78
|
+
export function hasNoLogParameter(
|
|
79
|
+
resolverClass: Function,
|
|
80
|
+
methodName: string,
|
|
81
|
+
parameterIndex: number,
|
|
82
|
+
): boolean {
|
|
83
|
+
return HasNoLogParameter(resolverClass, methodName, parameterIndex);
|
|
84
|
+
}
|
|
85
|
+
|
|
77
86
|
/**
|
|
78
87
|
* Returns the set of field names decorated `@NoLog` on the given input class. Empty set
|
|
79
88
|
* if none were marked.
|
|
@@ -81,8 +90,13 @@ export function hasNoLogParameter(
|
|
|
81
90
|
* Pass the input class itself (e.g. `GetDataInputType`) — the function reads from the
|
|
82
91
|
* prototype internally.
|
|
83
92
|
*/
|
|
84
|
-
export function
|
|
93
|
+
export function GetNoLogFields(inputTypeClass: Function): ReadonlySet<string> {
|
|
85
94
|
const target = inputTypeClass.prototype as object;
|
|
86
95
|
const marks = Reflect.getMetadata(NO_LOG_FIELD_KEY, target) as Set<string> | undefined;
|
|
87
96
|
return marks ?? new Set<string>();
|
|
88
97
|
}
|
|
98
|
+
|
|
99
|
+
/** @deprecated Use {@link GetNoLogFields}. */
|
|
100
|
+
export function getNoLogFields(inputTypeClass: Function): ReadonlySet<string> {
|
|
101
|
+
return GetNoLogFields(inputTypeClass);
|
|
102
|
+
}
|
|
@@ -117,7 +117,7 @@ export class StartupLogger {
|
|
|
117
117
|
* operator knob governs both telemetry and server logging. Defaults to
|
|
118
118
|
* `standard` when unset or unrecognized.
|
|
119
119
|
*/
|
|
120
|
-
public static
|
|
120
|
+
public static ResolveLevelFromConfig(): ServerLogLevel {
|
|
121
121
|
const raw = configInfo.telemetry?.level;
|
|
122
122
|
if (raw === 'minimal' || raw === 'standard' || raw === 'verbose' || raw === 'debug') {
|
|
123
123
|
return raw;
|
|
@@ -125,6 +125,11 @@ export class StartupLogger {
|
|
|
125
125
|
return 'standard';
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/** @deprecated Use {@link ResolveLevelFromConfig}. */
|
|
129
|
+
public static resolveLevelFromConfig(): ServerLogLevel {
|
|
130
|
+
return this.ResolveLevelFromConfig();
|
|
131
|
+
}
|
|
132
|
+
|
|
128
133
|
/**
|
|
129
134
|
* True when the active level is at least `minLevel` (using the ascending
|
|
130
135
|
* `minimal < standard < verbose < debug` ordering).
|
package/src/logging/bootAudit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getMetadataStorage } from 'type-graphql';
|
|
2
2
|
import { configInfo } from '../config.js';
|
|
3
|
-
import {
|
|
3
|
+
import { HasNoLogParameter } from './NoLog.js';
|
|
4
4
|
|
|
5
5
|
// Delete is included alongside Create/Update so codegen DeleteMJ*Input resolvers count as
|
|
6
6
|
// metadata-bound and don't flood the audit with false positives (their args are PK + Options
|
|
@@ -13,12 +13,12 @@ const INPUT_TYPE_REGEX = /^(Create|Update|Delete).+Input$/;
|
|
|
13
13
|
* Used by the audit walker. Mirrors the subset of `ArgParamMetadata` we need.
|
|
14
14
|
*/
|
|
15
15
|
export type AuditArgParam = {
|
|
16
|
-
kind: 'arg';
|
|
17
|
-
|
|
18
|
-
name: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
kind: 'arg'; // 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
|
|
17
|
+
Index: number;
|
|
18
|
+
name: 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
|
|
19
|
+
Target: Function;
|
|
20
|
+
MethodName: string;
|
|
21
|
+
GetType: () => unknown;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -26,9 +26,9 @@ export type AuditArgParam = {
|
|
|
26
26
|
* Includes `@Query`, `@Mutation`, `@Subscription` entries.
|
|
27
27
|
*/
|
|
28
28
|
export type AuditResolver = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
params?: ReadonlyArray<{ kind: string;
|
|
29
|
+
Target: Function;
|
|
30
|
+
MethodName: string;
|
|
31
|
+
params?: ReadonlyArray<{ kind: string; Index: number } & Partial<AuditArgParam>>; // 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
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -42,7 +42,7 @@ export type AuditResolver = {
|
|
|
42
42
|
*
|
|
43
43
|
* Never throws. Boot does not fail on a missed `@NoLog`.
|
|
44
44
|
*/
|
|
45
|
-
export function
|
|
45
|
+
export function AuditResolversForUndecoratedArgs(): void {
|
|
46
46
|
if (!configInfo.loggingSettings.graphql.logVariables) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -52,24 +52,34 @@ export function auditResolversForUndecoratedArgs(): void {
|
|
|
52
52
|
mutations: AuditResolver[];
|
|
53
53
|
subscriptions: AuditResolver[];
|
|
54
54
|
};
|
|
55
|
-
|
|
55
|
+
AuditResolverList([
|
|
56
56
|
...storage.queries,
|
|
57
57
|
...storage.mutations,
|
|
58
58
|
...storage.subscriptions,
|
|
59
59
|
]);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/** @deprecated Use {@link AuditResolversForUndecoratedArgs}. */
|
|
63
|
+
export function auditResolversForUndecoratedArgs(): void {
|
|
64
|
+
return AuditResolversForUndecoratedArgs();
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
/**
|
|
63
68
|
* Internal helper exported for test injection. Takes a list of resolver metadata directly,
|
|
64
69
|
* skipping the global `getMetadataStorage()` lookup. The boot-time scan uses this after
|
|
65
70
|
* pulling from the global storage; tests pass in a synthetic fixture.
|
|
66
71
|
*/
|
|
67
|
-
export function
|
|
72
|
+
export function AuditResolverList(resolvers: ReadonlyArray<AuditResolver>): void {
|
|
68
73
|
for (const resolver of resolvers) {
|
|
69
74
|
auditResolver(resolver);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
|
|
78
|
+
/** @deprecated Use {@link AuditResolverList}. */
|
|
79
|
+
export function auditResolverList(resolvers: ReadonlyArray<AuditResolver>): void {
|
|
80
|
+
return AuditResolverList(resolvers);
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
function auditResolver(resolver: AuditResolver): void {
|
|
74
84
|
for (const param of resolver.params ?? []) {
|
|
75
85
|
if (param.kind !== 'arg') {
|
|
@@ -84,10 +94,10 @@ function auditArg(resolver: AuditResolver, argParam: AuditArgParam): void {
|
|
|
84
94
|
if (typeName && INPUT_TYPE_REGEX.test(typeName)) {
|
|
85
95
|
return;
|
|
86
96
|
}
|
|
87
|
-
if (
|
|
97
|
+
if (HasNoLogParameter(resolver.Target, resolver.MethodName, argParam.Index)) {
|
|
88
98
|
return;
|
|
89
99
|
}
|
|
90
|
-
const resolverName = `${resolver.
|
|
100
|
+
const resolverName = `${resolver.Target.name}.${resolver.MethodName}`;
|
|
91
101
|
console.warn(
|
|
92
102
|
`[mj:NoLog audit] Custom resolver ${resolverName} takes argument '${argParam.name}' ` +
|
|
93
103
|
`(type ${typeName ?? 'unknown'}) which is not marked @NoLog. Verify this argument does ` +
|
|
@@ -103,7 +113,7 @@ function auditArg(resolver: AuditResolver, argParam: AuditArgParam): void {
|
|
|
103
113
|
*/
|
|
104
114
|
function readArgTypeName(argParam: AuditArgParam): string | undefined {
|
|
105
115
|
try {
|
|
106
|
-
const type = argParam.
|
|
116
|
+
const type = argParam.GetType();
|
|
107
117
|
if (typeof type === 'function') {
|
|
108
118
|
return (type as { name?: string }).name;
|
|
109
119
|
}
|
|
@@ -12,8 +12,15 @@
|
|
|
12
12
|
*
|
|
13
13
|
* See docs/adr/0001-graphql-variables-logging-tiered-by-verbose.md.
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
15
|
+
export function BuildBoundaryLogPayload(
|
|
16
16
|
operationName: string | undefined,
|
|
17
17
|
): { operationName: string | undefined } {
|
|
18
18
|
return { operationName };
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/** @deprecated Use {@link BuildBoundaryLogPayload}. */
|
|
22
|
+
export function buildBoundaryLogPayload(
|
|
23
|
+
operationName: string | undefined,
|
|
24
|
+
): { operationName: string | undefined } {
|
|
25
|
+
return BuildBoundaryLogPayload(operationName);
|
|
26
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IMetadataProvider } from '@memberjunction/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ShortenForLog } from './shortenForLog.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Input to the redactor. Built per `@Arg` per resolver call by the variables-logging middleware.
|
|
@@ -15,11 +15,11 @@ import { shortenForLog } from './shortenForLog.js';
|
|
|
15
15
|
* this set (decorator-driven) when walking top-level keys.
|
|
16
16
|
*/
|
|
17
17
|
export type RedactionContext = {
|
|
18
|
-
inputTypeName: string;
|
|
19
|
-
rawValue: unknown;
|
|
20
|
-
provider: IMetadataProvider;
|
|
21
|
-
noLogParameter: boolean;
|
|
22
|
-
noLogFields: ReadonlySet<string>;
|
|
18
|
+
inputTypeName: string; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
19
|
+
rawValue: unknown; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
20
|
+
provider: IMetadataProvider; // 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
|
|
21
|
+
noLogParameter: boolean; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
22
|
+
noLogFields: ReadonlySet<string>; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
// Delete is included so DeleteMJ*Input resolvers resolve to their entity (yielding an empty
|
|
@@ -33,7 +33,7 @@ const INPUT_TYPE_REGEX = /^(Create|Update|Delete)(?<name>.+)Input$/;
|
|
|
33
33
|
// type-graphql allows @Field({ name: 'overrideName' }) to rename fields at the
|
|
34
34
|
// GraphQL layer; MJ codegen does not use this. A future maintainer renaming an
|
|
35
35
|
// encrypted field at the GraphQL layer would silently miss redaction.
|
|
36
|
-
export function
|
|
36
|
+
export function RedactArg(ctx: RedactionContext): unknown {
|
|
37
37
|
if (ctx.noLogParameter) {
|
|
38
38
|
return '<redacted>';
|
|
39
39
|
}
|
|
@@ -79,7 +79,7 @@ export function redactArg(ctx: RedactionContext): unknown {
|
|
|
79
79
|
!Array.isArray(ctx.rawValue);
|
|
80
80
|
|
|
81
81
|
if (!canWalk) {
|
|
82
|
-
return
|
|
82
|
+
return ShortenForLog(ctx.rawValue);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const result: Record<string, unknown> = {};
|
|
@@ -87,12 +87,17 @@ export function redactArg(ctx: RedactionContext): unknown {
|
|
|
87
87
|
if (encryptedFieldNames.has(key) || ctx.noLogFields.has(key)) {
|
|
88
88
|
result[key] = '<redacted>';
|
|
89
89
|
} else {
|
|
90
|
-
result[key] =
|
|
90
|
+
result[key] = ShortenForLog(value);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
return result;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/** @deprecated Use {@link RedactArg}. */
|
|
97
|
+
export function redactArg(ctx: RedactionContext): unknown {
|
|
98
|
+
return RedactArg(ctx);
|
|
99
|
+
}
|
|
100
|
+
|
|
96
101
|
const EMPTY_SET: ReadonlySet<string> = new Set<string>();
|
|
97
102
|
|
|
98
103
|
/**
|
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
* Objects whose JSON exceeds `maxLen` and contain nested structure are recursed into so
|
|
5
5
|
* outer keys remain visible.
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function ShortenForLog(value: unknown, maxLen = 300): unknown {
|
|
8
8
|
if (value === null || typeof value !== 'object') return value;
|
|
9
|
-
if (Array.isArray(value)) return value.map((v) =>
|
|
9
|
+
if (Array.isArray(value)) return value.map((v) => ShortenForLog(v, maxLen));
|
|
10
10
|
const json = JSON.stringify(value);
|
|
11
11
|
if (json.length <= maxLen) return json;
|
|
12
12
|
const result: Record<string, unknown> = {};
|
|
13
13
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
14
|
-
result[k] =
|
|
14
|
+
result[k] = ShortenForLog(v, maxLen);
|
|
15
15
|
}
|
|
16
16
|
return result;
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/** @deprecated Use {@link ShortenForLog}. */
|
|
20
|
+
export function shortenForLog(value: unknown, maxLen = 300): unknown {
|
|
21
|
+
return ShortenForLog(value, maxLen);
|
|
22
|
+
}
|