@memberjunction/server 6.2.0-edge.6 → 6.2.0-edge.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +8 -3
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -1
- package/dist/agentSessions/BridgeHostInstance.js +14 -4
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -1
- package/dist/agentSessions/HandoffOfferExpiry.d.ts +10 -0
- package/dist/agentSessions/HandoffOfferExpiry.d.ts.map +1 -0
- package/dist/agentSessions/HandoffOfferExpiry.js +18 -0
- package/dist/agentSessions/HandoffOfferExpiry.js.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +31 -8
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +85 -41
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +14 -4
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +28 -4
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/conversationBrowsers.d.ts +61 -0
- package/dist/agentSessions/conversationBrowsers.d.ts.map +1 -0
- package/dist/agentSessions/conversationBrowsers.js +118 -0
- package/dist/agentSessions/conversationBrowsers.js.map +1 -0
- package/dist/agentSessions/sessionDeadline.d.ts +43 -0
- package/dist/agentSessions/sessionDeadline.d.ts.map +1 -0
- package/dist/agentSessions/sessionDeadline.js +68 -0
- package/dist/agentSessions/sessionDeadline.js.map +1 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +5 -4
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/loginEmailResolution.d.ts +41 -0
- package/dist/auth/loginEmailResolution.d.ts.map +1 -0
- package/dist/auth/loginEmailResolution.js +47 -0
- package/dist/auth/loginEmailResolution.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +50 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +129 -12
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +3 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +23 -5
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +39 -5
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +221 -9
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +1 -1
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +1 -1
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +2 -2
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +7 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +27 -3
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/magicLink/types.js +0 -4
- package/dist/auth/magicLink/types.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +1 -0
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/backgroundSweepConfigUnits.d.ts +231 -0
- package/dist/backgroundSweepConfigUnits.d.ts.map +1 -0
- package/dist/backgroundSweepConfigUnits.js +180 -0
- package/dist/backgroundSweepConfigUnits.js.map +1 -0
- package/dist/config.d.ts +906 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +35 -4
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +3 -1
- package/dist/coreRoutes.d.ts.map +1 -1
- package/dist/coreRoutes.js +6 -4
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +228 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +1163 -6
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +11 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +27 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +50 -5
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +321 -132
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +47 -7
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -35
- package/dist/index.js.map +1 -1
- package/dist/integration/ConnectionPause.d.ts +121 -0
- package/dist/integration/ConnectionPause.d.ts.map +1 -0
- package/dist/integration/ConnectionPause.js +183 -0
- package/dist/integration/ConnectionPause.js.map +1 -0
- package/dist/integration/CustomColumnPromoter.d.ts +72 -6
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +87 -46
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +78 -4
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +199 -5
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/integration/InactiveRowWarnings.d.ts +31 -0
- package/dist/integration/InactiveRowWarnings.d.ts.map +1 -1
- package/dist/integration/InactiveRowWarnings.js +29 -0
- package/dist/integration/InactiveRowWarnings.js.map +1 -1
- package/dist/integration/ObjectNamesByID.d.ts +28 -0
- package/dist/integration/ObjectNamesByID.d.ts.map +1 -0
- package/dist/integration/ObjectNamesByID.js +87 -0
- package/dist/integration/ObjectNamesByID.js.map +1 -0
- package/dist/integration/PostRestartIntrospect.d.ts +26 -0
- package/dist/integration/PostRestartIntrospect.d.ts.map +1 -0
- package/dist/integration/PostRestartIntrospect.js +27 -0
- package/dist/integration/PostRestartIntrospect.js.map +1 -0
- package/dist/integration/RSUPostRestartProgress.d.ts +176 -0
- package/dist/integration/RSUPostRestartProgress.d.ts.map +1 -0
- package/dist/integration/RSUPostRestartProgress.js +323 -0
- package/dist/integration/RSUPostRestartProgress.js.map +1 -0
- package/dist/integration/RSUProgressBridge.d.ts +41 -2
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -1
- package/dist/integration/RSUProgressBridge.js +84 -1
- package/dist/integration/RSUProgressBridge.js.map +1 -1
- package/dist/integration/RunArtifactAuthorization.d.ts +39 -0
- package/dist/integration/RunArtifactAuthorization.d.ts.map +1 -0
- package/dist/integration/RunArtifactAuthorization.js +45 -0
- package/dist/integration/RunArtifactAuthorization.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +9 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -1
- package/dist/integration/SchemaRefreshLaunch.js +3 -2
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -1
- package/dist/integration/ScopedFieldsForBuild.d.ts +46 -0
- package/dist/integration/ScopedFieldsForBuild.d.ts.map +1 -0
- package/dist/integration/ScopedFieldsForBuild.js +91 -0
- package/dist/integration/ScopedFieldsForBuild.js.map +1 -0
- package/dist/integration/TargetConfigGuard.d.ts +40 -0
- package/dist/integration/TargetConfigGuard.d.ts.map +1 -0
- package/dist/integration/TargetConfigGuard.js +40 -0
- package/dist/integration/TargetConfigGuard.js.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +2 -3
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +15 -0
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +22 -0
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +2 -0
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +1 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +4 -7
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/requestOrigin.d.ts +22 -0
- package/dist/requestOrigin.d.ts.map +1 -0
- package/dist/requestOrigin.js +60 -0
- package/dist/requestOrigin.js.map +1 -0
- package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +6 -2
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.js +2 -1
- package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +2 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts +6 -0
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.js +30 -7
- package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +34 -13
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +401 -11
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2690 -1305
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +13 -2
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +36 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +174 -87
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +1 -0
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +6 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +36 -5
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +62 -10
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +217 -34
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +24 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +185 -67
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +5 -3
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +19 -18
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +3 -1
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +2 -0
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +6 -2
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +11 -5
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +2 -4
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +2 -1
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +3 -1
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +11 -2
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js +6 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +2 -26
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +6 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +38 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +1 -0
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/WorkQueueHostService.d.ts +2 -1
- package/dist/services/WorkQueueHostService.d.ts.map +1 -1
- package/dist/services/WorkQueueHostService.js +19 -4
- package/dist/services/WorkQueueHostService.js.map +1 -1
- package/dist/services/workQueueConfig.d.ts +2 -2
- package/dist/services/workQueueConfig.js +5 -5
- package/dist/services/workQueueConfig.js.map +1 -1
- package/dist/sharedCache.js +1 -1
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +98 -98
- package/src/__tests__/APIKeyScopeAuth.test.ts +4 -8
- package/src/__tests__/ActiveOperations.test.ts +68 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +13 -0
- package/src/__tests__/AssertTargetConfigs.test.ts +75 -0
- package/src/__tests__/BatchApplyParity.test.ts +109 -0
- package/src/__tests__/BridgeHostInstance.test.ts +42 -0
- package/src/__tests__/CollectInactiveRowWarnings.test.ts +115 -0
- package/src/__tests__/ConnectionPause.test.ts +192 -0
- package/src/__tests__/ConnectionPauseResolver.test.ts +166 -0
- package/src/__tests__/ConnectionPauseSave.test.ts +143 -0
- package/src/__tests__/CustomColumnPromoterCompletion.test.ts +142 -0
- package/src/__tests__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
- package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
- package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
- package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
- package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -0
- package/src/__tests__/HandoffOfferExpiry.test.ts +40 -0
- package/src/__tests__/IntegrationRunArtifactAuthorization.test.ts +126 -0
- package/src/__tests__/MagicLinkKeys.test.ts +102 -0
- package/src/__tests__/MediaAccessKeys.test.ts +57 -10
- package/src/__tests__/NewArrivalsDefaultDisabled.test.ts +50 -0
- package/src/__tests__/ObjectNamesByID.test.ts +176 -0
- package/src/__tests__/PostRestartMapsInCatalogScope.test.ts +146 -0
- package/src/__tests__/QuerySystemUserResolver.childRows.test.ts +80 -0
- package/src/__tests__/QuerySystemUserResolver.collision.test.ts +200 -0
- package/src/__tests__/QuerySystemUserResolver.permissions.test.ts +132 -0
- package/src/__tests__/RSUPostRestartProgress.test.ts +343 -0
- package/src/__tests__/RSUProgressBridge.test.ts +188 -5
- package/src/__tests__/RSUStartupSweepWiring.test.ts +30 -0
- package/src/__tests__/ReactivateRefreshMessage.test.ts +10 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +22 -0
- package/src/__tests__/{RefreshAdoptsNewColumns.test.ts → RefreshReportsNewColumns.test.ts} +25 -16
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +287 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +3 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +6 -4
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +323 -26
- package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +53 -2
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +60 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +4 -0
- package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
- package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +87 -12
- package/src/__tests__/SchemaEvolutionCustomColumns.test.ts +119 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +24 -2
- package/src/__tests__/ScopedFieldsForBuild.test.ts +192 -0
- package/src/__tests__/SessionJanitor.test.ts +195 -4
- package/src/__tests__/SessionManager.test.ts +69 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
- package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
- package/src/__tests__/ViewOperationsHandler.test.ts +2 -5
- package/src/__tests__/WorkQueueHostService.test.ts +25 -7
- package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
- package/src/__tests__/contextRequestOrigin.test.ts +105 -0
- package/src/__tests__/conversationBrowsers.test.ts +62 -0
- package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
- package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
- package/src/__tests__/realtimeRecordingHandler.test.ts +7 -2
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +79 -1
- package/src/__tests__/requestOrigin.test.ts +104 -0
- package/src/__tests__/securityHardeningPr6034.test.ts +120 -0
- package/src/__tests__/sessionDeadline.test.ts +51 -0
- package/src/__tests__/sharedCache.test.ts +11 -0
- package/src/__tests__/unifiedAuth.test.ts +73 -1
- package/src/agentSessions/BridgeHostInstance.ts +20 -5
- package/src/agentSessions/HandoffOfferExpiry.ts +18 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +1 -0
- package/src/agentSessions/SessionJanitor.ts +92 -42
- package/src/agentSessions/SessionManager.ts +38 -8
- package/src/agentSessions/conversationBrowsers.ts +143 -0
- package/src/agentSessions/sessionDeadline.ts +81 -0
- package/src/auth/APIKeyScopeAuth.ts +5 -4
- package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
- package/src/auth/loginEmailResolution.ts +67 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +146 -14
- package/src/auth/magicLink/MagicLinkRouter.ts +33 -6
- package/src/auth/magicLink/MagicLinkService.ts +250 -10
- package/src/auth/magicLink/index.ts +1 -1
- package/src/auth/magicLink/redeemLanding.ts +7 -4
- package/src/auth/magicLink/types.ts +28 -3
- package/src/auth/newUsers.ts +1 -0
- package/src/backgroundSweepConfigUnits.ts +213 -0
- package/src/config.ts +69 -0
- package/src/context.ts +39 -6
- package/src/coreRoutes.ts +14 -7
- package/src/generated/graphql-schemas/__mj.ts +822 -7
- package/src/generic/OrphanedConversationDetailReconciler.ts +32 -1
- package/src/generic/ResolverBase.ts +414 -143
- package/src/generic/RunViewResolver.ts +96 -49
- package/src/index.ts +201 -35
- package/src/integration/ConnectionPause.ts +222 -0
- package/src/integration/CustomColumnPromoter.ts +123 -53
- package/src/integration/EntityMapLifecycle.ts +229 -6
- package/src/integration/InactiveRowWarnings.ts +50 -0
- package/src/integration/ObjectNamesByID.ts +97 -0
- package/src/integration/PostRestartIntrospect.ts +49 -0
- package/src/integration/RSUPostRestartProgress.ts +359 -0
- package/src/integration/RSUProgressBridge.ts +85 -2
- package/src/integration/RunArtifactAuthorization.ts +65 -0
- package/src/integration/SchemaRefreshLaunch.ts +12 -2
- package/src/integration/ScopedFieldsForBuild.ts +113 -0
- package/src/integration/TargetConfigGuard.ts +71 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +2 -6
- package/src/realtimeSessions/sessionAccess.ts +30 -0
- package/src/realtimeWidget/WidgetSessionService.ts +2 -0
- package/src/realtimeWidget/visitorIdentity.ts +1 -0
- package/src/realtimeWidget/widgetCore.ts +4 -8
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -0
- package/src/requestOrigin.ts +64 -0
- package/src/resolvers/AgentSessionResolver.ts +6 -2
- package/src/resolvers/AutotagPipelineResolver.ts +2 -1
- package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
- package/src/resolvers/GetDataResolver.ts +35 -13
- package/src/resolvers/IntegrationDiscoveryResolver.ts +1522 -203
- package/src/resolvers/MCPResolver.ts +15 -2
- package/src/resolvers/QuerySystemUserResolver.ts +197 -98
- package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +40 -7
- package/src/resolvers/RemoteBrowserActionResolver.ts +242 -32
- package/src/resolvers/RunAIAgentResolver.ts +265 -86
- package/src/resolvers/RunAIPromptResolver.ts +18 -18
- package/src/resolvers/RunTemplateResolver.ts +3 -1
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
- package/src/resolvers/meetingRecordingRegistration.ts +2 -0
- package/src/rest/MediaAccessKeys.ts +6 -2
- package/src/rest/OAuthCallbackHandler.ts +13 -5
- package/src/rest/RealtimeRecordingHandler.ts +5 -9
- package/src/rest/ViewOperationsHandler.ts +2 -1
- package/src/rest/setupRESTEndpoints.ts +11 -2
- package/src/services/DurableEntityActionTaskSubmitter.ts +10 -2
- package/src/services/TaskGraphActionRunner.ts +2 -23
- package/src/services/TaskGraphAgentRunner.ts +43 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +1 -0
- package/src/services/WorkQueueHostService.ts +26 -4
- package/src/services/workQueueConfig.ts +5 -5
- package/src/sharedCache.ts +1 -1
- package/src/types.ts +18 -0
- package/src/services/TaskOrchestration-Integration.md +0 -188
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "6.2.0-edge.
|
|
3
|
+
"version": "6.2.0-edge.7",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -19,101 +19,101 @@
|
|
|
19
19
|
"@as-integrations/express5": "^1.0.0",
|
|
20
20
|
"@graphql-tools/schema": "^10.0.38",
|
|
21
21
|
"@graphql-tools/utils": "^11.0.0",
|
|
22
|
-
"@memberjunction/actions": "6.2.0-edge.
|
|
23
|
-
"@memberjunction/actions-apollo": "6.2.0-edge.
|
|
24
|
-
"@memberjunction/actions-base": "6.2.0-edge.
|
|
25
|
-
"@memberjunction/actions-bizapps-accounting": "6.2.0-edge.
|
|
26
|
-
"@memberjunction/actions-bizapps-crm": "6.2.0-edge.
|
|
27
|
-
"@memberjunction/actions-bizapps-formbuilders": "6.2.0-edge.
|
|
28
|
-
"@memberjunction/actions-bizapps-lms": "6.2.0-edge.
|
|
29
|
-
"@memberjunction/actions-bizapps-social": "6.2.0-edge.
|
|
30
|
-
"@memberjunction/actions-peopledatalabs": "6.2.0-edge.
|
|
31
|
-
"@memberjunction/ai": "6.2.0-edge.
|
|
32
|
-
"@memberjunction/ai-agent-manager": "6.2.0-edge.
|
|
33
|
-
"@memberjunction/ai-agent-manager-actions": "6.2.0-edge.
|
|
34
|
-
"@memberjunction/ai-agents": "6.2.0-edge.
|
|
35
|
-
"@memberjunction/ai-bridge-base": "6.2.0-edge.
|
|
36
|
-
"@memberjunction/ai-bridge-ringcentral": "6.2.0-edge.
|
|
37
|
-
"@memberjunction/ai-bridge-server": "6.2.0-edge.
|
|
38
|
-
"@memberjunction/ai-bridge-teams": "6.2.0-edge.
|
|
39
|
-
"@memberjunction/ai-bridge-twilio": "6.2.0-edge.
|
|
40
|
-
"@memberjunction/ai-bridge-vonage": "6.2.0-edge.
|
|
41
|
-
"@memberjunction/ai-core-plus": "6.2.0-edge.
|
|
42
|
-
"@memberjunction/ai-engine-base": "6.2.0-edge.
|
|
43
|
-
"@memberjunction/ai-mcp-client": "6.2.0-edge.
|
|
44
|
-
"@memberjunction/ai-prompts": "6.2.0-edge.
|
|
45
|
-
"@memberjunction/ai-provider-bundle": "6.2.0-edge.
|
|
46
|
-
"@memberjunction/ai-vector-dupe": "6.2.0-edge.
|
|
47
|
-
"@memberjunction/ai-vector-sync": "6.2.0-edge.
|
|
48
|
-
"@memberjunction/ai-vectordb": "6.2.0-edge.
|
|
49
|
-
"@memberjunction/ai-vectors-pinecone": "6.2.0-edge.
|
|
50
|
-
"@memberjunction/aiengine": "6.2.0-edge.
|
|
51
|
-
"@memberjunction/api-keys": "6.2.0-edge.
|
|
52
|
-
"@memberjunction/auth-providers": "6.2.0-edge.
|
|
53
|
-
"@memberjunction/clustering-engine": "6.2.0-edge.
|
|
54
|
-
"@memberjunction/codegen-lib": "6.2.0-edge.
|
|
55
|
-
"@memberjunction/communication-engine": "6.2.0-edge.
|
|
56
|
-
"@memberjunction/communication-ms-graph": "6.2.0-edge.
|
|
57
|
-
"@memberjunction/communication-sendgrid": "6.2.0-edge.
|
|
58
|
-
"@memberjunction/communication-types": "6.2.0-edge.
|
|
59
|
-
"@memberjunction/component-registry-client-sdk": "6.2.0-edge.
|
|
60
|
-
"@memberjunction/computer-use": "6.2.0-edge.
|
|
61
|
-
"@memberjunction/computer-use-engine": "6.2.0-edge.
|
|
62
|
-
"@memberjunction/config": "6.2.0-edge.
|
|
63
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
64
|
-
"@memberjunction/core-actions": "6.2.0-edge.
|
|
65
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
66
|
-
"@memberjunction/core-entities-server": "6.2.0-edge.
|
|
67
|
-
"@memberjunction/credentials": "6.2.0-edge.
|
|
68
|
-
"@memberjunction/data-context": "6.2.0-edge.
|
|
69
|
-
"@memberjunction/data-context-server": "6.2.0-edge.
|
|
70
|
-
"@memberjunction/doc-utils": "6.2.0-edge.
|
|
71
|
-
"@memberjunction/encryption": "6.2.0-edge.
|
|
72
|
-
"@memberjunction/entity-communications-base": "6.2.0-edge.
|
|
73
|
-
"@memberjunction/entity-communications-server": "6.2.0-edge.
|
|
74
|
-
"@memberjunction/esignature": "6.2.0-edge.
|
|
75
|
-
"@memberjunction/external-change-detection": "6.2.0-edge.
|
|
76
|
-
"@memberjunction/generic-database-provider": "6.2.0-edge.
|
|
77
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
78
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
79
|
-
"@memberjunction/integration-engine": "6.2.0-edge.
|
|
80
|
-
"@memberjunction/integration-engine-base": "6.2.0-edge.
|
|
81
|
-
"@memberjunction/integration-progress-artifacts": "6.2.0-edge.
|
|
82
|
-
"@memberjunction/integration-schema-builder": "6.2.0-edge.
|
|
83
|
-
"@memberjunction/interactive-component-types": "6.2.0-edge.
|
|
84
|
-
"@memberjunction/lists": "6.2.0-edge.
|
|
85
|
-
"@memberjunction/lists-base": "6.2.0-edge.
|
|
86
|
-
"@memberjunction/livekit-room-server": "6.2.0-edge.
|
|
87
|
-
"@memberjunction/network-utils": "6.2.0-edge.
|
|
88
|
-
"@memberjunction/notifications": "6.2.0-edge.
|
|
89
|
-
"@memberjunction/postgresql-dataprovider": "6.2.0-edge.
|
|
90
|
-
"@memberjunction/queue": "6.2.0-edge.
|
|
91
|
-
"@memberjunction/record-cloning": "6.2.0-edge.
|
|
92
|
-
"@memberjunction/record-comparison": "6.2.0-edge.
|
|
93
|
-
"@memberjunction/redis-provider": "6.2.0-edge.
|
|
94
|
-
"@memberjunction/remote-browser-base": "6.2.0-edge.
|
|
95
|
-
"@memberjunction/remote-browser-cdp": "6.2.0-edge.
|
|
96
|
-
"@memberjunction/remote-browser-selfhost": "6.2.0-edge.
|
|
97
|
-
"@memberjunction/remote-browser-server": "6.2.0-edge.
|
|
98
|
-
"@memberjunction/scheduling-actions": "6.2.0-edge.
|
|
99
|
-
"@memberjunction/scheduling-base-types": "6.2.0-edge.
|
|
100
|
-
"@memberjunction/scheduling-engine": "6.2.0-edge.
|
|
101
|
-
"@memberjunction/scheduling-engine-base": "6.2.0-edge.
|
|
102
|
-
"@memberjunction/schema-engine": "6.2.0-edge.
|
|
103
|
-
"@memberjunction/search-engine": "6.2.0-edge.
|
|
104
|
-
"@memberjunction/server-extensions-core": "6.2.0-edge.
|
|
105
|
-
"@memberjunction/sql-dialect": "6.2.0-edge.
|
|
106
|
-
"@memberjunction/sql-parser": "6.2.0-edge.
|
|
107
|
-
"@memberjunction/sqlserver-dataprovider": "6.2.0-edge.
|
|
108
|
-
"@memberjunction/storage": "6.2.0-edge.
|
|
109
|
-
"@memberjunction/tag-engine": "6.2.0-edge.
|
|
110
|
-
"@memberjunction/tag-engine-base": "6.2.0-edge.
|
|
111
|
-
"@memberjunction/task-graph": "6.2.0-edge.
|
|
112
|
-
"@memberjunction/templates": "6.2.0-edge.
|
|
113
|
-
"@memberjunction/testing-engine": "6.2.0-edge.
|
|
114
|
-
"@memberjunction/testing-engine-base": "6.2.0-edge.
|
|
115
|
-
"@memberjunction/version-history": "6.2.0-edge.
|
|
116
|
-
"@memberjunction/work-queue-engine": "6.2.0-edge.
|
|
22
|
+
"@memberjunction/actions": "6.2.0-edge.7",
|
|
23
|
+
"@memberjunction/actions-apollo": "6.2.0-edge.7",
|
|
24
|
+
"@memberjunction/actions-base": "6.2.0-edge.7",
|
|
25
|
+
"@memberjunction/actions-bizapps-accounting": "6.2.0-edge.7",
|
|
26
|
+
"@memberjunction/actions-bizapps-crm": "6.2.0-edge.7",
|
|
27
|
+
"@memberjunction/actions-bizapps-formbuilders": "6.2.0-edge.7",
|
|
28
|
+
"@memberjunction/actions-bizapps-lms": "6.2.0-edge.7",
|
|
29
|
+
"@memberjunction/actions-bizapps-social": "6.2.0-edge.7",
|
|
30
|
+
"@memberjunction/actions-peopledatalabs": "6.2.0-edge.7",
|
|
31
|
+
"@memberjunction/ai": "6.2.0-edge.7",
|
|
32
|
+
"@memberjunction/ai-agent-manager": "6.2.0-edge.7",
|
|
33
|
+
"@memberjunction/ai-agent-manager-actions": "6.2.0-edge.7",
|
|
34
|
+
"@memberjunction/ai-agents": "6.2.0-edge.7",
|
|
35
|
+
"@memberjunction/ai-bridge-base": "6.2.0-edge.7",
|
|
36
|
+
"@memberjunction/ai-bridge-ringcentral": "6.2.0-edge.7",
|
|
37
|
+
"@memberjunction/ai-bridge-server": "6.2.0-edge.7",
|
|
38
|
+
"@memberjunction/ai-bridge-teams": "6.2.0-edge.7",
|
|
39
|
+
"@memberjunction/ai-bridge-twilio": "6.2.0-edge.7",
|
|
40
|
+
"@memberjunction/ai-bridge-vonage": "6.2.0-edge.7",
|
|
41
|
+
"@memberjunction/ai-core-plus": "6.2.0-edge.7",
|
|
42
|
+
"@memberjunction/ai-engine-base": "6.2.0-edge.7",
|
|
43
|
+
"@memberjunction/ai-mcp-client": "6.2.0-edge.7",
|
|
44
|
+
"@memberjunction/ai-prompts": "6.2.0-edge.7",
|
|
45
|
+
"@memberjunction/ai-provider-bundle": "6.2.0-edge.7",
|
|
46
|
+
"@memberjunction/ai-vector-dupe": "6.2.0-edge.7",
|
|
47
|
+
"@memberjunction/ai-vector-sync": "6.2.0-edge.7",
|
|
48
|
+
"@memberjunction/ai-vectordb": "6.2.0-edge.7",
|
|
49
|
+
"@memberjunction/ai-vectors-pinecone": "6.2.0-edge.7",
|
|
50
|
+
"@memberjunction/aiengine": "6.2.0-edge.7",
|
|
51
|
+
"@memberjunction/api-keys": "6.2.0-edge.7",
|
|
52
|
+
"@memberjunction/auth-providers": "6.2.0-edge.7",
|
|
53
|
+
"@memberjunction/clustering-engine": "6.2.0-edge.7",
|
|
54
|
+
"@memberjunction/codegen-lib": "6.2.0-edge.7",
|
|
55
|
+
"@memberjunction/communication-engine": "6.2.0-edge.7",
|
|
56
|
+
"@memberjunction/communication-ms-graph": "6.2.0-edge.7",
|
|
57
|
+
"@memberjunction/communication-sendgrid": "6.2.0-edge.7",
|
|
58
|
+
"@memberjunction/communication-types": "6.2.0-edge.7",
|
|
59
|
+
"@memberjunction/component-registry-client-sdk": "6.2.0-edge.7",
|
|
60
|
+
"@memberjunction/computer-use": "6.2.0-edge.7",
|
|
61
|
+
"@memberjunction/computer-use-engine": "6.2.0-edge.7",
|
|
62
|
+
"@memberjunction/config": "6.2.0-edge.7",
|
|
63
|
+
"@memberjunction/core": "6.2.0-edge.7",
|
|
64
|
+
"@memberjunction/core-actions": "6.2.0-edge.7",
|
|
65
|
+
"@memberjunction/core-entities": "6.2.0-edge.7",
|
|
66
|
+
"@memberjunction/core-entities-server": "6.2.0-edge.7",
|
|
67
|
+
"@memberjunction/credentials": "6.2.0-edge.7",
|
|
68
|
+
"@memberjunction/data-context": "6.2.0-edge.7",
|
|
69
|
+
"@memberjunction/data-context-server": "6.2.0-edge.7",
|
|
70
|
+
"@memberjunction/doc-utils": "6.2.0-edge.7",
|
|
71
|
+
"@memberjunction/encryption": "6.2.0-edge.7",
|
|
72
|
+
"@memberjunction/entity-communications-base": "6.2.0-edge.7",
|
|
73
|
+
"@memberjunction/entity-communications-server": "6.2.0-edge.7",
|
|
74
|
+
"@memberjunction/esignature": "6.2.0-edge.7",
|
|
75
|
+
"@memberjunction/external-change-detection": "6.2.0-edge.7",
|
|
76
|
+
"@memberjunction/generic-database-provider": "6.2.0-edge.7",
|
|
77
|
+
"@memberjunction/global": "6.2.0-edge.7",
|
|
78
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.7",
|
|
79
|
+
"@memberjunction/integration-engine": "6.2.0-edge.7",
|
|
80
|
+
"@memberjunction/integration-engine-base": "6.2.0-edge.7",
|
|
81
|
+
"@memberjunction/integration-progress-artifacts": "6.2.0-edge.7",
|
|
82
|
+
"@memberjunction/integration-schema-builder": "6.2.0-edge.7",
|
|
83
|
+
"@memberjunction/interactive-component-types": "6.2.0-edge.7",
|
|
84
|
+
"@memberjunction/lists": "6.2.0-edge.7",
|
|
85
|
+
"@memberjunction/lists-base": "6.2.0-edge.7",
|
|
86
|
+
"@memberjunction/livekit-room-server": "6.2.0-edge.7",
|
|
87
|
+
"@memberjunction/network-utils": "6.2.0-edge.7",
|
|
88
|
+
"@memberjunction/notifications": "6.2.0-edge.7",
|
|
89
|
+
"@memberjunction/postgresql-dataprovider": "6.2.0-edge.7",
|
|
90
|
+
"@memberjunction/queue": "6.2.0-edge.7",
|
|
91
|
+
"@memberjunction/record-cloning": "6.2.0-edge.7",
|
|
92
|
+
"@memberjunction/record-comparison": "6.2.0-edge.7",
|
|
93
|
+
"@memberjunction/redis-provider": "6.2.0-edge.7",
|
|
94
|
+
"@memberjunction/remote-browser-base": "6.2.0-edge.7",
|
|
95
|
+
"@memberjunction/remote-browser-cdp": "6.2.0-edge.7",
|
|
96
|
+
"@memberjunction/remote-browser-selfhost": "6.2.0-edge.7",
|
|
97
|
+
"@memberjunction/remote-browser-server": "6.2.0-edge.7",
|
|
98
|
+
"@memberjunction/scheduling-actions": "6.2.0-edge.7",
|
|
99
|
+
"@memberjunction/scheduling-base-types": "6.2.0-edge.7",
|
|
100
|
+
"@memberjunction/scheduling-engine": "6.2.0-edge.7",
|
|
101
|
+
"@memberjunction/scheduling-engine-base": "6.2.0-edge.7",
|
|
102
|
+
"@memberjunction/schema-engine": "6.2.0-edge.7",
|
|
103
|
+
"@memberjunction/search-engine": "6.2.0-edge.7",
|
|
104
|
+
"@memberjunction/server-extensions-core": "6.2.0-edge.7",
|
|
105
|
+
"@memberjunction/sql-dialect": "6.2.0-edge.7",
|
|
106
|
+
"@memberjunction/sql-parser": "6.2.0-edge.7",
|
|
107
|
+
"@memberjunction/sqlserver-dataprovider": "6.2.0-edge.7",
|
|
108
|
+
"@memberjunction/storage": "6.2.0-edge.7",
|
|
109
|
+
"@memberjunction/tag-engine": "6.2.0-edge.7",
|
|
110
|
+
"@memberjunction/tag-engine-base": "6.2.0-edge.7",
|
|
111
|
+
"@memberjunction/task-graph": "6.2.0-edge.7",
|
|
112
|
+
"@memberjunction/templates": "6.2.0-edge.7",
|
|
113
|
+
"@memberjunction/testing-engine": "6.2.0-edge.7",
|
|
114
|
+
"@memberjunction/testing-engine-base": "6.2.0-edge.7",
|
|
115
|
+
"@memberjunction/version-history": "6.2.0-edge.7",
|
|
116
|
+
"@memberjunction/work-queue-engine": "6.2.0-edge.7",
|
|
117
117
|
"@octokit/auth-app": "^7.1.5",
|
|
118
118
|
"@octokit/rest": "^21.1.1",
|
|
119
119
|
"@types/compression": "^1.8.1",
|
|
@@ -150,10 +150,10 @@
|
|
|
150
150
|
"uuid": "^13.0.0",
|
|
151
151
|
"ws": "^8.19.0",
|
|
152
152
|
"zod": "^3.25.0",
|
|
153
|
-
"@memberjunction/theme-engine": "6.2.0-edge.
|
|
153
|
+
"@memberjunction/theme-engine": "6.2.0-edge.7"
|
|
154
154
|
},
|
|
155
155
|
"devDependencies": {
|
|
156
|
-
"@memberjunction/conversations-runtime": "6.2.0-edge.
|
|
156
|
+
"@memberjunction/conversations-runtime": "6.2.0-edge.7",
|
|
157
157
|
"@types/express": "^5.0.6",
|
|
158
158
|
"pkgroll": "2.23.0",
|
|
159
159
|
"rimraf": "6.1.2",
|
|
@@ -155,18 +155,14 @@ describe('CheckAPIKeyScope', () => {
|
|
|
155
155
|
expect(result).toEqual({ Allowed: false, Checked: true, Reason: 'API key not found' });
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
it('
|
|
159
|
-
// The apiKeyId originates server-side (context.userPayload.apiKeyId, set only
|
|
160
|
-
// after key validation), so the trust boundary is upstream — but this layer
|
|
161
|
-
// performs no escaping of its own. Pinned so that if the call site ever
|
|
162
|
-
// starts accepting client-supplied IDs, this assertion is the reminder.
|
|
158
|
+
it('escapes single quotes in apiKeyId before interpolating into the RunView ExtraFilter', async () => {
|
|
163
159
|
const hostile = "abc' OR '1'='1";
|
|
164
160
|
keyLookup = { Success: true, Results: [] };
|
|
165
161
|
|
|
166
162
|
await CheckAPIKeyScope(hostile, 'view:run', makeUser(), { throwOnDenied: false });
|
|
167
163
|
|
|
168
164
|
expect(capturedRunViewParams[0].EntityName).toBe('MJ: API Keys');
|
|
169
|
-
expect(capturedRunViewParams[0].ExtraFilter).toBe(`ID='abc' OR '1'='1'`);
|
|
165
|
+
expect(capturedRunViewParams[0].ExtraFilter).toBe(`ID='abc'' OR ''1''=''1'`);
|
|
170
166
|
});
|
|
171
167
|
});
|
|
172
168
|
|
|
@@ -206,7 +202,7 @@ describe('CheckAPIKeyScope', () => {
|
|
|
206
202
|
expect(result).toEqual({ Allowed: false, Checked: true, Reason: 'Application is not active: MJAPI' });
|
|
207
203
|
});
|
|
208
204
|
|
|
209
|
-
it('
|
|
205
|
+
it('escapes single quotes in applicationName before interpolating into the application filter', async () => {
|
|
210
206
|
appLookup = { Success: true, Results: [] };
|
|
211
207
|
const hostile = "MJAPI' OR Name<>'";
|
|
212
208
|
|
|
@@ -216,7 +212,7 @@ describe('CheckAPIKeyScope', () => {
|
|
|
216
212
|
});
|
|
217
213
|
|
|
218
214
|
expect(capturedRunViewParams[1].EntityName).toBe('MJ: API Applications');
|
|
219
|
-
expect(capturedRunViewParams[1].ExtraFilter).toBe(`Name='MJAPI' OR Name<>''`);
|
|
215
|
+
expect(capturedRunViewParams[1].ExtraFilter).toBe(`Name='MJAPI'' OR Name<>'''`);
|
|
220
216
|
});
|
|
221
217
|
});
|
|
222
218
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plan.md: "In the UI for the integration ... there shouldbe an area that shows thigns that are
|
|
3
|
+
* running actively, this can be syncs, rsu, discovery, etc." and, crucially, "Let us say i clear
|
|
4
|
+
* browser cache and then i go to that integration page, i should see the same steps i mentioned
|
|
5
|
+
* hapepning there to". Everything here is derived server-side for exactly that reason.
|
|
6
|
+
*
|
|
7
|
+
* A surface previously had to fan out to four queries and stitch them, and each got the
|
|
8
|
+
* attribution wrong in its own way. The two rules that kept breaking are pinned below.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect } from 'vitest';
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
|
|
14
|
+
const SRC = readFileSync(join(__dirname, '..', 'resolvers', 'IntegrationDiscoveryResolver.ts'), 'utf-8');
|
|
15
|
+
|
|
16
|
+
function methodBody(name: string): string {
|
|
17
|
+
const i = SRC.indexOf(`async ${name}(`);
|
|
18
|
+
expect(i, `${name} not found`).toBeGreaterThan(-1);
|
|
19
|
+
const rest = SRC.slice(i);
|
|
20
|
+
const end = rest.search(/\n @(Query|Mutation)\(/);
|
|
21
|
+
return end === -1 ? rest : rest.slice(0, end);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('IntegrationGetActiveOperations', () => {
|
|
25
|
+
const body = () => methodBody('IntegrationGetActiveOperations');
|
|
26
|
+
|
|
27
|
+
it('exists and is authorized per connection', () => {
|
|
28
|
+
expect(SRC).toMatch(/@Query\(\(\) => ActiveOperationsOutput\)/);
|
|
29
|
+
expect(body()).toMatch(/userCanReadCompanyIntegration\(/);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('covers sync, in-flight runs and RSU in ONE call', () => {
|
|
33
|
+
const b = body();
|
|
34
|
+
expect(b).toMatch(/GetSyncProgressAsync\(/);
|
|
35
|
+
expect(b).toMatch(/ListRuns\(/);
|
|
36
|
+
expect(b).toMatch(/RuntimeSchemaManager\.Instance\.GetStatus\(\)/);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('never narrates a ConnectorCreation run as a sync', () => {
|
|
40
|
+
// it fetches nothing; calling it a sync made first-time setup claim record counts it never had
|
|
41
|
+
const b = body();
|
|
42
|
+
expect(b).toMatch(/kind === 'SyncRun'/);
|
|
43
|
+
expect(b).not.toMatch(/Kind: 'sync'[\s\S]{0,200}ConnectorCreation/);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('labels a process-wide RSU as workspace scope, not this connection', () => {
|
|
47
|
+
const b = body();
|
|
48
|
+
expect(b).toMatch(/rsuNamesThisConnection/);
|
|
49
|
+
expect(b).toMatch(/Scope: 'workspace'/);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('only reports the process RSU when no artifact tied one to this connection', () => {
|
|
53
|
+
expect(body()).toMatch(/rsu\?\.Running && !rsuNamesThisConnection/);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('marks only the sync cancellable', () => {
|
|
57
|
+
const b = body();
|
|
58
|
+
const syncBlock = b.slice(b.indexOf("Kind: 'sync'"), b.indexOf("Kind: 'sync'") + 700);
|
|
59
|
+
expect(syncBlock).toMatch(/Cancellable: true/);
|
|
60
|
+
const rsuBlock = b.slice(b.indexOf("Scope: 'workspace'"));
|
|
61
|
+
expect(rsuBlock).toMatch(/Cancellable: false/);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('surfaces the maintenance lock reason, so a refusal can say why', () => {
|
|
65
|
+
expect(body()).toMatch(/GetMaintenanceLock\(/);
|
|
66
|
+
expect(body()).toMatch(/MaintenanceLockReason/);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -128,6 +128,19 @@ describe('CloseAgentSession close reason (MJ#6013)', () => {
|
|
|
128
128
|
expect(closeSessionMock).toHaveBeenCalledWith(SESSION, expect.anything(), provider, 'Explicit');
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
+
it('a client may stamp TimeLimit (CloseSession verifies it); Janitor, Shutdown and Idle are still refused', async () => {
|
|
132
|
+
const resolver = new AgentSessionResolver();
|
|
133
|
+
const provider = makeProvider(true, 'visitor-1');
|
|
134
|
+
const ctx = makeCtx(guest('visitor-1'), provider);
|
|
135
|
+
await expect(resolver.CloseAgentSession(SESSION, ctx, 'TimeLimit')).resolves.toBe(true);
|
|
136
|
+
expect(closeSessionMock).toHaveBeenCalledWith(SESSION, expect.anything(), provider, 'TimeLimit');
|
|
137
|
+
closeSessionMock.mockClear();
|
|
138
|
+
for (const reason of ['Janitor', 'Shutdown', 'Idle']) {
|
|
139
|
+
await expect(resolver.CloseAgentSession(SESSION, ctx, reason)).rejects.toThrow(/Unsupported close reason/);
|
|
140
|
+
}
|
|
141
|
+
expect(closeSessionMock).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
|
|
131
144
|
it('refuses a reason only the server may stamp', async () => {
|
|
132
145
|
const resolver = new AgentSessionResolver();
|
|
133
146
|
const provider = makeProvider(true, 'visitor-1');
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An apply whose selected objects all drop out of buildTargetConfigs must fail, not run RSU on
|
|
3
|
+
* nothing (PropFuel, 2026-10-29). A selection that produces even one table must still apply.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import type { TargetTableConfig } from '@memberjunction/integration-schema-builder';
|
|
9
|
+
import { AssertTargetConfigs, NewTargetConfigDrops, SampleNames } from '../integration/TargetConfigGuard.js';
|
|
10
|
+
|
|
11
|
+
const selected = [{ SourceObjectName: 'clicks' }, { SourceObjectName: 'sends' }, { SourceObjectName: 'opens' }];
|
|
12
|
+
const oneTable = [{ SchemaName: 'propfuel', TableName: 'clicks' } as TargetTableConfig];
|
|
13
|
+
|
|
14
|
+
describe('AssertTargetConfigs', () => {
|
|
15
|
+
it('refuses a selection none of whose objects produced a table, naming what was asked for', () => {
|
|
16
|
+
expect(() => AssertTargetConfigs(selected, [], 'PropFuel')).toThrow(
|
|
17
|
+
/NO_TARGET_TABLES: none of the 3 selected object\(s\) for PropFuel produced a target table \(clicks, sends, opens\)/
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('names why each object was dropped, so a caller does not need the server log', () => {
|
|
22
|
+
const drops = NewTargetConfigDrops();
|
|
23
|
+
drops.NotInSchema.push('clicks', 'sends');
|
|
24
|
+
drops.NoPrimaryKey.push('opens');
|
|
25
|
+
expect(() => AssertTargetConfigs(selected, [], 'PropFuel', drops)).toThrow(
|
|
26
|
+
'Dropped as not in the source schema: clicks, sends; no primary key: opens.'
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('says nothing was applied by default, and what was already committed when the caller says so', () => {
|
|
31
|
+
expect(() => AssertTargetConfigs(selected, [], 'PropFuel')).toThrow('Nothing was applied.');
|
|
32
|
+
expect(() => AssertTargetConfigs(selected, [], 'PropFuel', undefined, 'The catalog had already been saved.'))
|
|
33
|
+
.toThrow(/The catalog had already been saved\. Re-run discovery/);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('caps the names it lists, so a large selection cannot make a multi-KB error', () => {
|
|
37
|
+
const many = Array.from({ length: 168 }, (_v, i) => ({ SourceObjectName: `obj${i}` }));
|
|
38
|
+
expect(() => AssertTargetConfigs(many, [], 'NetForum')).toThrow('(obj0, obj1, obj2, obj3, obj4 and 163 more)');
|
|
39
|
+
expect(SampleNames(['a', 'b'])).toBe('a, b');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('lets a selection through when at least one object produced a table', () => {
|
|
43
|
+
expect(() => AssertTargetConfigs(selected, oneTable, 'PropFuel')).not.toThrow();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('lets an empty selection through — there was nothing to refuse', () => {
|
|
47
|
+
expect(() => AssertTargetConfigs([], [], 'PropFuel')).not.toThrow();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Read from source: the call sites are resolver mutations that need a provider, a connector and an
|
|
53
|
+
* RSU pipeline to run.
|
|
54
|
+
*/
|
|
55
|
+
describe('the guard\'s callers', () => {
|
|
56
|
+
const SRC = readFileSync(join(__dirname, '..', 'resolvers', 'IntegrationDiscoveryResolver.ts'), 'utf-8');
|
|
57
|
+
|
|
58
|
+
it('IntegrationApplySchema filters on names whose casing resolveObjectInputs has corrected', () => {
|
|
59
|
+
// A filter built from the raw input is case-sensitive: `Clicks` for a stored `clicks` selected
|
|
60
|
+
// nothing, and the guard then told the caller to re-run discovery, which cannot fix casing.
|
|
61
|
+
const start = SRC.indexOf('async IntegrationApplySchema(');
|
|
62
|
+
const body = SRC.slice(start, SRC.indexOf('AssertTargetConfigs(', start));
|
|
63
|
+
const resolve = body.indexOf('await this.resolveObjectInputs(objects, sourceSchema, user);');
|
|
64
|
+
const names = body.indexOf('const resolvedNames = new Set(objects.map(o => o.SourceObjectName));');
|
|
65
|
+
expect(resolve).toBeGreaterThan(-1);
|
|
66
|
+
expect(names).toBeGreaterThan(resolve);
|
|
67
|
+
expect(body).toMatch(/sourceSchema\.Objects\.filter\(o => resolvedNames\.has\(o\.ExternalName\)\)/);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('every call passes the drop reasons, and schema evolution says what it had already committed', () => {
|
|
71
|
+
const calls = [...SRC.matchAll(/AssertTargetConfigs\(objects, targetConfigs, companyIntegration\.Integration, drops([\s\S]*?)\);/g)];
|
|
72
|
+
expect(calls).toHaveLength(3);
|
|
73
|
+
expect(calls.filter(c => /already been saved/.test(c[1]))).toHaveLength(1);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two apply paths must agree, because the shared connector surface collapses onto the batch
|
|
3
|
+
* one. Two defects made them differ, and both are invisible until a surface migrates:
|
|
4
|
+
*
|
|
5
|
+
* - MJ-APPLY-12: the batch never made the first-apply full-sync determination, and its input
|
|
6
|
+
* declared `defaultValue: false` for FullSync, which made the null-coalesce dead code. A
|
|
7
|
+
* re-apply the caller left unspecified therefore ran INCREMENTAL against objects whose
|
|
8
|
+
* watermark the schema change had just reset. everything.txt: "for the very first RSU of a
|
|
9
|
+
* connector, the sync afterwards should be chosen to be full/incremental, but always full
|
|
10
|
+
* generally as the default."
|
|
11
|
+
* - MJ-APPLY-13: the batch's skipRestart branch never applied remove-as-disable, so
|
|
12
|
+
* UnselectedAction was a silent no-op and a deselected table kept syncing.
|
|
13
|
+
*
|
|
14
|
+
* Read from source: both live in a resolver that needs a provider, a connector and an RSU
|
|
15
|
+
* pipeline to invoke, and the property under test is a one-line policy, not a behaviour worth
|
|
16
|
+
* standing all that up to observe.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, it, expect } from 'vitest';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
|
|
22
|
+
const SRC = readFileSync(
|
|
23
|
+
join(__dirname, '..', 'resolvers', 'IntegrationDiscoveryResolver.ts'),
|
|
24
|
+
'utf-8',
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/** The body of a named input class, up to its closing brace. */
|
|
28
|
+
function classBody(name: string): string {
|
|
29
|
+
const start = SRC.indexOf(`class ${name} {`);
|
|
30
|
+
expect(start, `${name} not found`).toBeGreaterThan(-1);
|
|
31
|
+
const rest = SRC.slice(start);
|
|
32
|
+
const end = rest.indexOf('\n}');
|
|
33
|
+
return end === -1 ? rest : rest.slice(0, end);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The body of a named resolver method, up to the next method at the same indent. */
|
|
37
|
+
function methodBody(name: string): string {
|
|
38
|
+
const start = SRC.indexOf(`async ${name}(`);
|
|
39
|
+
expect(start, `${name} not found`).toBeGreaterThan(-1);
|
|
40
|
+
const rest = SRC.slice(start);
|
|
41
|
+
const end = rest.search(/\n @(Query|Mutation)\(/);
|
|
42
|
+
return end === -1 ? rest : rest.slice(0, end);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('MJ-APPLY-12 first-apply full sync', () => {
|
|
46
|
+
it('the batch resolves FullSync from prior maps, not from a bare false', () => {
|
|
47
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
48
|
+
expect(body).toMatch(/const fullSync = input\.FullSync\s*\?\?\s*!hadPriorMaps;/);
|
|
49
|
+
expect(body).toMatch(/FullSync:\s*fullSync,/);
|
|
50
|
+
expect(body).not.toMatch(/input\.FullSync\s*\?\?\s*false/);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('ApplyAllBatchInput.FullSync has NO defaultValue, or the coalesce is dead again', () => {
|
|
54
|
+
// Scope to the CLASS. There are several `FullSync?: boolean` fields in this file and a bare
|
|
55
|
+
// find() picks ApplyAllInput's, which would pass no matter what the batch input declared.
|
|
56
|
+
const body = classBody('ApplyAllBatchInput');
|
|
57
|
+
const line = body.split('\n').find(l => l.includes('FullSync?: boolean') && l.includes('@Field'));
|
|
58
|
+
expect(line, 'ApplyAllBatchInput.FullSync not found').toBeDefined();
|
|
59
|
+
expect(line!).not.toMatch(/defaultValue/);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('the single-connector path still does the same thing', () => {
|
|
63
|
+
expect(methodBody('IntegrationApplyAll')).toMatch(/input\.FullSync\s*\?\?\s*!hadPriorMaps/);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('the prior-maps read UUID-validates the connection id, like every other caller-supplied id', () => {
|
|
67
|
+
// The batch takes its CompanyIntegrationIDs from the caller. The rest of this resolver refuses a
|
|
68
|
+
// non-UUID id with sqlUuid before it reaches an ExtraFilter; quote-doubling is not that check.
|
|
69
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
70
|
+
expect(body).toMatch(/CompanyIntegrationID='\$\{sqlUuid\(connInput\.CompanyIntegrationID, 'CompanyIntegrationID'\)\}'/);
|
|
71
|
+
expect(body).not.toMatch(/connInput\.CompanyIntegrationID\.replace\(/);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('the skipRestart branch starts its sync with the RESOLVED FullSync, as the restart path queues it', () => {
|
|
75
|
+
// The restart path carries the coalesced value in its PendingWork; the skipRestart branch starts
|
|
76
|
+
// the sync itself. Passing the raw input there means an omitted FullSync is undefined, which
|
|
77
|
+
// startSyncAfterApply reads as incremental — against tables the apply just created.
|
|
78
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
79
|
+
const call = body.match(/this\.startSyncAfterApply\(build\.connInput\.CompanyIntegrationID,[^)]*\)/);
|
|
80
|
+
expect(call, 'skipRestart sync start not found').not.toBeNull();
|
|
81
|
+
expect(call![0]).not.toMatch(/input\.FullSync/);
|
|
82
|
+
expect(call![0]).toMatch(/build\.fullSync\)$/);
|
|
83
|
+
expect(body).toMatch(/^\s*fullSync,$/m);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('the prior-maps probe skips the row count, as the single path does', () => {
|
|
87
|
+
// MaxRows: 1 is an existence probe; without SkipTotalRowCount the provider follows every hit
|
|
88
|
+
// with a COUNT(*) over the connection's maps.
|
|
89
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
90
|
+
const probe = body.slice(body.indexOf('const priorMapsResult'), body.indexOf('const hadPriorMaps'));
|
|
91
|
+
expect(probe).toMatch(/MaxRows:\s*1,/);
|
|
92
|
+
expect(probe).toMatch(/SkipTotalRowCount:\s*true/);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('MJ-APPLY-13 remove-as-disable', () => {
|
|
97
|
+
it('the batch skipRestart branch disables unselected maps', () => {
|
|
98
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
99
|
+
expect(body).toMatch(/UnselectedAction\s*\?\?\s*'disable'\)\s*!==\s*'ignore'/);
|
|
100
|
+
expect(body).toMatch(/DisableUnselectedEntityMaps\(/);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('and honours the ignore opt-out rather than always disabling', () => {
|
|
104
|
+
const body = methodBody('IntegrationApplyAllBatch');
|
|
105
|
+
const at = body.indexOf('DisableUnselectedEntityMaps(');
|
|
106
|
+
// the guard must precede the call, not follow it
|
|
107
|
+
expect(body.lastIndexOf("!== 'ignore'", at)).toBeGreaterThan(-1);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -230,3 +230,45 @@ describe('StartBridgeOrphanReconciliation', () => {
|
|
|
230
230
|
expect(runView.mock.calls[0][1]).toBe(user);
|
|
231
231
|
});
|
|
232
232
|
});
|
|
233
|
+
|
|
234
|
+
describe('StartBridgeOrphanReconciliation with agentSessions.bridgeReconciler settings', () => {
|
|
235
|
+
const HOUR = 60 * 60_000;
|
|
236
|
+
afterEach(() => {
|
|
237
|
+
vi.restoreAllMocks();
|
|
238
|
+
vi.useRealTimers();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('enabled: reconciles now, then on the configured interval', async () => {
|
|
242
|
+
vi.useFakeTimers();
|
|
243
|
+
const reconcile = vi.spyOn(AIBridgeEngine.Instance, 'ReconcileOrphans').mockResolvedValue(0);
|
|
244
|
+
const { provider } = bridgeTable([]);
|
|
245
|
+
|
|
246
|
+
StartBridgeOrphanReconciliation(provider, user, { enabled: true, sweepIntervalMs: 120_000 });
|
|
247
|
+
await vi.advanceTimersByTimeAsync(6 * 60_000);
|
|
248
|
+
|
|
249
|
+
expect(reconcile).toHaveBeenCalledTimes(4); // now + every 2 minutes
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('disabled: reconciles once now and never again', async () => {
|
|
253
|
+
vi.useFakeTimers();
|
|
254
|
+
const reconcile = vi.spyOn(AIBridgeEngine.Instance, 'ReconcileOrphans').mockResolvedValue(0);
|
|
255
|
+
const { provider } = bridgeTable([]);
|
|
256
|
+
|
|
257
|
+
StartBridgeOrphanReconciliation(provider, user, { enabled: false, sweepIntervalMs: 600_000 });
|
|
258
|
+
await vi.advanceTimersByTimeAsync(HOUR);
|
|
259
|
+
|
|
260
|
+
expect(reconcile).toHaveBeenCalledTimes(1);
|
|
261
|
+
expect(reconcile.mock.calls[0][0]).toBe(user);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('with no settings keeps the shipped 10-minute repeat', async () => {
|
|
265
|
+
vi.useFakeTimers();
|
|
266
|
+
const reconcile = vi.spyOn(AIBridgeEngine.Instance, 'ReconcileOrphans').mockResolvedValue(0);
|
|
267
|
+
const { provider } = bridgeTable([]);
|
|
268
|
+
|
|
269
|
+
StartBridgeOrphanReconciliation(provider, user);
|
|
270
|
+
await vi.advanceTimersByTimeAsync(HOUR);
|
|
271
|
+
|
|
272
|
+
expect(reconcile).toHaveBeenCalledTimes(7);
|
|
273
|
+
});
|
|
274
|
+
});
|