@memberjunction/server 6.1.0-edge.1 → 6.1.0-edge.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +180 -4
- package/dist/auth/AuthProviderCatalogRouter.d.ts +31 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.js +69 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -0
- package/dist/auth/AuthProviderEngine.d.ts +96 -0
- package/dist/auth/AuthProviderEngine.d.ts.map +1 -0
- package/dist/auth/AuthProviderEngine.js +245 -0
- package/dist/auth/AuthProviderEngine.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +11 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +65 -18
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +64 -1
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +117 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +1 -1
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.js +1 -1
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -35
- package/dist/config.js.map +1 -1
- package/dist/context.js +2 -2
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +540 -1595
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2755 -16857
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +20 -4
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +58 -21
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +31 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +183 -54
- package/dist/index.js.map +1 -1
- package/dist/integration/RSUProgressBridge.d.ts +83 -0
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -0
- package/dist/integration/RSUProgressBridge.js +230 -0
- package/dist/integration/RSUProgressBridge.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +52 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.js +50 -0
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -0
- package/dist/logging/secretRedactor.d.ts +9 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +39 -0
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/middleware/BaseServerMiddleware.d.ts +5 -0
- package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
- package/dist/middleware/BaseServerMiddleware.js +5 -0
- package/dist/middleware/BaseServerMiddleware.js.map +1 -1
- package/dist/providerConfigUnits.d.ts +20 -0
- package/dist/providerConfigUnits.d.ts.map +1 -0
- package/dist/providerConfigUnits.js +22 -0
- package/dist/providerConfigUnits.js.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.js +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +12 -0
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.js +1 -1
- package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +34 -4
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +218 -28
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +85 -3
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +302 -82
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +5 -4
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +29 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +12 -3
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +33 -14
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +5 -0
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +20 -7
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +2 -2
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +18 -0
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +75 -0
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +19 -17
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +66 -67
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/currentUserRoles.d.ts +19 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -0
- package/dist/resolvers/currentUserRoles.js +36 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -0
- package/dist/rest/MediaAccessKeys.d.ts +17 -0
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +42 -1
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +3 -2
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +83 -2
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +49 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +130 -44
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +1 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +90 -0
- package/dist/rest/UploadTokenManager.d.ts.map +1 -0
- package/dist/rest/UploadTokenManager.js +156 -0
- package/dist/rest/UploadTokenManager.js.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts +26 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js +55 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts +48 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.js +132 -0
- package/dist/services/IntegrationSyncWorkerService.js.map +1 -0
- package/dist/services/ScheduledJobsService.js +1 -1
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.d.ts +0 -10
- package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +37 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +34 -0
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphActionRunner.js +95 -0
- package/dist/services/TaskGraphActionRunner.js.map +1 -0
- package/dist/services/TaskGraphAgentRunner.d.ts +20 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +53 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +12 -1
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/TaskGraphPromptRunner.d.ts +31 -0
- package/dist/services/TaskGraphPromptRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphPromptRunner.js +134 -0
- package/dist/services/TaskGraphPromptRunner.js.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.js +1 -1
- package/dist/telephony/RingCentralTelephonyService.js.map +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js.map +1 -1
- package/dist/telephony/VonageTelephonyRouter.js +1 -1
- package/dist/telephony/VonageTelephonyRouter.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +91 -91
- package/src/__tests__/APIKeyScopeAuth.test.ts +475 -0
- package/src/__tests__/AuthProviderEngine.test.ts +278 -0
- package/src/__tests__/EntityCRUDHandler.test.ts +378 -0
- package/src/__tests__/IntegrationSyncWorkerService.test.ts +275 -0
- package/src/__tests__/OAuthCallbackHandler.openRedirect.test.ts +117 -0
- package/src/__tests__/OAuthCallbackHandler.xss.test.ts +4 -1
- package/src/__tests__/RESTEndpointHandler.test.ts +672 -0
- package/src/__tests__/RSUProgressBridge.test.ts +250 -0
- package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +1 -1
- package/src/__tests__/ResolverBase.frozenRecordMapping.test.ts +133 -0
- package/src/__tests__/ResolverBase.transportMapping.test.ts +289 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +114 -0
- package/src/__tests__/SessionManager.test.ts +1 -1
- package/src/__tests__/UserResolver.currentUser.test.ts +87 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +277 -0
- package/src/__tests__/WidgetSessionService.test.ts +1 -1
- package/src/__tests__/config-units.test.ts +74 -0
- package/src/__tests__/databaseAbstraction.test.ts +1 -1
- package/src/__tests__/initializeProviders.refresh.test.ts +146 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +1 -1
- package/src/__tests__/mjapi-bootstrap.test.ts +0 -6
- package/src/__tests__/newUsers.test.ts +726 -0
- package/src/__tests__/resolverBase.rls.test.ts +3 -0
- package/src/__tests__/secretRedactor.failOpen.test.ts +135 -0
- package/src/__tests__/uploadTokenManager.test.ts +159 -0
- package/src/__tests__/widgetGuestElevation.test.ts +1 -1
- package/src/auth/AuthProviderCatalogRouter.ts +76 -0
- package/src/auth/AuthProviderEngine.ts +253 -0
- package/src/auth/exampleNewUserSubClass.ts +1 -1
- package/src/auth/index.ts +69 -21
- package/src/auth/initializeProviders.ts +128 -7
- package/src/auth/magicLink/MagicLinkService.ts +1 -1
- package/src/auth/newUsers.ts +1 -1
- package/src/config.ts +55 -36
- package/src/context.ts +2 -2
- package/src/generated/generated.ts +2038 -10529
- package/src/generic/ResolverBase.ts +63 -21
- package/src/generic/RunViewResolver.ts +31 -0
- package/src/index.ts +199 -56
- package/src/integration/RSUProgressBridge.ts +248 -0
- package/src/integration/SchemaRefreshLaunch.ts +77 -0
- package/src/logging/secretRedactor.ts +43 -0
- package/src/middleware/BaseServerMiddleware.ts +5 -0
- package/src/providerConfigUnits.ts +21 -0
- package/src/realtimeWidget/WidgetSessionService.ts +1 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -1
- package/src/resolvers/ActionResolver.ts +13 -0
- package/src/resolvers/ComponentRegistryResolver.ts +1 -1
- package/src/resolvers/EntityPermissionResolver.ts +1 -1
- package/src/resolvers/FileResolver.ts +200 -40
- package/src/resolvers/IntegrationDiscoveryResolver.ts +328 -70
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +25 -11
- package/src/resolvers/QuerySystemUserResolver.ts +28 -13
- package/src/resolvers/RealtimeClientSessionResolver.ts +13 -0
- package/src/resolvers/RunAIAgentResolver.ts +21 -6
- package/src/resolvers/SearchEntitiesResolver.ts +1 -1
- package/src/resolvers/SqlLoggingConfigResolver.ts +1 -2
- package/src/resolvers/SyncRolesUsersResolver.ts +2 -2
- package/src/resolvers/TaskGraphFrameResolver.ts +67 -0
- package/src/resolvers/UserFavoriteResolver.ts +1 -1
- package/src/resolvers/UserResolver.ts +99 -60
- package/src/resolvers/currentUserRoles.ts +47 -0
- package/src/rest/MediaAccessKeys.ts +47 -1
- package/src/rest/MediaStreamHandler.ts +98 -3
- package/src/rest/OAuthCallbackHandler.ts +150 -42
- package/src/rest/SignatureWebhookHandler.ts +1 -1
- package/src/rest/UploadTokenManager.ts +211 -0
- package/src/services/DurableEntityActionTaskSubmitter.ts +78 -0
- package/src/services/IntegrationSyncWorkerService.ts +141 -0
- package/src/services/ScheduledJobsService.ts +1 -1
- package/src/services/StartTaskGraphDispatcher.ts +38 -1
- package/src/services/TaskGraphActionRunner.ts +99 -0
- package/src/services/TaskGraphAgentRunner.ts +58 -1
- package/src/services/TaskGraphContinuationDeliverer.ts +11 -1
- package/src/services/TaskGraphPromptRunner.ts +144 -0
- package/src/telephony/RingCentralTelephonyService.ts +1 -1
- package/src/telephony/TwilioTelephonyRouter.ts +1 -1
- package/src/telephony/VonageTelephonyRouter.ts +1 -1
- package/src/types.ts +6 -0
|
@@ -14,18 +14,21 @@ var IntegrationDiscoveryResolver_1;
|
|
|
14
14
|
import { Resolver, Query, Mutation, Arg, Ctx, ObjectType, Field, InputType, Int, Float } from "type-graphql";
|
|
15
15
|
import { CompositeKey, LocalCacheManager, Metadata, RunView, LogError, LogStatus } from "@memberjunction/core";
|
|
16
16
|
import { GetReadOnlyProvider, GetReadWriteProvider } from "../util.js";
|
|
17
|
+
import { NoLog } from "../logging/NoLog.js";
|
|
17
18
|
import { UUIDsEqual } from "@memberjunction/global";
|
|
18
19
|
import { CronExpressionHelper } from "@memberjunction/scheduling-engine";
|
|
19
20
|
import { ConnectorFactory, IntegrationEngine, IntegrationSchemaSync, decideSchemaLimitViolations, IntegrationConnectorCreationPipeline, IntegrationActionGenerator } from "@memberjunction/integration-engine";
|
|
20
21
|
import { IntegrationEngineBase } from "@memberjunction/integration-engine-base";
|
|
22
|
+
import { buildIntegrationLLMPKCallback } from "@memberjunction/core-entities-server";
|
|
21
23
|
import { SchemaBuilder, TypeMapper, SchemaEvolution } from "@memberjunction/integration-schema-builder";
|
|
22
24
|
import { RuntimeSchemaManager } from "@memberjunction/schema-engine";
|
|
23
|
-
import { IntegrationProgressReader } from "@memberjunction/integration-progress-artifacts";
|
|
25
|
+
import { IntegrationProgressEmitter, IntegrationProgressReader } from "@memberjunction/integration-progress-artifacts";
|
|
24
26
|
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
25
27
|
import { IntegrationCustomColumnPromoter } from "../integration/CustomColumnPromoter.js";
|
|
26
28
|
import { ComputeCascadeRemovalSet, ComputeRemovedDependencyWarnings, DisableUnselectedEntityMaps, ReenableFieldMapsForEntityMap, ResetPullWatermarks, SetEntityMapEnabled } from "../integration/EntityMapLifecycle.js";
|
|
29
|
+
import { BuildCreateConnectionMessage, BuildDetachedRefreshMessage, BuildUpdateConnectionMessage } from "../integration/SchemaRefreshLaunch.js";
|
|
27
30
|
import { RequireSystemUser } from "../directives/RequireSystemUser.js";
|
|
28
|
-
import { UserCache } from "@memberjunction/
|
|
31
|
+
import { UserCache } from "@memberjunction/generic-database-provider";
|
|
29
32
|
// ─── RSU Pipeline Output Types ──────────────────────────────────────────────
|
|
30
33
|
let RSUStepOutput = class RSUStepOutput {
|
|
31
34
|
};
|
|
@@ -1053,6 +1056,7 @@ __decorate([
|
|
|
1053
1056
|
], CreateConnectionInput.prototype, "CredentialName", void 0);
|
|
1054
1057
|
__decorate([
|
|
1055
1058
|
Field(),
|
|
1059
|
+
NoLog,
|
|
1056
1060
|
__metadata("design:type", String)
|
|
1057
1061
|
], CreateConnectionInput.prototype, "CredentialValues", void 0);
|
|
1058
1062
|
__decorate([
|
|
@@ -1072,6 +1076,18 @@ __decorate([
|
|
|
1072
1076
|
Field(),
|
|
1073
1077
|
__metadata("design:type", String)
|
|
1074
1078
|
], CreateConnectionPipelineSummary.prototype, "RunID", void 0);
|
|
1079
|
+
__decorate([
|
|
1080
|
+
Field(),
|
|
1081
|
+
__metadata("design:type", Boolean)
|
|
1082
|
+
], CreateConnectionPipelineSummary.prototype, "InProgress", void 0);
|
|
1083
|
+
__decorate([
|
|
1084
|
+
Field(),
|
|
1085
|
+
__metadata("design:type", Boolean)
|
|
1086
|
+
], CreateConnectionPipelineSummary.prototype, "Succeeded", void 0);
|
|
1087
|
+
__decorate([
|
|
1088
|
+
Field({ nullable: true }),
|
|
1089
|
+
__metadata("design:type", String)
|
|
1090
|
+
], CreateConnectionPipelineSummary.prototype, "FailureMessage", void 0);
|
|
1075
1091
|
__decorate([
|
|
1076
1092
|
Field(),
|
|
1077
1093
|
__metadata("design:type", Number)
|
|
@@ -1179,6 +1195,10 @@ __decorate([
|
|
|
1179
1195
|
Field(() => Int, { nullable: true, description: 'Time budget (ms) for stage-2 streaming field discovery before it stops and uses what it gathered.' }),
|
|
1180
1196
|
__metadata("design:type", Number)
|
|
1181
1197
|
], IntegrationSyncConfigInput.prototype, "DiscoveryTimeBudgetMs", void 0);
|
|
1198
|
+
__decorate([
|
|
1199
|
+
Field(() => Int, { nullable: true, description: 'Per-page FetchChanges timeout (ms). Raise it for a connector that fans out one request per parent record, whose page time scales with BatchSize. Wins over the connector\'s own FetchChangesTimeoutMs; unset = the connector\'s value, else the framework default (30000).' }),
|
|
1200
|
+
__metadata("design:type", Number)
|
|
1201
|
+
], IntegrationSyncConfigInput.prototype, "FetchTimeoutMs", void 0);
|
|
1182
1202
|
__decorate([
|
|
1183
1203
|
Field(() => Int, { nullable: true, description: 'Batch size for stage-2 streaming field discovery (records per FetchChanges page). Default 500.' }),
|
|
1184
1204
|
__metadata("design:type", Number)
|
|
@@ -1232,6 +1252,10 @@ __decorate([
|
|
|
1232
1252
|
Field(() => Int, { nullable: true }),
|
|
1233
1253
|
__metadata("design:type", Number)
|
|
1234
1254
|
], IntegrationSyncConfigOutput.prototype, "DiscoveryTimeBudgetMs", void 0);
|
|
1255
|
+
__decorate([
|
|
1256
|
+
Field(() => Int, { nullable: true }),
|
|
1257
|
+
__metadata("design:type", Number)
|
|
1258
|
+
], IntegrationSyncConfigOutput.prototype, "FetchTimeoutMs", void 0);
|
|
1235
1259
|
__decorate([
|
|
1236
1260
|
Field(() => Int, { nullable: true }),
|
|
1237
1261
|
__metadata("design:type", Number)
|
|
@@ -2081,7 +2105,7 @@ __decorate([
|
|
|
2081
2105
|
IntegrationRunEventsOutput = __decorate([
|
|
2082
2106
|
ObjectType()
|
|
2083
2107
|
], IntegrationRunEventsOutput);
|
|
2084
|
-
// Sync progress is now tracked inside IntegrationEngine itself via IntegrationEngine.
|
|
2108
|
+
// Sync progress is now tracked inside IntegrationEngine itself via IntegrationEngine.GetSyncProgressAsync()
|
|
2085
2109
|
let ConnectionSummaryOutput = class ConnectionSummaryOutput {
|
|
2086
2110
|
};
|
|
2087
2111
|
__decorate([
|
|
@@ -3370,9 +3394,33 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3370
3394
|
}
|
|
3371
3395
|
return result;
|
|
3372
3396
|
}
|
|
3373
|
-
async runSchemaRefreshPipeline(companyIntegrationID, user, provider, universalPKConvention) {
|
|
3397
|
+
async runSchemaRefreshPipeline(companyIntegrationID, user, provider, universalPKConvention, runID) {
|
|
3398
|
+
// Sync lock (#3656). This pipeline rewrites the very IO/IOF rows, field
|
|
3399
|
+
// maps and DDL a sync reads, so it must not overlap a sync or another
|
|
3400
|
+
// maintenance operation for the same connection. The two other
|
|
3401
|
+
// pipeline call sites — IntegrationRefreshConnectorSchema and
|
|
3402
|
+
// IntegrationSchemaEvolution — already take this lock inline; this is
|
|
3403
|
+
// the third and fourth (create/update/reactivate) finally taking it too.
|
|
3404
|
+
if (!IntegrationEngine.AcquireMaintenanceLock(companyIntegrationID, 'schema refresh')) {
|
|
3405
|
+
throw new Error('Schema refresh not started: a sync or another maintenance operation is currently running for this connection. Retry after it completes.');
|
|
3406
|
+
}
|
|
3407
|
+
try {
|
|
3408
|
+
return await this.runSchemaRefreshPipelineLocked(companyIntegrationID, user, provider, universalPKConvention, runID);
|
|
3409
|
+
}
|
|
3410
|
+
finally {
|
|
3411
|
+
IntegrationEngine.ReleaseMaintenanceLock(companyIntegrationID);
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
/** The body of {@link runSchemaRefreshPipeline}, run with the maintenance lock held. */
|
|
3415
|
+
async runSchemaRefreshPipelineLocked(companyIntegrationID, user, provider, universalPKConvention, runID) {
|
|
3374
3416
|
const { connector, companyIntegration } = await this.resolveConnector(companyIntegrationID, user, provider);
|
|
3375
3417
|
const pipeline = new IntegrationConnectorCreationPipeline();
|
|
3418
|
+
// SoftPKClassifier's LLM tier (universal → naming → statistical → LLM →
|
|
3419
|
+
// synthetic) only runs when this callback is supplied. It used to be
|
|
3420
|
+
// wired by the CompanyIntegration save hook; with that hook gone
|
|
3421
|
+
// (#3738) it is wired here, so the create/update/reactivate paths keep
|
|
3422
|
+
// the same PK-inference quality they had before.
|
|
3423
|
+
const llmInference = await buildIntegrationLLMPKCallback(user);
|
|
3376
3424
|
const runOpts = {
|
|
3377
3425
|
Connector: connector,
|
|
3378
3426
|
CompanyIntegration: companyIntegration,
|
|
@@ -3381,6 +3429,10 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3381
3429
|
UniversalPKConvention: universalPKConvention || undefined,
|
|
3382
3430
|
ConsoleMirror: true,
|
|
3383
3431
|
TriggerType: 'Manual',
|
|
3432
|
+
LLMInference: llmInference ?? undefined,
|
|
3433
|
+
// Caller-supplied runID: lets the detached path hand a tailable ID back to the client
|
|
3434
|
+
// BEFORE the pipeline has done any work. Omitted ⇒ the pipeline generates its own.
|
|
3435
|
+
RunID: runID,
|
|
3384
3436
|
};
|
|
3385
3437
|
const result = await pipeline.Run(runOpts);
|
|
3386
3438
|
// Refresh in-memory caches so downstream queries (object picker,
|
|
@@ -3389,6 +3441,9 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3389
3441
|
await IntegrationEngine.Instance.Config(true, user, provider);
|
|
3390
3442
|
return {
|
|
3391
3443
|
RunID: result.RunID,
|
|
3444
|
+
InProgress: false,
|
|
3445
|
+
Succeeded: result.Success,
|
|
3446
|
+
FailureMessage: result.FailureMessage,
|
|
3392
3447
|
ObjectsCreated: result.PersistResult?.ObjectsCreated ?? 0,
|
|
3393
3448
|
ObjectsUpdated: result.PersistResult?.ObjectsUpdated ?? 0,
|
|
3394
3449
|
FieldsCreated: result.PersistResult?.FieldsCreated ?? 0,
|
|
@@ -3404,6 +3459,88 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3404
3459
|
})),
|
|
3405
3460
|
};
|
|
3406
3461
|
}
|
|
3462
|
+
/**
|
|
3463
|
+
* Launches the schema-refresh pipeline WITHOUT awaiting it and returns a summary carrying the
|
|
3464
|
+
* tailable `RunID` and `InProgress: true`.
|
|
3465
|
+
*
|
|
3466
|
+
* Why: the pipeline is a live vendor introspect — minutes on a large catalog (HubSpot: 130
|
|
3467
|
+
* objects). Awaiting it inline holds the create/update mutation open for that entire time, so the
|
|
3468
|
+
* connection wizard's Finish button sits on an indeterminate spinner with no way to tell progress
|
|
3469
|
+
* from a hang. The pipeline already writes a complete, durable, per-run event stream keyed by its
|
|
3470
|
+
* runID; the only thing missing was handing that ID to the caller BEFORE the work starts. Hence
|
|
3471
|
+
* the caller-supplied runID.
|
|
3472
|
+
*
|
|
3473
|
+
* Trade-off the caller opts into: the mutation no longer reports what the refresh found (counts
|
|
3474
|
+
* are placeholder zeros) and a refresh failure no longer surfaces in the mutation's Message — both
|
|
3475
|
+
* live on the run stream instead. That is why `awaitSchemaRefresh` defaults to true.
|
|
3476
|
+
*
|
|
3477
|
+
* ON CREATE this is the only refresh that runs. #3738 removed the activation hook that used to
|
|
3478
|
+
* fire the same pipeline inside `Save()`, awaited — which had made the create mutation pay a full
|
|
3479
|
+
* introspect before ever reaching this method, and had run it BEFORE the connection test, so a
|
|
3480
|
+
* rejected connection was rolled back with its discovered schema already written.
|
|
3481
|
+
*
|
|
3482
|
+
* Belt and braces: if the launch below IS coalesced onto some other run for this connection (a
|
|
3483
|
+
* concurrent refresh, a repeat click), the pipeline publishes a terminal alias run under `runID`
|
|
3484
|
+
* naming the run that served it — so the ID handed back here is tailable in every case.
|
|
3485
|
+
*/
|
|
3486
|
+
startSchemaRefreshPipelineDetached(companyIntegrationID, user, provider, universalPKConvention) {
|
|
3487
|
+
const runID = IntegrationProgressEmitter.newRunID('connector');
|
|
3488
|
+
// Deliberately not awaited. Once the pipeline is running it records every outcome on this
|
|
3489
|
+
// run's artifact stream under `runID` itself — but it can also throw BEFORE it ever
|
|
3490
|
+
// constructs its emitter (connector-driver resolution, a missing Integration row), and in
|
|
3491
|
+
// the blocking path that throw surfaced in the mutation's Message. Detached, the caller has
|
|
3492
|
+
// already been handed `runID` and has nothing but the stream to watch, so a pre-emitter
|
|
3493
|
+
// throw must be published onto that stream — otherwise the run never appears at all and a
|
|
3494
|
+
// tailer waits forever on a run ID that will never produce an event.
|
|
3495
|
+
void this.runSchemaRefreshPipeline(companyIntegrationID, user, provider, universalPKConvention, runID)
|
|
3496
|
+
.catch(err => this.publishDetachedLaunchFailure(runID, companyIntegrationID, err));
|
|
3497
|
+
return {
|
|
3498
|
+
RunID: runID,
|
|
3499
|
+
InProgress: true,
|
|
3500
|
+
// Not known yet — the run has only just been launched.
|
|
3501
|
+
Succeeded: false,
|
|
3502
|
+
ObjectsCreated: 0,
|
|
3503
|
+
ObjectsUpdated: 0,
|
|
3504
|
+
FieldsCreated: 0,
|
|
3505
|
+
FieldsUpdated: 0,
|
|
3506
|
+
UnresolvedObjects: [],
|
|
3507
|
+
PKVerdicts: [],
|
|
3508
|
+
};
|
|
3509
|
+
}
|
|
3510
|
+
/**
|
|
3511
|
+
* Terminates a detached run that failed BEFORE the pipeline could open its own artifact stream.
|
|
3512
|
+
*
|
|
3513
|
+
* The pipeline constructs its emitter inside `Run()`, so anything that throws on the way there —
|
|
3514
|
+
* connector-driver resolution (`No connector registered for driver class "X"`), a missing
|
|
3515
|
+
* Integration row, a CompanyIntegration that vanished — produces no run directory at all. In the
|
|
3516
|
+
* blocking path that throw surfaced in the mutation's Message. Detached, the caller has already
|
|
3517
|
+
* been handed the run ID and has only the stream to watch, so the failure has to be published
|
|
3518
|
+
* there or the run is invisible forever.
|
|
3519
|
+
*
|
|
3520
|
+
* Only ever called on the rejection path: if the pipeline got far enough to build its own emitter
|
|
3521
|
+
* it terminates its own run, and a pipeline that completed never reaches here.
|
|
3522
|
+
*/
|
|
3523
|
+
publishDetachedLaunchFailure(runID, companyIntegrationID, err) {
|
|
3524
|
+
const message = this.formatError(err);
|
|
3525
|
+
LogError(`Detached schema refresh (run ${runID}) failed: ${message}`);
|
|
3526
|
+
try {
|
|
3527
|
+
const emitter = new IntegrationProgressEmitter({
|
|
3528
|
+
runID,
|
|
3529
|
+
runKind: 'ConnectorCreation',
|
|
3530
|
+
companyIntegrationID,
|
|
3531
|
+
triggerType: 'Manual',
|
|
3532
|
+
startedAt: new Date().toISOString(),
|
|
3533
|
+
});
|
|
3534
|
+
emitter.runStart('Detached schema refresh launch');
|
|
3535
|
+
emitter.stageError('Launch', message, { code: 'schema-refresh-launch-failed' });
|
|
3536
|
+
void emitter.fail(`Schema refresh could not start: ${message}`, 'schema-refresh-launch-failed')
|
|
3537
|
+
.catch(e => LogError(`Detached schema refresh (run ${runID}): failure artifact write failed — ${e}`));
|
|
3538
|
+
}
|
|
3539
|
+
catch (e) {
|
|
3540
|
+
// Progress reporting must never mask the original failure, which is already logged above.
|
|
3541
|
+
LogError(`Detached schema refresh (run ${runID}): could not open failure artifact — ${e}`);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3407
3544
|
/**
|
|
3408
3545
|
* Rolls back a freshly created connection by deleting both the CompanyIntegration and Credential records.
|
|
3409
3546
|
*/
|
|
@@ -3554,7 +3691,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3554
3691
|
/**
|
|
3555
3692
|
* Creates a CompanyIntegration with a linked Credential entity for encrypted credential storage.
|
|
3556
3693
|
*/
|
|
3557
|
-
async IntegrationCreateConnection(input, testConnection, runSchemaRefresh, universalPKConvention, ctx) {
|
|
3694
|
+
async IntegrationCreateConnection(input, testConnection, runSchemaRefresh, universalPKConvention, awaitSchemaRefresh, ctx) {
|
|
3558
3695
|
try {
|
|
3559
3696
|
const user = this.getAuthenticatedUser(ctx);
|
|
3560
3697
|
const md = GetReadWriteProvider(ctx.providers, { allowFallbackToReadOnly: true });
|
|
@@ -3577,12 +3714,20 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3577
3714
|
ci.IntegrationID = input.IntegrationID;
|
|
3578
3715
|
ci.CompanyID = input.CompanyID;
|
|
3579
3716
|
ci.CredentialID = credentialID;
|
|
3580
|
-
|
|
3717
|
+
// Created INACTIVE on purpose (#3738). A connection is not marked
|
|
3718
|
+
// active until its credential has had a chance to prove itself in
|
|
3719
|
+
// step 3 below — so nothing downstream ever observes an active row
|
|
3720
|
+
// backed by a password that is about to be rejected and rolled back.
|
|
3721
|
+
ci.IsActive = false;
|
|
3581
3722
|
ci.Name = input.CredentialName; // Name is required on CompanyIntegration
|
|
3582
3723
|
if (input.ExternalSystemID)
|
|
3583
3724
|
ci.ExternalSystemID = input.ExternalSystemID;
|
|
3584
3725
|
if (input.Configuration)
|
|
3585
3726
|
ci.Configuration = input.Configuration;
|
|
3727
|
+
// Whether the refresh runs detached (this resolver owns it and returns a tailable RunID)
|
|
3728
|
+
// or inline below. No save-side refresh exists to coordinate with any more — #3738 removed
|
|
3729
|
+
// the activation hook, so every refresh on this path is one this method asked for.
|
|
3730
|
+
const ownSchemaRefresh = runSchemaRefresh && !awaitSchemaRefresh;
|
|
3586
3731
|
const saved = await ci.Save();
|
|
3587
3732
|
if (!saved) {
|
|
3588
3733
|
const validationErrors = ci.LatestResult?.Message || 'Unknown validation error';
|
|
@@ -3605,12 +3750,27 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3605
3750
|
testPassed = true;
|
|
3606
3751
|
testMessage = testResult.Message;
|
|
3607
3752
|
}
|
|
3753
|
+
// 3b. Credential has proven itself (or the caller declined a test,
|
|
3754
|
+
// which is the pre-existing default) — activate. Ordering matters:
|
|
3755
|
+
// this save is what makes the connection usable, and it must not
|
|
3756
|
+
// happen while the credential is still unverified.
|
|
3757
|
+
ci.IsActive = true;
|
|
3758
|
+
if (!await ci.Save()) {
|
|
3759
|
+
await this.rollbackCreatedConnection(ci, credential);
|
|
3760
|
+
return {
|
|
3761
|
+
Success: false,
|
|
3762
|
+
Message: `Failed to activate CompanyIntegration: ${ci.LatestResult?.Message || 'Unknown error'}`,
|
|
3763
|
+
};
|
|
3764
|
+
}
|
|
3608
3765
|
// 4. Auto-run schema refresh pipeline (intermittent server-side period).
|
|
3609
3766
|
// Fires whenever runSchemaRefresh=true, regardless of whether the
|
|
3610
3767
|
// caller also asked for a test. The wizard may have tested separately
|
|
3611
3768
|
// and just be hitting Create to save.
|
|
3612
3769
|
let schemaRefreshSummary;
|
|
3613
|
-
if (
|
|
3770
|
+
if (ownSchemaRefresh) {
|
|
3771
|
+
schemaRefreshSummary = this.startSchemaRefreshPipelineDetached(ci.ID, user, md, universalPKConvention);
|
|
3772
|
+
}
|
|
3773
|
+
else if (runSchemaRefresh) {
|
|
3614
3774
|
try {
|
|
3615
3775
|
const refreshResult = await this.runSchemaRefreshPipeline(ci.ID, user, md, universalPKConvention);
|
|
3616
3776
|
schemaRefreshSummary = refreshResult;
|
|
@@ -3624,9 +3784,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3624
3784
|
if (testConnection || schemaRefreshSummary) {
|
|
3625
3785
|
return {
|
|
3626
3786
|
Success: true,
|
|
3627
|
-
Message: schemaRefreshSummary
|
|
3628
|
-
? `Connection created${testConnection ? ', test passed' : ''}, schema refresh: ${schemaRefreshSummary.ObjectsCreated} created, ${schemaRefreshSummary.ObjectsUpdated} updated, ${schemaRefreshSummary.UnresolvedObjects.length} PK-unresolved`
|
|
3629
|
-
: 'Connection created and test passed',
|
|
3787
|
+
Message: BuildCreateConnectionMessage(testConnection, schemaRefreshSummary),
|
|
3630
3788
|
CompanyIntegrationID: ci.ID,
|
|
3631
3789
|
CredentialID: credentialID,
|
|
3632
3790
|
ConnectionTestSuccess: testPassed,
|
|
@@ -3649,7 +3807,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3649
3807
|
/**
|
|
3650
3808
|
* Updates credential values and/or configuration on an existing CompanyIntegration.
|
|
3651
3809
|
*/
|
|
3652
|
-
async IntegrationUpdateConnection(companyIntegrationID, credentialValues, configuration, externalSystemID, testConnection, runSchemaRefresh, universalPKConvention, ctx) {
|
|
3810
|
+
async IntegrationUpdateConnection(companyIntegrationID, credentialValues, configuration, externalSystemID, testConnection, runSchemaRefresh, universalPKConvention, awaitSchemaRefresh, ctx) {
|
|
3653
3811
|
try {
|
|
3654
3812
|
const user = this.getAuthenticatedUser(ctx);
|
|
3655
3813
|
const md = GetReadWriteProvider(ctx.providers, { allowFallbackToReadOnly: true });
|
|
@@ -3698,13 +3856,14 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3698
3856
|
// Fires whenever runSchemaRefresh=true, regardless of whether the
|
|
3699
3857
|
// caller also asked for a test — the wizard may have tested separately
|
|
3700
3858
|
// already and is just hitting Update to save edits.
|
|
3859
|
+
if (runSchemaRefresh && !awaitSchemaRefresh) {
|
|
3860
|
+
const detached = this.startSchemaRefreshPipelineDetached(companyIntegrationID, user, md, universalPKConvention);
|
|
3861
|
+
return { Success: true, Message: BuildDetachedRefreshMessage(detached.RunID) };
|
|
3862
|
+
}
|
|
3701
3863
|
if (runSchemaRefresh) {
|
|
3702
3864
|
try {
|
|
3703
3865
|
const refreshResult = await this.runSchemaRefreshPipeline(companyIntegrationID, user, md, universalPKConvention);
|
|
3704
|
-
return {
|
|
3705
|
-
Success: true,
|
|
3706
|
-
Message: `Updated, schema refresh: ${refreshResult.ObjectsCreated} created, ${refreshResult.ObjectsUpdated} updated, ${refreshResult.UnresolvedObjects.length} PK-unresolved`,
|
|
3707
|
-
};
|
|
3866
|
+
return { Success: true, Message: BuildUpdateConnectionMessage(refreshResult) };
|
|
3708
3867
|
}
|
|
3709
3868
|
catch (refreshErr) {
|
|
3710
3869
|
LogError(`IntegrationUpdateConnection: pipeline error — ${refreshErr}`);
|
|
@@ -3749,6 +3908,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3749
3908
|
set('crossLayerPipeline', config.CrossLayerPipeline);
|
|
3750
3909
|
set('partitionReconcile', config.PartitionReconcile);
|
|
3751
3910
|
set('discoveryTimeBudgetMs', config.DiscoveryTimeBudgetMs);
|
|
3911
|
+
set('fetchTimeoutMs', config.FetchTimeoutMs);
|
|
3752
3912
|
set('discoveryBatchSize', config.DiscoveryBatchSize);
|
|
3753
3913
|
set('discoveryMaxRecords', config.DiscoveryMaxRecords);
|
|
3754
3914
|
set('deactivateAbsent', config.DeactivateAbsent);
|
|
@@ -3810,6 +3970,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3810
3970
|
CrossLayerPipeline: bool(cfg.crossLayerPipeline),
|
|
3811
3971
|
PartitionReconcile: bool(cfg.partitionReconcile),
|
|
3812
3972
|
DiscoveryTimeBudgetMs: num(cfg.discoveryTimeBudgetMs),
|
|
3973
|
+
FetchTimeoutMs: num(cfg.fetchTimeoutMs),
|
|
3813
3974
|
DiscoveryBatchSize: num(cfg.discoveryBatchSize),
|
|
3814
3975
|
DiscoveryMaxRecords: num(cfg.discoveryMaxRecords),
|
|
3815
3976
|
DeactivateAbsent: bool(cfg.deactivateAbsent),
|
|
@@ -3905,8 +4066,13 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3905
4066
|
}
|
|
3906
4067
|
/**
|
|
3907
4068
|
* Reactivates a previously deactivated CompanyIntegration by setting IsActive=true.
|
|
4069
|
+
*
|
|
4070
|
+
* Before #3738 this mutation inherited a full schema refresh from the
|
|
4071
|
+
* CompanyIntegration save hook, with no way to decline it. The refresh is
|
|
4072
|
+
* now this resolver's own, explicit step — same default behaviour, but
|
|
4073
|
+
* visible in the API and suppressible with `runSchemaRefresh: false`.
|
|
3908
4074
|
*/
|
|
3909
|
-
async IntegrationReactivateConnection(companyIntegrationID, ctx) {
|
|
4075
|
+
async IntegrationReactivateConnection(companyIntegrationID, runSchemaRefresh, ctx) {
|
|
3910
4076
|
try {
|
|
3911
4077
|
const user = this.getAuthenticatedUser(ctx);
|
|
3912
4078
|
const md = GetReadWriteProvider(ctx.providers, { allowFallbackToReadOnly: true });
|
|
@@ -3917,6 +4083,22 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
3917
4083
|
ci.IsActive = true;
|
|
3918
4084
|
if (!await ci.Save())
|
|
3919
4085
|
return { Success: false, Message: `Failed to reactivate: ${ci.LatestResult?.Message ?? 'Unknown error'}` };
|
|
4086
|
+
if (runSchemaRefresh) {
|
|
4087
|
+
try {
|
|
4088
|
+
const refreshResult = await this.runSchemaRefreshPipeline(companyIntegrationID, user, md);
|
|
4089
|
+
return {
|
|
4090
|
+
Success: true,
|
|
4091
|
+
Message: `Reactivated, schema refresh: ${refreshResult.ObjectsCreated} created, ${refreshResult.ObjectsUpdated} updated, ${refreshResult.UnresolvedObjects.length} PK-unresolved`,
|
|
4092
|
+
};
|
|
4093
|
+
}
|
|
4094
|
+
catch (refreshErr) {
|
|
4095
|
+
// Refresh failure does NOT undo the reactivation — the
|
|
4096
|
+
// connection is active, only discovery failed, and the
|
|
4097
|
+
// operator can re-run IntegrationRefreshConnectorSchema.
|
|
4098
|
+
LogError(`IntegrationReactivateConnection: pipeline error — ${refreshErr}`);
|
|
4099
|
+
return { Success: true, Message: `Reactivated (schema refresh failed: ${this.formatError(refreshErr)})` };
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
3920
4102
|
return { Success: true, Message: 'Reactivated' };
|
|
3921
4103
|
}
|
|
3922
4104
|
catch (e) {
|
|
@@ -4264,11 +4446,7 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
4264
4446
|
// Step 3: Build schema and RSU pipeline input
|
|
4265
4447
|
const { schemaOutput, rsuInput } = await this.buildSchemaForConnector(input.CompanyIntegrationID, objects, validatedPlatform, user, skipGitCommit, skipRestart, provider);
|
|
4266
4448
|
// Step 4: Inject integration post-restart payload into RSU input.
|
|
4267
|
-
|
|
4268
|
-
const rsuWorkDir = process.env.RSU_WORK_DIR || process.cwd();
|
|
4269
|
-
const pendingWorkDir = join(rsuWorkDir, '.rsu_pending');
|
|
4270
|
-
const pendingFilePath = join(pendingWorkDir, `${Date.now()}.json`);
|
|
4271
|
-
// Build per-object field map for pending file (null = all fields).
|
|
4449
|
+
// Build per-object field map for the pending payload (null = all fields).
|
|
4272
4450
|
// resolved.sourceObjects is order-aligned with resolvedNames after the
|
|
4273
4451
|
// resolveSourceObjectsToNames refactor — pair them directly instead
|
|
4274
4452
|
// of looking up by ID (which broke for name-only selections).
|
|
@@ -4298,13 +4476,12 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
4298
4476
|
ScheduleTimezone: input.ScheduleTimezone,
|
|
4299
4477
|
StartSync: input.StartSync,
|
|
4300
4478
|
FullSync: effectiveFullSync,
|
|
4301
|
-
SyncScope: input.SyncScope
|
|
4479
|
+
SyncScope: input.SyncScope === 'all' ? 'all' : 'created',
|
|
4302
4480
|
UnselectedAction: (input.UnselectedAction ?? 'disable'),
|
|
4303
4481
|
CreatedAt: new Date().toISOString(),
|
|
4304
4482
|
};
|
|
4305
|
-
rsuInput.
|
|
4306
|
-
|
|
4307
|
-
];
|
|
4483
|
+
rsuInput.PendingWork = [pendingPayload];
|
|
4484
|
+
rsuInput.ContextUser = user;
|
|
4308
4485
|
// Step 5: Run pipeline (restart kills process at the end).
|
|
4309
4486
|
// Retrying variant — an install should not die because the migration hit a dropped
|
|
4310
4487
|
// connection or a transient lock; it only replays while nothing has been applied.
|
|
@@ -4314,12 +4491,9 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
4314
4491
|
const pipelineSteps = batchResult.Results[0]?.Steps.map((s) => ({
|
|
4315
4492
|
Name: s.Name, Status: s.Status, DurationMs: s.DurationMs, Message: s.Message, StepIndex: s.StepIndex, StepTotal: s.StepTotal,
|
|
4316
4493
|
}));
|
|
4317
|
-
//
|
|
4494
|
+
// Pending work is registered only for migrations that succeeded, so a
|
|
4495
|
+
// failed pipeline has nothing to clean up.
|
|
4318
4496
|
if (!migrationSucceeded) {
|
|
4319
|
-
try {
|
|
4320
|
-
(await import('node:fs')).unlinkSync(pendingFilePath);
|
|
4321
|
-
}
|
|
4322
|
-
catch { /* may not exist */ }
|
|
4323
4497
|
return {
|
|
4324
4498
|
Success: false,
|
|
4325
4499
|
Message: `Pipeline failed: ${batchResult.Results[0]?.ErrorMessage ?? 'unknown error'}`,
|
|
@@ -4363,10 +4537,10 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
4363
4537
|
console.warn(`[Integration] Schedule creation failed: ${schedErr}`);
|
|
4364
4538
|
}
|
|
4365
4539
|
}
|
|
4366
|
-
|
|
4367
|
-
|
|
4540
|
+
// The work just happened inline (no restart), so close out its durable rows.
|
|
4541
|
+
for (const pendingWorkID of batchResult.Results[0]?.PendingWorkIDs ?? []) {
|
|
4542
|
+
await rsm.CompletePendingWork(pendingWorkID, user);
|
|
4368
4543
|
}
|
|
4369
|
-
catch { /* already consumed */ }
|
|
4370
4544
|
return {
|
|
4371
4545
|
Success: true,
|
|
4372
4546
|
Message: `Applied ${objects.length} object(s) — ${entityMapsCreated.length} entity maps created${syncRunID ? ', sync started' : ''}${scheduledJobID ? ', schedule created' : ''}`,
|
|
@@ -4847,14 +5021,56 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
4847
5021
|
return { Success: false, Message: this.formatError(e) };
|
|
4848
5022
|
}
|
|
4849
5023
|
}
|
|
5024
|
+
/**
|
|
5025
|
+
* Enqueue a sync for worker execution (PR 1 item 8) instead of running it in this
|
|
5026
|
+
* process. Creates the run row with `Status='Queued'` and returns its ID immediately —
|
|
5027
|
+
* so the caller gets a real, trackable RunID with no fire-and-forget polling window,
|
|
5028
|
+
* and the sync survives this process going away before it starts.
|
|
5029
|
+
*
|
|
5030
|
+
* Requires a process running the integration sync worker (`integrationSyncWorker.enabled`);
|
|
5031
|
+
* without one, rows accumulate in the queue unexecuted.
|
|
5032
|
+
*/
|
|
5033
|
+
async IntegrationEnqueueSync(companyIntegrationID, fullSync, entityMapIDs, syncDirection, ctx) {
|
|
5034
|
+
try {
|
|
5035
|
+
const user = this.getAuthenticatedUser(ctx);
|
|
5036
|
+
const provider = GetReadWriteProvider(ctx.providers);
|
|
5037
|
+
await IntegrationEngine.Instance.Config(false, user, provider);
|
|
5038
|
+
// Same upfront gates as IntegrationStartSync — refusing here beats queueing work
|
|
5039
|
+
// that the engine will only refuse later, in another process, out of the caller's sight.
|
|
5040
|
+
const ciCheck = await provider.GetEntityObject('MJ: Company Integrations', user);
|
|
5041
|
+
if (await ciCheck.InnerLoad(CompositeKey.FromID(companyIntegrationID)) && ciCheck.IsActive === false) {
|
|
5042
|
+
return { Success: false, Message: 'Connector is deactivated (IsActive=false); sync not enqueued' };
|
|
5043
|
+
}
|
|
5044
|
+
const maintenance = IntegrationEngine.GetMaintenanceLock(companyIntegrationID);
|
|
5045
|
+
if (maintenance) {
|
|
5046
|
+
return { Success: false, Message: `Sync not enqueued: ${maintenance.Reason} is in progress for this connection (since ${maintenance.AcquiredAt.toISOString()}). Retry after it completes.` };
|
|
5047
|
+
}
|
|
5048
|
+
const syncOptions = {};
|
|
5049
|
+
if (fullSync)
|
|
5050
|
+
syncOptions.FullSync = true;
|
|
5051
|
+
if (entityMapIDs?.length)
|
|
5052
|
+
syncOptions.EntityMapIDs = entityMapIDs;
|
|
5053
|
+
if (syncDirection)
|
|
5054
|
+
syncOptions.SyncDirection = syncDirection;
|
|
5055
|
+
const runID = await IntegrationEngine.Instance.EnqueueSync(companyIntegrationID, user, 'Manual', Object.keys(syncOptions).length > 0 ? syncOptions : undefined, provider);
|
|
5056
|
+
return { Success: true, Message: 'Sync enqueued', RunID: runID };
|
|
5057
|
+
}
|
|
5058
|
+
catch (e) {
|
|
5059
|
+
LogError(`IntegrationEnqueueSync error: ${e}`);
|
|
5060
|
+
return { Success: false, Message: this.formatError(e) };
|
|
5061
|
+
}
|
|
5062
|
+
}
|
|
4850
5063
|
/**
|
|
4851
5064
|
* Cancels a running sync by marking its status as Cancelled.
|
|
4852
5065
|
*/
|
|
4853
5066
|
async IntegrationCancelSync(companyIntegrationID, ctx) {
|
|
4854
5067
|
try {
|
|
4855
|
-
this.getAuthenticatedUser(ctx);
|
|
4856
|
-
|
|
4857
|
-
|
|
5068
|
+
const user = this.getAuthenticatedUser(ctx);
|
|
5069
|
+
const provider = GetReadWriteProvider(ctx.providers);
|
|
5070
|
+
// DB-backed cancel (durable runs): stamps CancelRequestedAt on the live run row, so
|
|
5071
|
+
// the request reaches the owning process wherever it is — this server, another API
|
|
5072
|
+
// node, or a worker — via its heartbeat/boundary checks. No in-memory signal.
|
|
5073
|
+
const cancelled = await IntegrationEngine.CancelSyncAsync(companyIntegrationID, user, provider);
|
|
4858
5074
|
if (!cancelled) {
|
|
4859
5075
|
return { Success: false, Message: 'No active sync found for this connector' };
|
|
4860
5076
|
}
|
|
@@ -5393,8 +5609,11 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5393
5609
|
}
|
|
5394
5610
|
async IntegrationGetSyncProgress(companyIntegrationID, ctx) {
|
|
5395
5611
|
try {
|
|
5396
|
-
this.getAuthenticatedUser(ctx);
|
|
5397
|
-
const
|
|
5612
|
+
const user = this.getAuthenticatedUser(ctx);
|
|
5613
|
+
const provider = GetReadOnlyProvider(ctx.providers, { allowFallbackToReadWrite: true });
|
|
5614
|
+
// DB-backed progress (durable runs): reads ProgressJSON from the live run row, so
|
|
5615
|
+
// progress is visible from ANY process — not just the one executing the sync.
|
|
5616
|
+
const syncProgress = await IntegrationEngine.GetSyncProgressAsync(companyIntegrationID, user, provider);
|
|
5398
5617
|
if (syncProgress) {
|
|
5399
5618
|
return {
|
|
5400
5619
|
Success: true,
|
|
@@ -5838,16 +6057,12 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5838
6057
|
return obj;
|
|
5839
6058
|
});
|
|
5840
6059
|
const { schemaOutput, rsuInput } = await this.buildSchemaForConnector(connInput.CompanyIntegrationID, objects, validatedPlatform, user, skipGitCommit, skipRestart, provider, sourceSchema);
|
|
5841
|
-
// Build per-object field map for pending
|
|
6060
|
+
// Build per-object field map for the pending payload
|
|
5842
6061
|
const sourceObjectFields = {};
|
|
5843
6062
|
for (const name of resolvedNames) {
|
|
5844
6063
|
sourceObjectFields[name] = fieldsByName.get(name.toLowerCase()) ?? null;
|
|
5845
6064
|
}
|
|
5846
6065
|
// Inject post-restart pending work payload
|
|
5847
|
-
const { join } = await import('node:path');
|
|
5848
|
-
const rsuWorkDir = process.env.RSU_WORK_DIR || process.cwd();
|
|
5849
|
-
const pendingWorkDir = join(rsuWorkDir, '.rsu_pending');
|
|
5850
|
-
const pendingFilePath = join(pendingWorkDir, `${Date.now()}_${connInput.CompanyIntegrationID}.json`);
|
|
5851
6066
|
const pendingPayload = {
|
|
5852
6067
|
CompanyIntegrationID: connInput.CompanyIntegrationID,
|
|
5853
6068
|
SourceObjectNames: resolvedNames,
|
|
@@ -5857,15 +6072,15 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5857
6072
|
ScheduleTimezone: connInput.ScheduleTimezone,
|
|
5858
6073
|
StartSync: input.StartSync,
|
|
5859
6074
|
FullSync: input.FullSync ?? false,
|
|
5860
|
-
SyncScope: input.SyncScope
|
|
5861
|
-
|
|
5862
|
-
|
|
6075
|
+
SyncScope: input.SyncScope === 'all' ? 'all' : 'created',
|
|
6076
|
+
// Unrecognized directions fall back to undefined = "use the entity map's own SyncDirection"
|
|
6077
|
+
SyncDirection: input.SyncDirection && isValidSyncDirection(input.SyncDirection) ? input.SyncDirection : undefined,
|
|
6078
|
+
ScheduleSyncDirection: input.ScheduleSyncDirection && isValidSyncDirection(input.ScheduleSyncDirection) ? input.ScheduleSyncDirection : undefined,
|
|
5863
6079
|
UnselectedAction: (input.UnselectedAction ?? 'disable'),
|
|
5864
6080
|
CreatedAt: new Date().toISOString(),
|
|
5865
6081
|
};
|
|
5866
|
-
rsuInput.
|
|
5867
|
-
|
|
5868
|
-
];
|
|
6082
|
+
rsuInput.PendingWork = [pendingPayload];
|
|
6083
|
+
rsuInput.ContextUser = user;
|
|
5869
6084
|
return {
|
|
5870
6085
|
connInput,
|
|
5871
6086
|
connector,
|
|
@@ -5874,7 +6089,6 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5874
6089
|
objects,
|
|
5875
6090
|
schemaOutput,
|
|
5876
6091
|
rsuInput,
|
|
5877
|
-
pendingFilePath,
|
|
5878
6092
|
};
|
|
5879
6093
|
}));
|
|
5880
6094
|
// Separate successes and failures
|
|
@@ -5925,11 +6139,8 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5925
6139
|
Message: pipelineResult?.ErrorMessage ?? 'Pipeline failed',
|
|
5926
6140
|
Warnings: build.schemaOutput.Warnings.length > 0 ? build.schemaOutput.Warnings : undefined,
|
|
5927
6141
|
});
|
|
5928
|
-
//
|
|
5929
|
-
|
|
5930
|
-
(await import('node:fs')).unlinkSync(build.pendingFilePath);
|
|
5931
|
-
}
|
|
5932
|
-
catch { /* may not exist */ }
|
|
6142
|
+
// No pending-work cleanup needed — rows are registered only for
|
|
6143
|
+
// migrations that succeeded.
|
|
5933
6144
|
continue;
|
|
5934
6145
|
}
|
|
5935
6146
|
const connResult = {
|
|
@@ -5965,11 +6176,10 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
5965
6176
|
if (scheduleResult)
|
|
5966
6177
|
connResult.ScheduledJobID = scheduleResult;
|
|
5967
6178
|
}
|
|
5968
|
-
//
|
|
5969
|
-
|
|
5970
|
-
|
|
6179
|
+
// The work just happened inline (no restart), so close out its durable rows.
|
|
6180
|
+
for (const pendingWorkID of pipelineResult.PendingWorkIDs ?? []) {
|
|
6181
|
+
await rsm.CompletePendingWork(pendingWorkID, user);
|
|
5971
6182
|
}
|
|
5972
|
-
catch { /* already consumed */ }
|
|
5973
6183
|
connResult.Message = `Applied ${build.objects.length} object(s) — ${entityMapsCreated.length} entity maps created${syncRunID ? ', sync started' : ''}`;
|
|
5974
6184
|
}
|
|
5975
6185
|
connectorResults.push(connResult);
|
|
@@ -6474,26 +6684,21 @@ let IntegrationDiscoveryResolver = class IntegrationDiscoveryResolver extends Re
|
|
|
6474
6684
|
// ApplyAll uses. default: created DISABLED (user enables after the refresh);
|
|
6475
6685
|
// autoEnableNewObjects opts in. Removal was already handled in Phase 3 → 'ignore'.
|
|
6476
6686
|
if (newObjects.length > 0 && !skipRestart) {
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
const pendingFilePath = join(rsuWorkDir, '.rsu_pending', `${Date.now()}-evolution.json`);
|
|
6480
|
-
rsuInput.PostRestartFiles = [
|
|
6481
|
-
...(rsuInput.PostRestartFiles ?? []),
|
|
6687
|
+
rsuInput.PendingWork = [
|
|
6688
|
+
...(rsuInput.PendingWork ?? []),
|
|
6482
6689
|
{
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
CreateDisabled: !autoEnableNewObjects,
|
|
6493
|
-
CreatedAt: new Date().toISOString(),
|
|
6494
|
-
}, null, 2),
|
|
6690
|
+
CompanyIntegrationID: companyIntegrationID,
|
|
6691
|
+
SourceObjectNames: newObjects,
|
|
6692
|
+
SourceObjectFields: Object.fromEntries(newObjects.map(n => [n, null])),
|
|
6693
|
+
SchemaName: schemaName,
|
|
6694
|
+
StartSync: false,
|
|
6695
|
+
SyncScope: 'created',
|
|
6696
|
+
UnselectedAction: 'ignore',
|
|
6697
|
+
CreateDisabled: !autoEnableNewObjects,
|
|
6698
|
+
CreatedAt: new Date().toISOString(),
|
|
6495
6699
|
},
|
|
6496
6700
|
];
|
|
6701
|
+
rsuInput.ContextUser = user;
|
|
6497
6702
|
}
|
|
6498
6703
|
const rsm = RuntimeSchemaManager.Instance;
|
|
6499
6704
|
const batchResult = await rsm.RunPipelineBatch([rsuInput]);
|
|
@@ -6751,9 +6956,10 @@ __decorate([
|
|
|
6751
6956
|
__param(1, Arg("testConnection", () => Boolean, { defaultValue: false })),
|
|
6752
6957
|
__param(2, Arg("runSchemaRefresh", () => Boolean, { defaultValue: true, description: "When true (default) and TestConnection succeeds, automatically runs IntegrationConnectorCreationPipeline (live introspect → persist Declared/Discovered/Custom → SoftPKClassifier). The intermittent server-side work the wizard's Forward step represents." })),
|
|
6753
6958
|
__param(3, Arg("universalPKConvention", { nullable: true, description: "Optional vendor-wide PK hint (e.g. 'id' for HubSpot). Improves SoftPKClassifier convergence." })),
|
|
6754
|
-
__param(4,
|
|
6959
|
+
__param(4, Arg("awaitSchemaRefresh", () => Boolean, { defaultValue: true, description: "When false, the schema refresh is launched detached and this mutation returns immediately with SchemaRefresh.RunID + InProgress=true — tail that run instead of blocking on a minutes-long live introspect. The introspect happens exactly once either way, and always AFTER the connection test, so a failed test rolls back a connection that left no discovered schema behind. Default true preserves the blocking behaviour (counts returned inline)." })),
|
|
6960
|
+
__param(5, Ctx()),
|
|
6755
6961
|
__metadata("design:type", Function),
|
|
6756
|
-
__metadata("design:paramtypes", [CreateConnectionInput, Boolean, Boolean, String, Object]),
|
|
6962
|
+
__metadata("design:paramtypes", [CreateConnectionInput, Boolean, Boolean, String, Boolean, Object]),
|
|
6757
6963
|
__metadata("design:returntype", Promise)
|
|
6758
6964
|
], IntegrationDiscoveryResolver.prototype, "IntegrationCreateConnection", null);
|
|
6759
6965
|
__decorate([
|
|
@@ -6765,9 +6971,10 @@ __decorate([
|
|
|
6765
6971
|
__param(4, Arg("testConnection", () => Boolean, { defaultValue: false })),
|
|
6766
6972
|
__param(5, Arg("runSchemaRefresh", () => Boolean, { defaultValue: true, description: "When true (default) and TestConnection succeeds, automatically runs IntegrationConnectorCreationPipeline. Same intermittent server-side step as the create flow." })),
|
|
6767
6973
|
__param(6, Arg("universalPKConvention", { nullable: true, description: "Optional vendor-wide PK hint (e.g. 'id' for HubSpot)" })),
|
|
6768
|
-
__param(7,
|
|
6974
|
+
__param(7, Arg("awaitSchemaRefresh", () => Boolean, { defaultValue: true, description: "When false, the schema refresh is launched detached and this mutation returns immediately with the run ID to tail instead of blocking on a minutes-long live introspect. Default true preserves the blocking behaviour." })),
|
|
6975
|
+
__param(8, Ctx()),
|
|
6769
6976
|
__metadata("design:type", Function),
|
|
6770
|
-
__metadata("design:paramtypes", [String, String, String, String, Boolean, Boolean, String, Object]),
|
|
6977
|
+
__metadata("design:paramtypes", [String, String, String, String, Boolean, Boolean, String, Boolean, Object]),
|
|
6771
6978
|
__metadata("design:returntype", Promise)
|
|
6772
6979
|
], IntegrationDiscoveryResolver.prototype, "IntegrationUpdateConnection", null);
|
|
6773
6980
|
__decorate([
|
|
@@ -6817,9 +7024,10 @@ __decorate([
|
|
|
6817
7024
|
__decorate([
|
|
6818
7025
|
Mutation(() => MutationResultOutput),
|
|
6819
7026
|
__param(0, Arg("companyIntegrationID")),
|
|
6820
|
-
__param(1,
|
|
7027
|
+
__param(1, Arg("runSchemaRefresh", () => Boolean, { defaultValue: true, description: "When true (default), re-runs IntegrationConnectorCreationPipeline after reactivating so the catalog reflects the source as it is now. Pass false to reactivate without a live scan — useful when the catalog is known-current, or when the source is large enough that discovery should be scheduled separately." })),
|
|
7028
|
+
__param(2, Ctx()),
|
|
6821
7029
|
__metadata("design:type", Function),
|
|
6822
|
-
__metadata("design:paramtypes", [String, Object]),
|
|
7030
|
+
__metadata("design:paramtypes", [String, Boolean, Object]),
|
|
6823
7031
|
__metadata("design:returntype", Promise)
|
|
6824
7032
|
], IntegrationDiscoveryResolver.prototype, "IntegrationReactivateConnection", null);
|
|
6825
7033
|
__decorate([
|
|
@@ -6881,6 +7089,18 @@ __decorate([
|
|
|
6881
7089
|
__metadata("design:paramtypes", [String, String, Boolean, Array, String, Object]),
|
|
6882
7090
|
__metadata("design:returntype", Promise)
|
|
6883
7091
|
], IntegrationDiscoveryResolver.prototype, "IntegrationStartSync", null);
|
|
7092
|
+
__decorate([
|
|
7093
|
+
Mutation(() => StartSyncOutput),
|
|
7094
|
+
RequireSystemUser(),
|
|
7095
|
+
__param(0, Arg("companyIntegrationID")),
|
|
7096
|
+
__param(1, Arg("fullSync", () => Boolean, { defaultValue: false, description: 'If true, ignores watermarks and re-fetches all records from the source' })),
|
|
7097
|
+
__param(2, Arg("entityMapIDs", () => [String], { nullable: true, description: 'Optional: sync only these entity maps. If omitted, syncs all maps for the connector.' })),
|
|
7098
|
+
__param(3, Arg("syncDirection", () => String, { nullable: true, description: 'Override sync direction: Pull | Push | Bidirectional. If omitted, each entity map\'s own SyncDirection is used.' })),
|
|
7099
|
+
__param(4, Ctx()),
|
|
7100
|
+
__metadata("design:type", Function),
|
|
7101
|
+
__metadata("design:paramtypes", [String, Boolean, Array, String, Object]),
|
|
7102
|
+
__metadata("design:returntype", Promise)
|
|
7103
|
+
], IntegrationDiscoveryResolver.prototype, "IntegrationEnqueueSync", null);
|
|
6884
7104
|
__decorate([
|
|
6885
7105
|
Mutation(() => MutationResultOutput),
|
|
6886
7106
|
__param(0, Arg("companyIntegrationID")),
|