@tailor-platform/sdk 1.83.0 → 1.85.0
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/CHANGELOG.md +58 -0
- package/dist/application-C-zsrNjn.mjs +3 -0
- package/dist/{application-Cp0FxIm2.mjs → application-m5tYtz0-.mjs} +246 -68
- package/dist/application-m5tYtz0-.mjs.map +1 -0
- package/dist/cli/commands/deploy/tailordb/index.d.mts +2 -0
- package/dist/cli/commands/generate/seed/bundler.d.mts +2 -1
- package/dist/cli/commands/generate/service.d.mts +1 -1
- package/dist/cli/commands/generate/types.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +11 -1
- package/dist/cli/commands/tailordb/migrate/schema-checks.d.mts +5 -0
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
- package/dist/cli/index.mjs +291 -29
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +1 -1
- package/dist/cli/lib.mjs +92 -36
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/shared/client.d.mts +28 -3
- package/dist/cli/skills.d.mts +1 -1
- package/dist/completion/zsh-worker.zsh +85 -22
- package/dist/configure/index.d.mts +2 -2
- package/dist/configure/index.mjs +170 -2
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/executor/index.d.mts +2 -2
- package/dist/configure/services/executor/trigger/event.d.mts +245 -2
- package/dist/configure/services/executor/trigger/index.d.mts +3 -3
- package/dist/configure/services/index.d.mts +2 -2
- package/dist/configure/services/tailordb/index.d.mts +0 -1
- package/dist/configure/services/workflow/job.d.mts +9 -0
- package/dist/configure/services/workflow/workflow.d.mts +10 -0
- package/dist/node-builtins-CmaL2Cbq.mjs +36 -0
- package/dist/node-builtins-CmaL2Cbq.mjs.map +1 -0
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/{register-typescript-runtime-CCHyKeXO.mjs → register-typescript-runtime-nG-n9lPw.mjs} +752 -403
- package/dist/register-typescript-runtime-nG-n9lPw.mjs.map +1 -0
- package/dist/{seed-DFFigL8V.mjs → seed-6eTFj-3Q.mjs} +158 -41
- package/dist/seed-6eTFj-3Q.mjs.map +1 -0
- package/dist/{service-B0MaodSg.mjs → service-CPJWhTLn.mjs} +29 -2
- package/dist/service-CPJWhTLn.mjs.map +1 -0
- package/dist/service-Cigg_U-v.mjs +3 -0
- package/dist/{service_pb-BwZRiNug.mjs → service_pb-D5--My_M.mjs} +5 -5
- package/dist/service_pb-D5--My_M.mjs.map +1 -0
- package/dist/{service_pb-wRkxUta6.mjs → service_pb-i8CmnQP4.mjs} +1 -1
- package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +106 -1
- package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +24 -1
- package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +49 -1
- package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +89 -6
- package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +26 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +101 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +22 -1
- package/dist/types/executor.generated.d.mts +23 -3
- package/dist/vitest/index.mjs +3 -35
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/{workspace_resource_pb-UGK1SSn_.mjs → workspace_resource_pb-DXnO2AT-.mjs} +7 -7
- package/dist/workspace_resource_pb-DXnO2AT-.mjs.map +1 -0
- package/docs/cli/tailordb.md +36 -12
- package/docs/cli-reference.md +16 -15
- package/docs/generator/builtin.md +7 -0
- package/docs/services/executor.md +83 -3
- package/docs/services/idp.md +3 -3
- package/docs/services/tailordb-migration.md +24 -4
- package/docs/services/workflow.md +26 -0
- package/package.json +17 -18
- package/dist/application-CP7JKG9R.mjs +0 -3
- package/dist/application-Cp0FxIm2.mjs.map +0 -1
- package/dist/register-typescript-runtime-CCHyKeXO.mjs.map +0 -1
- package/dist/seed-DFFigL8V.mjs.map +0 -1
- package/dist/service-B0MaodSg.mjs.map +0 -1
- package/dist/service-KnAiVofD.mjs +0 -3
- package/dist/service_pb-BwZRiNug.mjs.map +0 -1
- package/dist/workspace_resource_pb-UGK1SSn_.mjs.map +0 -1
package/dist/{register-typescript-runtime-CCHyKeXO.mjs → register-typescript-runtime-nG-n9lPw.mjs}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as db } from "./schema-CYrle8JZ.mjs";
|
|
2
|
-
import { $ as CreateAuthHookRequestSchema, B as IdPLang, Bt as Subgraph_ServiceType, C as CreateStaticWebsiteRequestSchema, Ct as AuthInvokerSchema, D as CreateSecretManagerSecretRequestSchema, Dt as AuthSCIMAttribute_Type, Et as AuthSCIMAttribute_Mutability, Ft as CreateApplicationRequestSchema, H as IdPPermissionPermit, Ht as UpdateAIGatewayRequestSchema, I as PipelineResolver_OperationType, It as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, Jt as FilterSchema, K as CreateExecutorExecutorRequestSchema, Kt as ConditionSchema, L as CreateIdPServiceRequestSchema, Lt as UpdateApplicationRequestSchema, M as CreatePipelineServiceRequestSchema, Mt as UserProfileProviderConfig_UserProfileProviderType, N as UpdatePipelineResolverRequestSchema, O as CreateSecretManagerVaultRequestSchema, Ot as AuthSCIMAttribute_Uniqueness, P as UpdatePipelineServiceRequestSchema, Q as CreateAuthConnectionRequestSchema, R as UpdateIdPServiceRequestSchema, S as AddCustomDomainRequestSchema, St as AuthIDPConfig_AuthType, Tt as AuthOAuth2Client_GrantType, U as FunctionExecution_Status, V as IdPPermissionOperator, Vt as CreateAIGatewayRequestSchema, X as ExecutorTargetType, Y as ExecutorJobStatus, Yt as PageDirection, Z as ExecutorTriggerType, _ as TailorDBGQLPermission_Permit, _t as UpdateUserProfileConfigRequestSchema, a as CreateWorkflowRequestSchema, at as CreateAuthServiceRequestSchema, b as TailorDBType_Permission_Permit, bt as AuthConnection_Type, ct as UpdateAuthConnectionRequestSchema, d as CreateTailorDBServiceRequestSchema, dt as UpdateAuthMachineUserRequestSchema, et as CreateAuthIDPConfigRequestSchema, f as CreateTailorDBTypeRequestSchema, ft as UpdateAuthOAuth2ClientRequestSchema, g as TailorDBGQLPermission_Operator, gt as UpdateTenantConfigRequestSchema, h as TailorDBGQLPermission_Action, ht as UpdateAuthServiceRequestSchema, i as CreateWorkflowJobFunctionRequestSchema, it as CreateAuthSCIMResourceRequestSchema, j as CreatePipelineResolverRequestSchema, jt as TenantProviderConfig_TenantProviderType, k as UpdateSecretManagerSecretRequestSchema, kt as AuthSCIMConfig_AuthorizationType, l as WorkflowExecution_Status, lt as UpdateAuthHookRequestSchema, mt as UpdateAuthSCIMResourceRequestSchema, nt as CreateAuthOAuth2ClientRequestSchema, o as UpdateWorkflowJobFunctionExecutionPolicyRequestSchema, ot as CreateTenantConfigRequestSchema, p as UpdateTailorDBTypeRequestSchema, pt as UpdateAuthSCIMConfigRequestSchema, q as UpdateExecutorExecutorRequestSchema, qt as Condition_Operator, r as CreateWorkflowJobFunctionExecutionPolicyRequestSchema, rt as CreateAuthSCIMConfigRequestSchema, s as UpdateWorkflowRequestSchema, st as CreateUserProfileConfigRequestSchema, t as WorkspacePlatformUserRole, tt as CreateAuthMachineUserRequestSchema, u as WorkflowJobExecution_Status, ut as UpdateAuthIDPConfigRequestSchema, v as TailorDBTypeSchema, w as UpdateStaticWebsiteRequestSchema, wt as AuthOAuth2Client_ClientType, x as TailorDBType_PermitAction, xt as AuthHookPoint, y as TailorDBType_Permission_Operator, yt as AuthConnection_Status, zt as ApplicationSchemaUpdateAttemptStatus } from "./workspace_resource_pb-
|
|
2
|
+
import { $ as CreateAuthHookRequestSchema, B as IdPLang, Bt as Subgraph_ServiceType, C as CreateStaticWebsiteRequestSchema, Ct as AuthInvokerSchema, D as CreateSecretManagerSecretRequestSchema, Dt as AuthSCIMAttribute_Type, Et as AuthSCIMAttribute_Mutability, Ft as CreateApplicationRequestSchema, H as IdPPermissionPermit, Ht as UpdateAIGatewayRequestSchema, I as PipelineResolver_OperationType, It as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, Jt as FilterSchema, K as CreateExecutorExecutorRequestSchema, Kt as ConditionSchema, L as CreateIdPServiceRequestSchema, Lt as UpdateApplicationRequestSchema, M as CreatePipelineServiceRequestSchema, Mt as UserProfileProviderConfig_UserProfileProviderType, N as UpdatePipelineResolverRequestSchema, O as CreateSecretManagerVaultRequestSchema, Ot as AuthSCIMAttribute_Uniqueness, P as UpdatePipelineServiceRequestSchema, Q as CreateAuthConnectionRequestSchema, R as UpdateIdPServiceRequestSchema, S as AddCustomDomainRequestSchema, St as AuthIDPConfig_AuthType, Tt as AuthOAuth2Client_GrantType, U as FunctionExecution_Status, V as IdPPermissionOperator, Vt as CreateAIGatewayRequestSchema, X as ExecutorTargetType, Y as ExecutorJobStatus, Yt as PageDirection, Z as ExecutorTriggerType, _ as TailorDBGQLPermission_Permit, _t as UpdateUserProfileConfigRequestSchema, a as CreateWorkflowRequestSchema, at as CreateAuthServiceRequestSchema, b as TailorDBType_Permission_Permit, bt as AuthConnection_Type, ct as UpdateAuthConnectionRequestSchema, d as CreateTailorDBServiceRequestSchema, dt as UpdateAuthMachineUserRequestSchema, et as CreateAuthIDPConfigRequestSchema, f as CreateTailorDBTypeRequestSchema, ft as UpdateAuthOAuth2ClientRequestSchema, g as TailorDBGQLPermission_Operator, gt as UpdateTenantConfigRequestSchema, h as TailorDBGQLPermission_Action, ht as UpdateAuthServiceRequestSchema, i as CreateWorkflowJobFunctionRequestSchema, it as CreateAuthSCIMResourceRequestSchema, j as CreatePipelineResolverRequestSchema, jt as TenantProviderConfig_TenantProviderType, k as UpdateSecretManagerSecretRequestSchema, kt as AuthSCIMConfig_AuthorizationType, l as WorkflowExecution_Status, lt as UpdateAuthHookRequestSchema, mt as UpdateAuthSCIMResourceRequestSchema, nt as CreateAuthOAuth2ClientRequestSchema, o as UpdateWorkflowJobFunctionExecutionPolicyRequestSchema, ot as CreateTenantConfigRequestSchema, p as UpdateTailorDBTypeRequestSchema, pt as UpdateAuthSCIMConfigRequestSchema, q as UpdateExecutorExecutorRequestSchema, qt as Condition_Operator, r as CreateWorkflowJobFunctionExecutionPolicyRequestSchema, rt as CreateAuthSCIMConfigRequestSchema, s as UpdateWorkflowRequestSchema, st as CreateUserProfileConfigRequestSchema, t as WorkspacePlatformUserRole, tt as CreateAuthMachineUserRequestSchema, u as WorkflowJobExecution_Status, ut as UpdateAuthIDPConfigRequestSchema, v as TailorDBTypeSchema, w as UpdateStaticWebsiteRequestSchema, wt as AuthOAuth2Client_ClientType, x as TailorDBType_PermitAction, xt as AuthHookPoint, y as TailorDBType_Permission_Operator, yt as AuthConnection_Status, zt as ApplicationSchemaUpdateAttemptStatus } from "./workspace_resource_pb-DXnO2AT-.mjs";
|
|
3
3
|
import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
|
|
4
4
|
import { a as parseBoolean, i as symbols, n as logger, o as renderTable, r as styles, t as CIPromptError } from "./logger-CXQq9YIp.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-
|
|
5
|
+
import { $ as LOG_LEVELS, A as hashContent, B as getConsoleBaseUrl, D as hasGenerationHooks, E as getPluginGenerationDependencies, F as fetchAllTolerant, G as initOperatorClient, H as getOrNull, I as fetchMachineUserToken, J as normalizeBaseUrl, K as isDefaultPlatform, L as fetchPaged, N as defaultPlatformBaseUrl, O as createBundleCache, P as fetchAll, Q as createApplyLimiter, T as createBundleLog, U as getPlatformBaseUrl, V as getOAuth2ClientId, W as initOAuth2Client, X as resolveStaticWebsiteUrls, Y as rememberPlatformConfigForToken, Z as byName, _ as stringifyFunction, b as resolveTSConfigWithFallback, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as TailorDBTypeSchema$1, h as assertUniqueTailorDBTypeNamesWithExternal, i as resolverBundleKey, j as hashFile, k as getDistDir, l as HTTP_METHODS, m as assertUniqueLocalTailorDBTypeNames, n as generatePluginFilesIfNeeded, o as WorkflowJobFunctionExecutionPolicySchema, q as isNotFoundError, r as loadApplication, t as defineApplication, v as createGeneratedEntryResolverPlugin, x as platformBundleDefinePlugin, y as createTsconfigPathsPlugin } from "./application-m5tYtz0-.mjs";
|
|
6
|
+
import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-CPJWhTLn.mjs";
|
|
7
7
|
import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-j9QBF0cB.mjs";
|
|
8
8
|
import { t as multiline } from "./multiline-sfHpTZZK.mjs";
|
|
9
9
|
import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "./file-utils-DcyIPFQh.mjs";
|
|
10
10
|
import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "./kysely-type-D-zflMGf.mjs";
|
|
11
|
-
import { n as seedPlugin, t as SeedGeneratorID } from "./seed-
|
|
11
|
+
import { n as seedPlugin, t as SeedGeneratorID } from "./seed-6eTFj-3Q.mjs";
|
|
12
12
|
import { t as readPackageJson } from "./package-json-8b0O9TlX.mjs";
|
|
13
13
|
import { t as userAgent } from "./user-agent-DX2Jnw0-.mjs";
|
|
14
14
|
import { r as isCLIError, t as createCLIError } from "./errors-DVFS0AZk.mjs";
|
|
@@ -5926,6 +5926,18 @@ function protoExecutor(context, executor) {
|
|
|
5926
5926
|
}
|
|
5927
5927
|
});
|
|
5928
5928
|
break;
|
|
5929
|
+
case "workflowExecution":
|
|
5930
|
+
case "workflowJobExecution":
|
|
5931
|
+
triggerType = ExecutorTriggerType.EVENT;
|
|
5932
|
+
triggerConfig = typedEventTrigger({
|
|
5933
|
+
case: "workflow",
|
|
5934
|
+
value: {
|
|
5935
|
+
eventTypes: trigger.events,
|
|
5936
|
+
workflowName: trigger.workflowName,
|
|
5937
|
+
...trigger.condition ? { condition: { expr: `(${stringifyFunction(trigger.condition)})(${argsExpr})` } } : {}
|
|
5938
|
+
}
|
|
5939
|
+
});
|
|
5940
|
+
break;
|
|
5929
5941
|
default: throw new Error(`Unknown trigger: ${trigger}`);
|
|
5930
5942
|
}
|
|
5931
5943
|
const target = executor.operation;
|
|
@@ -7200,6 +7212,10 @@ const warningChangeInfoSchema = z.looseObject({
|
|
|
7200
7212
|
fieldName: z.string().optional(),
|
|
7201
7213
|
reason: z.string()
|
|
7202
7214
|
});
|
|
7215
|
+
const scriptSkippedInfoSchema = z.looseObject({
|
|
7216
|
+
reason: z.string().trim().min(1),
|
|
7217
|
+
acknowledgedAt: z.string()
|
|
7218
|
+
});
|
|
7203
7219
|
const migrationDiffSchema = z.looseObject({
|
|
7204
7220
|
version: z.number(),
|
|
7205
7221
|
namespace: z.string(),
|
|
@@ -7210,7 +7226,8 @@ const migrationDiffSchema = z.looseObject({
|
|
|
7210
7226
|
breakingChanges: z.array(breakingChangeInfoSchema),
|
|
7211
7227
|
hasWarnings: z.boolean().optional(),
|
|
7212
7228
|
warnings: z.array(warningChangeInfoSchema).optional(),
|
|
7213
|
-
requiresMigrationScript: z.boolean()
|
|
7229
|
+
requiresMigrationScript: z.boolean(),
|
|
7230
|
+
scriptSkipped: scriptSkippedInfoSchema.optional()
|
|
7214
7231
|
});
|
|
7215
7232
|
|
|
7216
7233
|
//#endregion
|
|
@@ -7852,75 +7869,81 @@ function areFieldsDifferent(oldField, newField) {
|
|
|
7852
7869
|
return false;
|
|
7853
7870
|
}
|
|
7854
7871
|
/**
|
|
7855
|
-
*
|
|
7872
|
+
* Collect breaking changes for a field change
|
|
7856
7873
|
* @param {string} typeName - Name of the type containing the field
|
|
7857
7874
|
* @param {string} fieldName - Name of the field being changed
|
|
7858
7875
|
* @param {SnapshotFieldConfig | undefined} oldField - Old field configuration
|
|
7859
7876
|
* @param {SnapshotFieldConfig | undefined} newField - New field configuration
|
|
7860
|
-
* @returns {BreakingChangeInfo
|
|
7877
|
+
* @returns {BreakingChangeInfo[]} Breaking change information
|
|
7861
7878
|
*/
|
|
7862
|
-
function
|
|
7863
|
-
|
|
7879
|
+
function getBreakingFieldChanges(typeName, fieldName, oldField, newField) {
|
|
7880
|
+
const breakingChanges = [];
|
|
7881
|
+
if (!oldField && newField && newField.required) breakingChanges.push({
|
|
7864
7882
|
typeName,
|
|
7865
7883
|
fieldName,
|
|
7866
7884
|
reason: "Required field added"
|
|
7867
|
-
};
|
|
7868
|
-
if (oldField && newField && oldField.type !== newField.type)
|
|
7885
|
+
});
|
|
7886
|
+
if (oldField && newField && oldField.type !== newField.type) breakingChanges.push({
|
|
7869
7887
|
typeName,
|
|
7870
7888
|
fieldName,
|
|
7871
7889
|
reason: `Field type changed from ${oldField.type} to ${newField.type}`,
|
|
7872
7890
|
unsupported: true,
|
|
7873
7891
|
showThreeStepHint: true
|
|
7874
|
-
};
|
|
7875
|
-
if (oldField && newField && !oldField.required && newField.required)
|
|
7892
|
+
});
|
|
7893
|
+
if (oldField && newField && !oldField.required && newField.required) breakingChanges.push({
|
|
7876
7894
|
typeName,
|
|
7877
7895
|
fieldName,
|
|
7878
7896
|
reason: "Field changed from optional to required"
|
|
7879
|
-
};
|
|
7897
|
+
});
|
|
7880
7898
|
if (oldField && newField && (oldField.array ?? false) !== (newField.array ?? false)) {
|
|
7881
7899
|
const [fromType, toType] = oldField.array ? ["array", "single value"] : ["single value", "array"];
|
|
7882
|
-
|
|
7900
|
+
breakingChanges.push({
|
|
7883
7901
|
typeName,
|
|
7884
7902
|
fieldName,
|
|
7885
7903
|
reason: `Field changed from ${fromType} to ${toType}`,
|
|
7886
7904
|
unsupported: true,
|
|
7887
7905
|
showThreeStepHint: true
|
|
7888
|
-
};
|
|
7906
|
+
});
|
|
7889
7907
|
}
|
|
7890
7908
|
if (oldField && newField) {
|
|
7891
7909
|
const oldForeignKeyType = oldField.foreignKeyType;
|
|
7892
7910
|
const newForeignKeyType = newField.foreignKeyType;
|
|
7893
|
-
if (oldForeignKeyType && newForeignKeyType && oldForeignKeyType !== newForeignKeyType)
|
|
7911
|
+
if (oldForeignKeyType && newForeignKeyType && oldForeignKeyType !== newForeignKeyType) breakingChanges.push({
|
|
7894
7912
|
typeName,
|
|
7895
7913
|
fieldName,
|
|
7896
7914
|
reason: `Foreign key target type changed from ${oldForeignKeyType} to ${newForeignKeyType}`
|
|
7897
|
-
};
|
|
7915
|
+
});
|
|
7898
7916
|
}
|
|
7899
|
-
if (oldField && newField && !(oldField.unique ?? false) && (newField.unique ?? false))
|
|
7917
|
+
if (oldField && newField && !(oldField.unique ?? false) && (newField.unique ?? false)) breakingChanges.push({
|
|
7900
7918
|
typeName,
|
|
7901
7919
|
fieldName,
|
|
7902
7920
|
reason: "Unique constraint added to field"
|
|
7903
|
-
};
|
|
7921
|
+
});
|
|
7922
|
+
if (oldField?.type === "decimal" && newField?.type === "decimal" && oldField.scale !== newField.scale) breakingChanges.push({
|
|
7923
|
+
typeName,
|
|
7924
|
+
fieldName,
|
|
7925
|
+
reason: `Decimal scale changed from ${oldField.scale} to ${newField.scale}`
|
|
7926
|
+
});
|
|
7904
7927
|
if (oldField && newField && oldField.type === "enum" && newField.type === "enum") {
|
|
7905
7928
|
const oldAllowed = oldField.allowedValues ?? [];
|
|
7906
7929
|
const newAllowed = newField.allowedValues ?? [];
|
|
7907
7930
|
const oldValues = oldAllowed.map((v) => v.value);
|
|
7908
7931
|
const newValuesSet = new Set(newAllowed.map((v) => v.value));
|
|
7909
7932
|
const removedValues = oldValues.filter((v) => !newValuesSet.has(v));
|
|
7910
|
-
if (removedValues.length > 0)
|
|
7933
|
+
if (removedValues.length > 0) breakingChanges.push({
|
|
7911
7934
|
typeName,
|
|
7912
7935
|
fieldName,
|
|
7913
7936
|
reason: `Enum values removed: ${removedValues.join(", ")}`
|
|
7914
|
-
};
|
|
7937
|
+
});
|
|
7915
7938
|
}
|
|
7916
|
-
return
|
|
7939
|
+
return breakingChanges;
|
|
7917
7940
|
}
|
|
7918
7941
|
function addChange(ctx, change, oldField, newField) {
|
|
7919
7942
|
ctx.changes.push(change);
|
|
7920
7943
|
if (!change.fieldName) return;
|
|
7921
|
-
const
|
|
7922
|
-
if (
|
|
7923
|
-
ctx.breakingChanges.push(
|
|
7944
|
+
const breakingChanges = getBreakingFieldChanges(change.typeName, change.fieldName, oldField, newField);
|
|
7945
|
+
if (breakingChanges.length > 0) {
|
|
7946
|
+
ctx.breakingChanges.push(...breakingChanges);
|
|
7924
7947
|
return;
|
|
7925
7948
|
}
|
|
7926
7949
|
if (change.kind === "field_removed") ctx.warnings.push({
|
|
@@ -9521,6 +9544,283 @@ function handleOptionalToRequiredError(error, messages) {
|
|
|
9521
9544
|
throw error;
|
|
9522
9545
|
}
|
|
9523
9546
|
|
|
9547
|
+
//#endregion
|
|
9548
|
+
//#region src/cli/commands/tailordb/migrate/schema-checks.ts
|
|
9549
|
+
/**
|
|
9550
|
+
* Schema validation checks shared between `deploy` and
|
|
9551
|
+
* `tailordb migration validate`.
|
|
9552
|
+
*
|
|
9553
|
+
* These checks are read-only: they compare local type definitions, the
|
|
9554
|
+
* migration snapshot history, and the remote schema without mutating any
|
|
9555
|
+
* state.
|
|
9556
|
+
*/
|
|
9557
|
+
/**
|
|
9558
|
+
* Convert a runtime TailorDBService to the snapshot-shaped deploy input.
|
|
9559
|
+
* @param service - Loaded TailorDB service (after `loadTypes()`)
|
|
9560
|
+
* @returns The canonical snapshot-shaped deploy input for downstream plan/apply phases.
|
|
9561
|
+
*/
|
|
9562
|
+
function toTailorDBDeployInput(service) {
|
|
9563
|
+
const types = {};
|
|
9564
|
+
for (const [typeName, type] of Object.entries(service.types)) types[typeName] = createSnapshotType(type);
|
|
9565
|
+
return {
|
|
9566
|
+
namespace: service.namespace,
|
|
9567
|
+
config: service.config,
|
|
9568
|
+
types
|
|
9569
|
+
};
|
|
9570
|
+
}
|
|
9571
|
+
/**
|
|
9572
|
+
* Fetch all TailorDB types from remote for a namespace
|
|
9573
|
+
* @param {OperatorClient} client - Operator client instance
|
|
9574
|
+
* @param {string} workspaceId - Workspace ID
|
|
9575
|
+
* @param {string} namespace - TailorDB namespace
|
|
9576
|
+
* @returns {Promise<ProtoTailorDBType[]>} Remote TailorDB types
|
|
9577
|
+
*/
|
|
9578
|
+
async function fetchRemoteTypes(client, workspaceId, namespace) {
|
|
9579
|
+
return fetchAllTolerant(async (pageToken, maxPageSize) => {
|
|
9580
|
+
const { tailordbTypes, nextPageToken } = await client.listTailorDBTypes({
|
|
9581
|
+
workspaceId,
|
|
9582
|
+
namespaceName: namespace,
|
|
9583
|
+
pageToken,
|
|
9584
|
+
pageSize: maxPageSize
|
|
9585
|
+
});
|
|
9586
|
+
return [tailordbTypes, nextPageToken];
|
|
9587
|
+
});
|
|
9588
|
+
}
|
|
9589
|
+
async function fetchRemoteGqlPermissions(client, workspaceId, namespace) {
|
|
9590
|
+
return fetchAllTolerant(async (pageToken, maxPageSize) => {
|
|
9591
|
+
const { permissions, nextPageToken } = await client.listTailorDBGQLPermissions({
|
|
9592
|
+
workspaceId,
|
|
9593
|
+
namespaceName: namespace,
|
|
9594
|
+
pageToken,
|
|
9595
|
+
pageSize: maxPageSize
|
|
9596
|
+
});
|
|
9597
|
+
return [permissions, nextPageToken];
|
|
9598
|
+
});
|
|
9599
|
+
}
|
|
9600
|
+
function definedWhenNotEmpty(value) {
|
|
9601
|
+
return Object.keys(value).length > 0 ? value : void 0;
|
|
9602
|
+
}
|
|
9603
|
+
function namespaceConfig(config, tailorDBInputs, namespace) {
|
|
9604
|
+
return tailorDBInputs.find((input) => input.namespace === namespace)?.config ?? config.db?.[namespace];
|
|
9605
|
+
}
|
|
9606
|
+
function namespaceGqlOperations(config, tailorDBInputs, namespace) {
|
|
9607
|
+
return namespaceConfig(config, tailorDBInputs, namespace)?.gqlOperations;
|
|
9608
|
+
}
|
|
9609
|
+
const GQL_OPERATION_KEYS = [
|
|
9610
|
+
"create",
|
|
9611
|
+
"update",
|
|
9612
|
+
"delete",
|
|
9613
|
+
"read"
|
|
9614
|
+
];
|
|
9615
|
+
function configuredDisabledGqlOperations(operations) {
|
|
9616
|
+
if (!operations) return void 0;
|
|
9617
|
+
if (operations === "query") return {
|
|
9618
|
+
create: false,
|
|
9619
|
+
update: false,
|
|
9620
|
+
delete: false
|
|
9621
|
+
};
|
|
9622
|
+
const disabled = {};
|
|
9623
|
+
for (const key of GQL_OPERATION_KEYS) if (operations[key] === false) disabled[key] = false;
|
|
9624
|
+
return definedWhenNotEmpty(disabled);
|
|
9625
|
+
}
|
|
9626
|
+
function appliedConfiguredDisabledGqlOperations(remoteDisabled, configuredDisabled) {
|
|
9627
|
+
if (!remoteDisabled || !configuredDisabled) return void 0;
|
|
9628
|
+
const disabled = {};
|
|
9629
|
+
for (const key of GQL_OPERATION_KEYS) if (configuredDisabled[key] === false && remoteDisabled[key]) disabled[key] = false;
|
|
9630
|
+
return definedWhenNotEmpty(disabled);
|
|
9631
|
+
}
|
|
9632
|
+
function deployComparableSnapshot(snapshot, remoteTypes, gqlOperations) {
|
|
9633
|
+
const remoteTypesByName = new Map(remoteTypes.map((type) => [type.name, type]));
|
|
9634
|
+
const configuredDisabled = configuredDisabledGqlOperations(gqlOperations);
|
|
9635
|
+
const types = {};
|
|
9636
|
+
for (const [typeName, type] of Object.entries(snapshot.types)) {
|
|
9637
|
+
const settings = { ...type.settings };
|
|
9638
|
+
const remoteSettings = remoteTypesByName.get(typeName)?.schema?.settings;
|
|
9639
|
+
if (type.settings?.publishEvents === void 0 && remoteSettings?.publishRecordEvents) settings.publishEvents = true;
|
|
9640
|
+
if (type.settings?.gqlOperations === void 0) {
|
|
9641
|
+
const disabled = appliedConfiguredDisabledGqlOperations(remoteSettings?.disableGqlOperations, configuredDisabled);
|
|
9642
|
+
if (disabled) settings.gqlOperations = disabled;
|
|
9643
|
+
}
|
|
9644
|
+
const comparableType = { ...type };
|
|
9645
|
+
const comparableSettings = definedWhenNotEmpty(settings);
|
|
9646
|
+
if (comparableSettings) comparableType.settings = comparableSettings;
|
|
9647
|
+
else delete comparableType.settings;
|
|
9648
|
+
types[typeName] = comparableType;
|
|
9649
|
+
}
|
|
9650
|
+
return {
|
|
9651
|
+
...snapshot,
|
|
9652
|
+
types
|
|
9653
|
+
};
|
|
9654
|
+
}
|
|
9655
|
+
async function getRemoteMigrationNumberState(client, workspaceId, namespace) {
|
|
9656
|
+
const trn = resourceTrn(workspaceId, "tailordb", namespace);
|
|
9657
|
+
const metadata = await getOrNull(async () => {
|
|
9658
|
+
const { metadata } = await client.getMetadata({ trn });
|
|
9659
|
+
return metadata;
|
|
9660
|
+
});
|
|
9661
|
+
if (!metadata) return {
|
|
9662
|
+
metadataExists: false,
|
|
9663
|
+
number: null
|
|
9664
|
+
};
|
|
9665
|
+
const label = metadata.labels[MIGRATION_LABEL_KEY];
|
|
9666
|
+
if (!label) return {
|
|
9667
|
+
metadataExists: true,
|
|
9668
|
+
number: null
|
|
9669
|
+
};
|
|
9670
|
+
return {
|
|
9671
|
+
metadataExists: true,
|
|
9672
|
+
number: parseMigrationLabelNumber(label)
|
|
9673
|
+
};
|
|
9674
|
+
}
|
|
9675
|
+
/**
|
|
9676
|
+
* Get the current migration number from remote metadata
|
|
9677
|
+
* @param {OperatorClient} client - Operator client instance
|
|
9678
|
+
* @param {string} workspaceId - Workspace ID
|
|
9679
|
+
* @param {string} namespace - TailorDB namespace
|
|
9680
|
+
* @returns {Promise<number | null>} Current migration number, or null if no migration label exists
|
|
9681
|
+
*/
|
|
9682
|
+
async function getRemoteMigrationNumber(client, workspaceId, namespace) {
|
|
9683
|
+
return (await getRemoteMigrationNumberState(client, workspaceId, namespace)).number;
|
|
9684
|
+
}
|
|
9685
|
+
/**
|
|
9686
|
+
* Verify remote schema matches the expected snapshot state
|
|
9687
|
+
* @param {OperatorClient} client - Operator client instance
|
|
9688
|
+
* @param {string} workspaceId - Workspace ID
|
|
9689
|
+
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migration config
|
|
9690
|
+
* @param {LoadedConfig} config - Loaded application config
|
|
9691
|
+
* @param {ReadonlyArray<TailorDBDeployInput>} tailorDBInputs - Deploy inputs for namespace defaults
|
|
9692
|
+
* @returns {Promise<RemoteSchemaVerificationResult[]>} Verification results per namespace
|
|
9693
|
+
*/
|
|
9694
|
+
async function verifyRemoteSchema(client, workspaceId, namespacesWithMigrations, config, tailorDBInputs) {
|
|
9695
|
+
const results = [];
|
|
9696
|
+
for (const { namespace, migrationsDir } of namespacesWithMigrations) {
|
|
9697
|
+
const { metadataExists, number: remoteMigrationNumber } = await getRemoteMigrationNumberState(client, workspaceId, namespace);
|
|
9698
|
+
if (remoteMigrationNumber === null) {
|
|
9699
|
+
results.push({
|
|
9700
|
+
namespace,
|
|
9701
|
+
remoteMigrationNumber: 0,
|
|
9702
|
+
drifts: [],
|
|
9703
|
+
hasDrift: false,
|
|
9704
|
+
skipped: metadataExists ? "no_migration_label" : "not_deployed"
|
|
9705
|
+
});
|
|
9706
|
+
continue;
|
|
9707
|
+
}
|
|
9708
|
+
if (remoteMigrationNumber > getLatestMigrationNumber(migrationsDir)) {
|
|
9709
|
+
results.push({
|
|
9710
|
+
namespace,
|
|
9711
|
+
remoteMigrationNumber,
|
|
9712
|
+
drifts: [],
|
|
9713
|
+
hasDrift: false,
|
|
9714
|
+
checkpointMissingLocal: true
|
|
9715
|
+
});
|
|
9716
|
+
continue;
|
|
9717
|
+
}
|
|
9718
|
+
const expectedSnapshot = reconstructSnapshotFromMigrations(migrationsDir, remoteMigrationNumber);
|
|
9719
|
+
if (!expectedSnapshot) {
|
|
9720
|
+
results.push({
|
|
9721
|
+
namespace,
|
|
9722
|
+
remoteMigrationNumber,
|
|
9723
|
+
drifts: [],
|
|
9724
|
+
hasDrift: false,
|
|
9725
|
+
skipped: "no_snapshot"
|
|
9726
|
+
});
|
|
9727
|
+
continue;
|
|
9728
|
+
}
|
|
9729
|
+
const [remoteTypes, remoteGqlPermissions] = await Promise.all([fetchRemoteTypes(client, workspaceId, namespace), fetchRemoteGqlPermissions(client, workspaceId, namespace)]);
|
|
9730
|
+
const drifts = compareRemoteWithSnapshot(remoteTypes, deployComparableSnapshot(expectedSnapshot, remoteTypes, namespaceGqlOperations(config, tailorDBInputs, namespace)), remoteGqlPermissions);
|
|
9731
|
+
results.push({
|
|
9732
|
+
namespace,
|
|
9733
|
+
remoteMigrationNumber,
|
|
9734
|
+
drifts,
|
|
9735
|
+
hasDrift: drifts.length > 0
|
|
9736
|
+
});
|
|
9737
|
+
}
|
|
9738
|
+
return results;
|
|
9739
|
+
}
|
|
9740
|
+
/**
|
|
9741
|
+
* Log common causes of remote schema drift and how to resolve them
|
|
9742
|
+
*/
|
|
9743
|
+
function logRemoteDriftGuidance() {
|
|
9744
|
+
logger.info("This may indicate:");
|
|
9745
|
+
logger.info(" - Another developer applied different migrations", { mode: "plain" });
|
|
9746
|
+
logger.info(" - Manual schema changes were made directly", { mode: "plain" });
|
|
9747
|
+
logger.info(" - Migration history is out of sync", { mode: "plain" });
|
|
9748
|
+
logger.newline();
|
|
9749
|
+
logger.info("To resolve:");
|
|
9750
|
+
logger.info(" - Run 'tailor-sdk tailordb migration status' to compare local vs remote.", { mode: "plain" });
|
|
9751
|
+
logger.info(" - If remote is correct, update local types and run 'migration generate'.", { mode: "plain" });
|
|
9752
|
+
logger.info(" - If local migration history is correct, run 'migration sync <N>' to overwrite remote.", { mode: "plain" });
|
|
9753
|
+
logger.info(" - If only bookkeeping is stale, run 'migration set <N>'.", { mode: "plain" });
|
|
9754
|
+
}
|
|
9755
|
+
/**
|
|
9756
|
+
* Format remote schema verification results for display
|
|
9757
|
+
* @param {RemoteSchemaVerificationResult[]} results - Verification results
|
|
9758
|
+
* @returns {string} Formatted results string
|
|
9759
|
+
*/
|
|
9760
|
+
function formatRemoteVerificationResults(results) {
|
|
9761
|
+
const lines = [];
|
|
9762
|
+
for (const result of results) {
|
|
9763
|
+
if (!result.hasDrift) continue;
|
|
9764
|
+
lines.push(`Namespace: ${result.namespace}`);
|
|
9765
|
+
lines.push(` Remote migration: ${formatMigrationNumber(result.remoteMigrationNumber)}`);
|
|
9766
|
+
lines.push(` Differences:`);
|
|
9767
|
+
lines.push(formatSchemaDrifts(result.drifts));
|
|
9768
|
+
lines.push("");
|
|
9769
|
+
}
|
|
9770
|
+
return lines.join("\n");
|
|
9771
|
+
}
|
|
9772
|
+
/**
|
|
9773
|
+
* Check if there are schema differences between migration snapshots and local definitions
|
|
9774
|
+
* @param {ReadonlyMap<string, Record<string, TailorDBSnapshotType>>} typesByNamespace - Snapshot-shaped local types by namespace
|
|
9775
|
+
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migrations config
|
|
9776
|
+
* @returns {Promise<MigrationCheckResult[]>} Results for each namespace
|
|
9777
|
+
*/
|
|
9778
|
+
async function checkMigrationDiffs(typesByNamespace, namespacesWithMigrations) {
|
|
9779
|
+
const results = [];
|
|
9780
|
+
for (const { namespace, migrationsDir } of namespacesWithMigrations) {
|
|
9781
|
+
const localTypes = typesByNamespace.get(namespace);
|
|
9782
|
+
if (!localTypes) continue;
|
|
9783
|
+
const previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
|
|
9784
|
+
if (!previousSnapshot) {
|
|
9785
|
+
results.push({
|
|
9786
|
+
namespace,
|
|
9787
|
+
migrationsDir,
|
|
9788
|
+
hasDiff: true,
|
|
9789
|
+
diff: void 0
|
|
9790
|
+
});
|
|
9791
|
+
continue;
|
|
9792
|
+
}
|
|
9793
|
+
const diff = compareLocalTypesWithSnapshot(previousSnapshot, localTypes, namespace);
|
|
9794
|
+
results.push({
|
|
9795
|
+
namespace,
|
|
9796
|
+
migrationsDir,
|
|
9797
|
+
hasDiff: hasChanges(diff),
|
|
9798
|
+
diff: hasChanges(diff) ? diff : void 0
|
|
9799
|
+
});
|
|
9800
|
+
}
|
|
9801
|
+
return results;
|
|
9802
|
+
}
|
|
9803
|
+
/**
|
|
9804
|
+
* Format migration check results for display
|
|
9805
|
+
* @param {MigrationCheckResult[]} results - Migration check results
|
|
9806
|
+
* @returns {string} Formatted results string
|
|
9807
|
+
*/
|
|
9808
|
+
function formatMigrationCheckResults(results) {
|
|
9809
|
+
const lines = [];
|
|
9810
|
+
for (const result of results) {
|
|
9811
|
+
if (!result.hasDiff) continue;
|
|
9812
|
+
lines.push(`Namespace: ${result.namespace}`);
|
|
9813
|
+
if (!result.diff) lines.push(" No migration snapshot found. Run 'tailor-sdk tailordb migration generate' first.");
|
|
9814
|
+
else {
|
|
9815
|
+
lines.push(` ${formatDiffSummary(result.diff)}`);
|
|
9816
|
+
lines.push("");
|
|
9817
|
+
lines.push(formatMigrationDiff(result.diff));
|
|
9818
|
+
}
|
|
9819
|
+
lines.push("");
|
|
9820
|
+
}
|
|
9821
|
+
return lines.join("\n");
|
|
9822
|
+
}
|
|
9823
|
+
|
|
9524
9824
|
//#endregion
|
|
9525
9825
|
//#region src/cli/commands/tailordb/migrate/bundler.ts
|
|
9526
9826
|
/**
|
|
@@ -9569,31 +9869,39 @@ async function bundleMigrationScript(sourceFile, namespace, migrationNumber, env
|
|
|
9569
9869
|
}
|
|
9570
9870
|
`;
|
|
9571
9871
|
fs$1.writeFileSync(entryPath, entryContent);
|
|
9572
|
-
const
|
|
9872
|
+
const projectDir = baseDir ?? path.dirname(absoluteSourcePath);
|
|
9873
|
+
const tsconfig = await resolveTSConfigWithFallback(projectDir);
|
|
9874
|
+
const bundleLog = createBundleLog({ tsconfig });
|
|
9875
|
+
const result = await rolldown.build({
|
|
9876
|
+
plugins: [
|
|
9877
|
+
createGeneratedEntryResolverPlugin(entryPath, projectDir),
|
|
9878
|
+
createTsconfigPathsPlugin(),
|
|
9879
|
+
platformBundleDefinePlugin
|
|
9880
|
+
],
|
|
9881
|
+
input: entryPath,
|
|
9882
|
+
write: false,
|
|
9883
|
+
output: {
|
|
9884
|
+
format: "esm",
|
|
9885
|
+
sourcemap: false,
|
|
9886
|
+
minify: false,
|
|
9887
|
+
codeSplitting: false,
|
|
9888
|
+
globals: { tailordb: "tailordb" }
|
|
9889
|
+
},
|
|
9890
|
+
external: ["tailordb"],
|
|
9891
|
+
resolve: { conditionNames: ["node", "import"] },
|
|
9892
|
+
tsconfig,
|
|
9893
|
+
treeshake: {
|
|
9894
|
+
moduleSideEffects: false,
|
|
9895
|
+
annotations: true,
|
|
9896
|
+
unknownGlobalSideEffects: false
|
|
9897
|
+
},
|
|
9898
|
+
...bundleLog.options
|
|
9899
|
+
});
|
|
9900
|
+
bundleLog.assertAllResolved();
|
|
9573
9901
|
return {
|
|
9574
9902
|
namespace,
|
|
9575
9903
|
migrationNumber,
|
|
9576
|
-
bundledCode:
|
|
9577
|
-
plugins: [platformBundleDefinePlugin],
|
|
9578
|
-
input: entryPath,
|
|
9579
|
-
write: false,
|
|
9580
|
-
output: {
|
|
9581
|
-
format: "esm",
|
|
9582
|
-
sourcemap: false,
|
|
9583
|
-
minify: false,
|
|
9584
|
-
codeSplitting: false,
|
|
9585
|
-
globals: { tailordb: "tailordb" }
|
|
9586
|
-
},
|
|
9587
|
-
external: ["tailordb"],
|
|
9588
|
-
resolve: { conditionNames: ["node", "import"] },
|
|
9589
|
-
tsconfig,
|
|
9590
|
-
treeshake: {
|
|
9591
|
-
moduleSideEffects: false,
|
|
9592
|
-
annotations: true,
|
|
9593
|
-
unknownGlobalSideEffects: false
|
|
9594
|
-
},
|
|
9595
|
-
logLevel: "silent"
|
|
9596
|
-
})).output[0].code
|
|
9904
|
+
bundledCode: result.output[0].code
|
|
9597
9905
|
};
|
|
9598
9906
|
}
|
|
9599
9907
|
|
|
@@ -9855,8 +10163,9 @@ async function getCurrentMigrationNumber(client, workspaceId, namespace) {
|
|
|
9855
10163
|
const label = metadata?.labels[MIGRATION_LABEL_KEY];
|
|
9856
10164
|
if (!label) return 0;
|
|
9857
10165
|
return parseMigrationLabelNumber(label) ?? 0;
|
|
9858
|
-
} catch {
|
|
9859
|
-
return 0;
|
|
10166
|
+
} catch (error) {
|
|
10167
|
+
if (isNotFoundError(error)) return 0;
|
|
10168
|
+
throw error;
|
|
9860
10169
|
}
|
|
9861
10170
|
}
|
|
9862
10171
|
/**
|
|
@@ -9864,9 +10173,10 @@ async function getCurrentMigrationNumber(client, workspaceId, namespace) {
|
|
|
9864
10173
|
* @param {OperatorClient} client - Operator client instance
|
|
9865
10174
|
* @param {string} workspaceId - Workspace ID
|
|
9866
10175
|
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migrations config
|
|
10176
|
+
* @param {string} [configPath] - Config file path, included in remediation guidance when provided
|
|
9867
10177
|
* @returns {Promise<PendingMigration[]>} List of pending migrations
|
|
9868
10178
|
*/
|
|
9869
|
-
async function detectPendingMigrations(client, workspaceId, namespacesWithMigrations) {
|
|
10179
|
+
async function detectPendingMigrations(client, workspaceId, namespacesWithMigrations, configPath) {
|
|
9870
10180
|
const pendingMigrations = [];
|
|
9871
10181
|
for (const { namespace, migrationsDir } of namespacesWithMigrations) {
|
|
9872
10182
|
const currentMigration = await getCurrentMigrationNumber(client, workspaceId, namespace);
|
|
@@ -9878,9 +10188,15 @@ async function detectPendingMigrations(client, workspaceId, namespacesWithMigrat
|
|
|
9878
10188
|
const diff = loadDiff(diffPath);
|
|
9879
10189
|
const scriptPath = getMigrationFilePath(migrationsDir, file.number, "migrate");
|
|
9880
10190
|
const hasScript = fs$1.existsSync(scriptPath);
|
|
9881
|
-
if (diff.requiresMigrationScript && !hasScript) {
|
|
9882
|
-
|
|
9883
|
-
|
|
10191
|
+
if (diff.requiresMigrationScript && !hasScript && !diff.scriptSkipped) {
|
|
10192
|
+
const configArg = configPath ? ` --config "${path.relative(process.cwd(), configPath) || configPath}"` : "";
|
|
10193
|
+
const scriptCmd = `tailor-sdk tailordb migration script ${file.number} --namespace ${namespace}${configArg}`;
|
|
10194
|
+
throw new Error(`Migration ${namespace}/${formatMigrationNumber(file.number)} requires a migration script but migrate.ts was not found.\nTo resolve, either:\n - Add a script: ${scriptCmd}\n - Or record that no script is needed: ${scriptCmd} --no-script --reason "<why no data migration is needed>"`);
|
|
10195
|
+
}
|
|
10196
|
+
if (diff.scriptSkipped) {
|
|
10197
|
+
const migrationLabel = `${namespace}/${formatMigrationNumber(file.number)}`;
|
|
10198
|
+
if (hasScript) logger.warn(`Migration ${migrationLabel} has both a skip acknowledgment and migrate.ts; executing migrate.ts.`);
|
|
10199
|
+
else logger.info(`Migration ${migrationLabel} runs without a script (skip acknowledged at ${diff.scriptSkipped.acknowledgedAt}: ${diff.scriptSkipped.reason})`);
|
|
9884
10200
|
}
|
|
9885
10201
|
pendingMigrations.push({
|
|
9886
10202
|
number: file.number,
|
|
@@ -9984,198 +10300,67 @@ async function executeMigrations(context, migrations) {
|
|
|
9984
10300
|
}
|
|
9985
10301
|
}
|
|
9986
10302
|
/**
|
|
9987
|
-
* Get the machine user name for migration execution
|
|
9988
|
-
*
|
|
9989
|
-
* Priority:
|
|
9990
|
-
* 1. machineUser from migration config (if set)
|
|
9991
|
-
* 2. First machine user from auth config
|
|
9992
|
-
* @param {object | undefined} migrationConfig - Migration config for namespace
|
|
9993
|
-
* @param {string[] | undefined} machineUsers - Machine users from auth config
|
|
9994
|
-
* @returns {string | undefined} Machine user name or undefined if none available
|
|
9995
|
-
*/
|
|
9996
|
-
function getMigrationMachineUser(migrationConfig, machineUsers) {
|
|
9997
|
-
if (migrationConfig?.machineUser) return migrationConfig.machineUser;
|
|
9998
|
-
if (machineUsers && machineUsers.length > 0) return machineUsers[0];
|
|
9999
|
-
}
|
|
10000
|
-
/**
|
|
10001
|
-
* Group migrations by namespace
|
|
10002
|
-
* @param {PendingMigration[]} migrations - Migrations to group
|
|
10003
|
-
* @returns {Map<string, PendingMigration[]>} Migrations grouped by namespace
|
|
10004
|
-
*/
|
|
10005
|
-
function groupMigrationsByNamespace(migrations) {
|
|
10006
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
10007
|
-
for (const migration of migrations) {
|
|
10008
|
-
const existing = grouped.get(migration.namespace) ?? [];
|
|
10009
|
-
existing.push(migration);
|
|
10010
|
-
grouped.set(migration.namespace, existing);
|
|
10011
|
-
}
|
|
10012
|
-
return grouped;
|
|
10013
|
-
}
|
|
10014
|
-
|
|
10015
|
-
//#endregion
|
|
10016
|
-
//#region src/cli/commands/deploy/tailordb/index.ts
|
|
10017
|
-
/**
|
|
10018
|
-
* Fetch all TailorDB types from remote for a namespace
|
|
10019
|
-
* @param {OperatorClient} client - Operator client instance
|
|
10020
|
-
* @param {string} workspaceId - Workspace ID
|
|
10021
|
-
* @param {string} namespace - TailorDB namespace
|
|
10022
|
-
* @returns {Promise<ProtoTailorDBType[]>} Remote TailorDB types
|
|
10023
|
-
*/
|
|
10024
|
-
async function fetchRemoteTypes(client, workspaceId, namespace) {
|
|
10025
|
-
return fetchAllTolerant(async (pageToken, maxPageSize) => {
|
|
10026
|
-
const { tailordbTypes, nextPageToken } = await client.listTailorDBTypes({
|
|
10027
|
-
workspaceId,
|
|
10028
|
-
namespaceName: namespace,
|
|
10029
|
-
pageToken,
|
|
10030
|
-
pageSize: maxPageSize
|
|
10031
|
-
});
|
|
10032
|
-
return [tailordbTypes, nextPageToken];
|
|
10033
|
-
});
|
|
10034
|
-
}
|
|
10035
|
-
async function fetchRemoteGqlPermissions(client, workspaceId, namespace) {
|
|
10036
|
-
return fetchAllTolerant(async (pageToken, maxPageSize) => {
|
|
10037
|
-
const { permissions, nextPageToken } = await client.listTailorDBGQLPermissions({
|
|
10038
|
-
workspaceId,
|
|
10039
|
-
namespaceName: namespace,
|
|
10040
|
-
pageToken,
|
|
10041
|
-
pageSize: maxPageSize
|
|
10042
|
-
});
|
|
10043
|
-
return [permissions, nextPageToken];
|
|
10044
|
-
});
|
|
10045
|
-
}
|
|
10046
|
-
function definedWhenNotEmpty(value) {
|
|
10047
|
-
return Object.keys(value).length > 0 ? value : void 0;
|
|
10048
|
-
}
|
|
10049
|
-
function namespaceConfig(config, tailorDBInputs, namespace) {
|
|
10050
|
-
return tailorDBInputs.find((input) => input.namespace === namespace)?.config ?? config.db?.[namespace];
|
|
10051
|
-
}
|
|
10052
|
-
function namespaceGqlOperations(config, tailorDBInputs, namespace) {
|
|
10053
|
-
return namespaceConfig(config, tailorDBInputs, namespace)?.gqlOperations;
|
|
10054
|
-
}
|
|
10055
|
-
const GQL_OPERATION_KEYS = [
|
|
10056
|
-
"create",
|
|
10057
|
-
"update",
|
|
10058
|
-
"delete",
|
|
10059
|
-
"read"
|
|
10060
|
-
];
|
|
10061
|
-
function configuredDisabledGqlOperations(operations) {
|
|
10062
|
-
if (!operations) return void 0;
|
|
10063
|
-
if (operations === "query") return {
|
|
10064
|
-
create: false,
|
|
10065
|
-
update: false,
|
|
10066
|
-
delete: false
|
|
10067
|
-
};
|
|
10068
|
-
const disabled = {};
|
|
10069
|
-
for (const key of GQL_OPERATION_KEYS) if (operations[key] === false) disabled[key] = false;
|
|
10070
|
-
return definedWhenNotEmpty(disabled);
|
|
10071
|
-
}
|
|
10072
|
-
function appliedConfiguredDisabledGqlOperations(remoteDisabled, configuredDisabled) {
|
|
10073
|
-
if (!remoteDisabled || !configuredDisabled) return void 0;
|
|
10074
|
-
const disabled = {};
|
|
10075
|
-
for (const key of GQL_OPERATION_KEYS) if (configuredDisabled[key] === false && remoteDisabled[key]) disabled[key] = false;
|
|
10076
|
-
return definedWhenNotEmpty(disabled);
|
|
10077
|
-
}
|
|
10078
|
-
function deployComparableSnapshot(snapshot, remoteTypes, gqlOperations) {
|
|
10079
|
-
const remoteTypesByName = new Map(remoteTypes.map((type) => [type.name, type]));
|
|
10080
|
-
const configuredDisabled = configuredDisabledGqlOperations(gqlOperations);
|
|
10081
|
-
const types = {};
|
|
10082
|
-
for (const [typeName, type] of Object.entries(snapshot.types)) {
|
|
10083
|
-
const settings = { ...type.settings };
|
|
10084
|
-
const remoteSettings = remoteTypesByName.get(typeName)?.schema?.settings;
|
|
10085
|
-
if (type.settings?.publishEvents === void 0 && remoteSettings?.publishRecordEvents) settings.publishEvents = true;
|
|
10086
|
-
if (type.settings?.gqlOperations === void 0) {
|
|
10087
|
-
const disabled = appliedConfiguredDisabledGqlOperations(remoteSettings?.disableGqlOperations, configuredDisabled);
|
|
10088
|
-
if (disabled) settings.gqlOperations = disabled;
|
|
10089
|
-
}
|
|
10090
|
-
const comparableType = { ...type };
|
|
10091
|
-
const comparableSettings = definedWhenNotEmpty(settings);
|
|
10092
|
-
if (comparableSettings) comparableType.settings = comparableSettings;
|
|
10093
|
-
else delete comparableType.settings;
|
|
10094
|
-
types[typeName] = comparableType;
|
|
10095
|
-
}
|
|
10096
|
-
return {
|
|
10097
|
-
...snapshot,
|
|
10098
|
-
types
|
|
10099
|
-
};
|
|
10100
|
-
}
|
|
10101
|
-
/**
|
|
10102
|
-
* Get the current migration number from remote metadata
|
|
10103
|
-
* @param {OperatorClient} client - Operator client instance
|
|
10104
|
-
* @param {string} workspaceId - Workspace ID
|
|
10105
|
-
* @param {string} namespace - TailorDB namespace
|
|
10106
|
-
* @returns {Promise<number | null>} Current migration number, or null if no migration label exists
|
|
10303
|
+
* Get the machine user name for migration execution
|
|
10304
|
+
*
|
|
10305
|
+
* Priority:
|
|
10306
|
+
* 1. machineUser from migration config (if set)
|
|
10307
|
+
* 2. First machine user from auth config
|
|
10308
|
+
* @param {object | undefined} migrationConfig - Migration config for namespace
|
|
10309
|
+
* @param {string[] | undefined} machineUsers - Machine users from auth config
|
|
10310
|
+
* @returns {string | undefined} Machine user name or undefined if none available
|
|
10107
10311
|
*/
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
const { metadata } = await client.getMetadata({ trn });
|
|
10112
|
-
const label = metadata?.labels["sdk-migration"];
|
|
10113
|
-
if (!label) return null;
|
|
10114
|
-
const match = label.match(/^m(\d+)$/);
|
|
10115
|
-
return match ? parseInt(assertDefined(match[1], "migration label capture group missing"), 10) : null;
|
|
10116
|
-
} catch {
|
|
10117
|
-
return null;
|
|
10118
|
-
}
|
|
10312
|
+
function getMigrationMachineUser(migrationConfig, machineUsers) {
|
|
10313
|
+
if (migrationConfig?.machineUser) return migrationConfig.machineUser;
|
|
10314
|
+
if (machineUsers && machineUsers.length > 0) return machineUsers[0];
|
|
10119
10315
|
}
|
|
10120
10316
|
/**
|
|
10121
|
-
*
|
|
10122
|
-
* @param {
|
|
10123
|
-
* @
|
|
10124
|
-
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migration config
|
|
10125
|
-
* @param {LoadedConfig} config - Loaded application config
|
|
10126
|
-
* @param {ReadonlyArray<TailorDBDeployInput>} tailorDBInputs - Deploy inputs for namespace defaults
|
|
10127
|
-
* @returns {Promise<RemoteSchemaVerificationResult[]>} Verification results per namespace
|
|
10317
|
+
* Group migrations by namespace
|
|
10318
|
+
* @param {PendingMigration[]} migrations - Migrations to group
|
|
10319
|
+
* @returns {Map<string, PendingMigration[]>} Migrations grouped by namespace
|
|
10128
10320
|
*/
|
|
10129
|
-
|
|
10130
|
-
const
|
|
10131
|
-
for (const
|
|
10132
|
-
const
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
namespace,
|
|
10136
|
-
remoteMigrationNumber: 0,
|
|
10137
|
-
drifts: [],
|
|
10138
|
-
hasDrift: false
|
|
10139
|
-
});
|
|
10140
|
-
continue;
|
|
10141
|
-
}
|
|
10142
|
-
const expectedSnapshot = reconstructSnapshotFromMigrations(migrationsDir, remoteMigrationNumber);
|
|
10143
|
-
if (!expectedSnapshot) {
|
|
10144
|
-
results.push({
|
|
10145
|
-
namespace,
|
|
10146
|
-
remoteMigrationNumber,
|
|
10147
|
-
drifts: [],
|
|
10148
|
-
hasDrift: false
|
|
10149
|
-
});
|
|
10150
|
-
continue;
|
|
10151
|
-
}
|
|
10152
|
-
const [remoteTypes, remoteGqlPermissions] = await Promise.all([fetchRemoteTypes(client, workspaceId, namespace), fetchRemoteGqlPermissions(client, workspaceId, namespace)]);
|
|
10153
|
-
const drifts = compareRemoteWithSnapshot(remoteTypes, deployComparableSnapshot(expectedSnapshot, remoteTypes, namespaceGqlOperations(config, tailorDBInputs, namespace)), remoteGqlPermissions);
|
|
10154
|
-
results.push({
|
|
10155
|
-
namespace,
|
|
10156
|
-
remoteMigrationNumber,
|
|
10157
|
-
drifts,
|
|
10158
|
-
hasDrift: drifts.length > 0
|
|
10159
|
-
});
|
|
10321
|
+
function groupMigrationsByNamespace(migrations) {
|
|
10322
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
10323
|
+
for (const migration of migrations) {
|
|
10324
|
+
const existing = grouped.get(migration.namespace) ?? [];
|
|
10325
|
+
existing.push(migration);
|
|
10326
|
+
grouped.set(migration.namespace, existing);
|
|
10160
10327
|
}
|
|
10161
|
-
return
|
|
10328
|
+
return grouped;
|
|
10162
10329
|
}
|
|
10330
|
+
|
|
10331
|
+
//#endregion
|
|
10332
|
+
//#region src/cli/commands/deploy/tailordb/index.ts
|
|
10333
|
+
const MIGRATION_FILE_KINDS = [
|
|
10334
|
+
"schema",
|
|
10335
|
+
"diff",
|
|
10336
|
+
"migrate",
|
|
10337
|
+
"db"
|
|
10338
|
+
];
|
|
10163
10339
|
/**
|
|
10164
|
-
*
|
|
10165
|
-
* @param
|
|
10166
|
-
* @returns
|
|
10167
|
-
*/
|
|
10168
|
-
function
|
|
10169
|
-
const
|
|
10170
|
-
for (const
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10340
|
+
* Capture the migration files that a deployment plan depends on.
|
|
10341
|
+
* @param namespacesWithMigrations - Configured migration directories by namespace
|
|
10342
|
+
* @returns SHA-256 digest by namespace
|
|
10343
|
+
*/
|
|
10344
|
+
function captureMigrationFileState(namespacesWithMigrations) {
|
|
10345
|
+
const state = {};
|
|
10346
|
+
for (const { namespace, migrationsDir } of namespacesWithMigrations.toSorted((a, b) => a.namespace.localeCompare(b.namespace))) {
|
|
10347
|
+
const hash = createHash("sha256");
|
|
10348
|
+
const migrationNumbers = [...new Set(getMigrationFiles(migrationsDir).map(({ number }) => number))].toSorted((a, b) => a - b);
|
|
10349
|
+
for (const migrationNumber of migrationNumbers) for (const kind of MIGRATION_FILE_KINDS) {
|
|
10350
|
+
const filePath = getMigrationFilePath(migrationsDir, migrationNumber, kind);
|
|
10351
|
+
hash.update(`${formatMigrationNumber(migrationNumber)}/${kind}\0`);
|
|
10352
|
+
if (fs$1.existsSync(filePath)) hash.update(fs$1.readFileSync(filePath));
|
|
10353
|
+
else hash.update("<missing>");
|
|
10354
|
+
hash.update("\0");
|
|
10355
|
+
}
|
|
10356
|
+
state[namespace] = hash.digest("hex");
|
|
10177
10357
|
}
|
|
10178
|
-
return
|
|
10358
|
+
return state;
|
|
10359
|
+
}
|
|
10360
|
+
function migrationFileStatesEqual(planned, current) {
|
|
10361
|
+
const plannedNamespaces = Object.keys(planned).toSorted();
|
|
10362
|
+
const currentNamespaces = Object.keys(current).toSorted();
|
|
10363
|
+
return plannedNamespaces.length === currentNamespaces.length && plannedNamespaces.every((namespace, index) => namespace === currentNamespaces[index] && planned[namespace] === current[namespace]);
|
|
10179
10364
|
}
|
|
10180
10365
|
/**
|
|
10181
10366
|
* Validate migration files and detect pending migrations
|
|
@@ -10203,38 +10388,38 @@ async function validateAndDetectMigrations(client, workspaceId, typesByNamespace
|
|
|
10203
10388
|
throw new Error("Schema migration check failed");
|
|
10204
10389
|
}
|
|
10205
10390
|
const remoteVerificationResults = await verifyRemoteSchema(client, workspaceId, namespacesWithMigrations, config, tailorDBInputs);
|
|
10391
|
+
const missingCheckpointResults = remoteVerificationResults.filter((result) => result.checkpointMissingLocal);
|
|
10392
|
+
if (missingCheckpointResults.length > 0) {
|
|
10393
|
+
logger.error("Remote migration checkpoint is not in the local migration history:");
|
|
10394
|
+
for (const result of missingCheckpointResults) logger.log(` ${result.namespace}: ${formatMigrationNumber(result.remoteMigrationNumber)}`);
|
|
10395
|
+
logger.newline();
|
|
10396
|
+
logger.info("Pull the latest migration files, or run 'tailor-sdk tailordb migration status' to compare.");
|
|
10397
|
+
throw new Error("Remote migration checkpoint verification failed");
|
|
10398
|
+
}
|
|
10206
10399
|
if (remoteVerificationResults.some((r) => r.hasDrift)) {
|
|
10207
10400
|
logger.error("Remote schema drift detected:");
|
|
10208
10401
|
logger.log(formatRemoteVerificationResults(remoteVerificationResults));
|
|
10209
10402
|
logger.newline();
|
|
10210
|
-
|
|
10211
|
-
logger.info(" - Another developer applied different migrations", { mode: "plain" });
|
|
10212
|
-
logger.info(" - Manual schema changes were made directly", { mode: "plain" });
|
|
10213
|
-
logger.info(" - Migration history is out of sync", { mode: "plain" });
|
|
10214
|
-
logger.newline();
|
|
10215
|
-
logger.info("To resolve:");
|
|
10216
|
-
logger.info(" - Run 'tailor-sdk tailordb migration status' to compare local vs remote.", { mode: "plain" });
|
|
10217
|
-
logger.info(" - If remote is correct, update local types and run 'migration generate'.", { mode: "plain" });
|
|
10218
|
-
logger.info(" - If local migration history is correct, run 'migration sync <N>' to overwrite remote.", { mode: "plain" });
|
|
10219
|
-
logger.info(" - If only bookkeeping is stale, run 'migration set <N>'.", { mode: "plain" });
|
|
10403
|
+
logRemoteDriftGuidance();
|
|
10220
10404
|
logger.newline();
|
|
10221
10405
|
logger.info("Use '--no-schema-check' to skip this check (not recommended).");
|
|
10222
10406
|
throw new Error("Remote schema verification failed");
|
|
10223
10407
|
}
|
|
10224
10408
|
}
|
|
10225
|
-
pendingMigrations = await detectPendingMigrations(client, workspaceId, namespacesWithMigrations);
|
|
10409
|
+
pendingMigrations = await detectPendingMigrations(client, workspaceId, namespacesWithMigrations, config.path);
|
|
10226
10410
|
if (pendingMigrations.length > 0) {
|
|
10227
10411
|
logger.newline();
|
|
10228
10412
|
const withScripts = pendingMigrations.filter((m) => m.hasScript);
|
|
10229
10413
|
const withoutScripts = pendingMigrations.filter((m) => !m.hasScript);
|
|
10230
|
-
logger.info(
|
|
10414
|
+
logger.info(`${pendingMigrations.length} pending migration(s) will be applied:`);
|
|
10231
10415
|
if (withoutScripts.length > 0) logger.info(` • ${withoutScripts.length} schema change(s) (applied automatically with schema deployment)`, { mode: "plain" });
|
|
10232
10416
|
if (withScripts.length > 0) logger.info(` • ${withScripts.length} data migration(s) (requires migration script execution)`, { mode: "plain" });
|
|
10233
10417
|
}
|
|
10234
10418
|
}
|
|
10235
10419
|
return {
|
|
10236
10420
|
pendingMigrations,
|
|
10237
|
-
namespacesWithMigrations
|
|
10421
|
+
namespacesWithMigrations,
|
|
10422
|
+
migrationFileState: captureMigrationFileState(namespacesWithMigrations)
|
|
10238
10423
|
};
|
|
10239
10424
|
}
|
|
10240
10425
|
/**
|
|
@@ -10253,7 +10438,7 @@ async function reconcileMigrationLabels(client, workspaceId, namespacesWithMigra
|
|
|
10253
10438
|
for (const { namespace, migrationsDir } of namespacesWithMigrations) {
|
|
10254
10439
|
if (getMigrationFiles(migrationsDir).length === 0) continue;
|
|
10255
10440
|
const targetVersion = getLatestMigrationNumber(migrationsDir);
|
|
10256
|
-
const currentVersion = await getRemoteMigrationNumber(client, workspaceId, namespace);
|
|
10441
|
+
const currentVersion = await getRemoteMigrationNumber(client, workspaceId, namespace).catch(() => null);
|
|
10257
10442
|
if (currentVersion === targetVersion) continue;
|
|
10258
10443
|
await updateMigrationLabel(client, workspaceId, namespace, targetVersion);
|
|
10259
10444
|
const from = currentVersion === null ? "<unset>" : formatMigrationNumber(currentVersion);
|
|
@@ -10282,6 +10467,22 @@ function buildMigrationContextForScripts(client, migrationContext, migrationsReq
|
|
|
10282
10467
|
configDir: path.dirname(migrationContext.config.path)
|
|
10283
10468
|
};
|
|
10284
10469
|
}
|
|
10470
|
+
async function validateTailorDBMigrationState(client, result) {
|
|
10471
|
+
const { context } = result;
|
|
10472
|
+
const typesByNamespace = /* @__PURE__ */ new Map();
|
|
10473
|
+
for (const tailordb of context.tailorDBInputs) typesByNamespace.set(tailordb.namespace, tailordb.types);
|
|
10474
|
+
const validation = await validateAndDetectMigrations(client, context.workspaceId, typesByNamespace, context.config, context.noSchemaCheck, context.tailorDBInputs);
|
|
10475
|
+
if (!migrationFileStatesEqual(context.migrationFileState, validation.migrationFileState)) throw new Error("Migration files changed after deployment planning. Run the deployment again to create a fresh plan.");
|
|
10476
|
+
return validation;
|
|
10477
|
+
}
|
|
10478
|
+
/**
|
|
10479
|
+
* Revalidate migration state before the deployment enters any mutation phase.
|
|
10480
|
+
* @param client - Operator client instance
|
|
10481
|
+
* @param result - Planned TailorDB changes
|
|
10482
|
+
*/
|
|
10483
|
+
async function preflightTailorDB(client, result) {
|
|
10484
|
+
await validateTailorDBMigrationState(client, result);
|
|
10485
|
+
}
|
|
10285
10486
|
/**
|
|
10286
10487
|
* Apply TailorDB-related changes for the given phase.
|
|
10287
10488
|
* @param client - Operator client instance
|
|
@@ -10291,9 +10492,7 @@ function buildMigrationContextForScripts(client, migrationContext, migrationsReq
|
|
|
10291
10492
|
async function applyTailorDB(client, result, phase = "create-update") {
|
|
10292
10493
|
const { changeSet, context: migrationContext } = result;
|
|
10293
10494
|
if (phase === "create-update") {
|
|
10294
|
-
const
|
|
10295
|
-
for (const tailordb of migrationContext.tailorDBInputs) typesByNamespace.set(tailordb.namespace, tailordb.types);
|
|
10296
|
-
const { pendingMigrations, namespacesWithMigrations } = await validateAndDetectMigrations(client, migrationContext.workspaceId, typesByNamespace, migrationContext.config, migrationContext.noSchemaCheck, migrationContext.tailorDBInputs);
|
|
10495
|
+
const { pendingMigrations, namespacesWithMigrations } = await validateTailorDBMigrationState(client, result);
|
|
10297
10496
|
if (pendingMigrations.length > 0) {
|
|
10298
10497
|
processedTypes.reset();
|
|
10299
10498
|
deletedResources.reset();
|
|
@@ -10678,19 +10877,10 @@ async function rollbackSingleMigrationPrePhase(client, changeSet, migration, wor
|
|
|
10678
10877
|
}
|
|
10679
10878
|
}
|
|
10680
10879
|
/**
|
|
10681
|
-
*
|
|
10682
|
-
* @param
|
|
10683
|
-
* @returns
|
|
10880
|
+
* Plan TailorDB-related changes based on current and desired state.
|
|
10881
|
+
* @param context - Planning context
|
|
10882
|
+
* @returns Planned changes
|
|
10684
10883
|
*/
|
|
10685
|
-
function toTailorDBDeployInput(service) {
|
|
10686
|
-
const types = {};
|
|
10687
|
-
for (const [typeName, type] of Object.entries(service.types)) types[typeName] = createSnapshotType(type);
|
|
10688
|
-
return {
|
|
10689
|
-
namespace: service.namespace,
|
|
10690
|
-
config: service.config,
|
|
10691
|
-
types
|
|
10692
|
-
};
|
|
10693
|
-
}
|
|
10694
10884
|
async function planTailorDB(context) {
|
|
10695
10885
|
const { client, workspaceId, application, forRemoval, config, noSchemaCheck, forceApplyAll = false } = context;
|
|
10696
10886
|
const tailordbs = [];
|
|
@@ -10701,6 +10891,12 @@ async function planTailorDB(context) {
|
|
|
10701
10891
|
const executors = forRemoval ? [] : Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
10702
10892
|
const executorUsedTypes = new Set(context.executorUsedTailorDBTypes ?? []);
|
|
10703
10893
|
for (const executor of executors) if (executor.trigger.kind === "tailordb") executorUsedTypes.add(executor.trigger.typeName);
|
|
10894
|
+
const typesByNamespace = /* @__PURE__ */ new Map();
|
|
10895
|
+
for (const tailordb of tailordbs) typesByNamespace.set(tailordb.namespace, tailordb.types);
|
|
10896
|
+
const { namespacesWithMigrations, migrationFileState } = forRemoval ? {
|
|
10897
|
+
namespacesWithMigrations: [],
|
|
10898
|
+
migrationFileState: {}
|
|
10899
|
+
} : await validateAndDetectMigrations(client, workspaceId, typesByNamespace, config, noSchemaCheck ?? false, tailordbs);
|
|
10704
10900
|
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, application.id, tailordbs);
|
|
10705
10901
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
10706
10902
|
const [typeChangeSet, gqlPermissionChangeSet] = await Promise.all([planTypes(client, workspaceId, tailordbs, executorUsedTypes, deletedServices, void 0, forceApplyAll), planGqlPermissions(client, workspaceId, tailordbs, deletedServices, forceApplyAll)]);
|
|
@@ -10722,7 +10918,9 @@ async function planTailorDB(context) {
|
|
|
10722
10918
|
tailorDBInputs: tailordbs,
|
|
10723
10919
|
executorUsedTypes,
|
|
10724
10920
|
config,
|
|
10725
|
-
noSchemaCheck: noSchemaCheck ?? false
|
|
10921
|
+
noSchemaCheck: noSchemaCheck ?? false,
|
|
10922
|
+
namespacesWithMigrations,
|
|
10923
|
+
migrationFileState
|
|
10726
10924
|
}
|
|
10727
10925
|
};
|
|
10728
10926
|
}
|
|
@@ -11070,57 +11268,6 @@ function normalizeComparableGqlPermission(permission) {
|
|
|
11070
11268
|
actions: (policy.actions ?? []).toSorted((left, right) => left - right)
|
|
11071
11269
|
})) };
|
|
11072
11270
|
}
|
|
11073
|
-
/**
|
|
11074
|
-
* Check if there are schema differences between migration snapshots and local definitions
|
|
11075
|
-
* @param {ReadonlyMap<string, Record<string, TailorDBSnapshotType>>} typesByNamespace - Snapshot-shaped local types by namespace
|
|
11076
|
-
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migrations config
|
|
11077
|
-
* @returns {Promise<MigrationCheckResult[]>} Results for each namespace
|
|
11078
|
-
*/
|
|
11079
|
-
async function checkMigrationDiffs(typesByNamespace, namespacesWithMigrations) {
|
|
11080
|
-
const results = [];
|
|
11081
|
-
for (const { namespace, migrationsDir } of namespacesWithMigrations) {
|
|
11082
|
-
const localTypes = typesByNamespace.get(namespace);
|
|
11083
|
-
if (!localTypes) continue;
|
|
11084
|
-
const previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
|
|
11085
|
-
if (!previousSnapshot) {
|
|
11086
|
-
results.push({
|
|
11087
|
-
namespace,
|
|
11088
|
-
migrationsDir,
|
|
11089
|
-
hasDiff: true,
|
|
11090
|
-
diff: void 0
|
|
11091
|
-
});
|
|
11092
|
-
continue;
|
|
11093
|
-
}
|
|
11094
|
-
const diff = compareLocalTypesWithSnapshot(previousSnapshot, localTypes, namespace);
|
|
11095
|
-
results.push({
|
|
11096
|
-
namespace,
|
|
11097
|
-
migrationsDir,
|
|
11098
|
-
hasDiff: hasChanges(diff),
|
|
11099
|
-
diff: hasChanges(diff) ? diff : void 0
|
|
11100
|
-
});
|
|
11101
|
-
}
|
|
11102
|
-
return results;
|
|
11103
|
-
}
|
|
11104
|
-
/**
|
|
11105
|
-
* Format migration check results for display
|
|
11106
|
-
* @param {MigrationCheckResult[]} results - Migration check results
|
|
11107
|
-
* @returns {string} Formatted results string
|
|
11108
|
-
*/
|
|
11109
|
-
function formatMigrationCheckResults(results) {
|
|
11110
|
-
const lines = [];
|
|
11111
|
-
for (const result of results) {
|
|
11112
|
-
if (!result.hasDiff) continue;
|
|
11113
|
-
lines.push(`Namespace: ${result.namespace}`);
|
|
11114
|
-
if (!result.diff) lines.push(" No migration snapshot found. Run 'tailor-sdk tailordb migration generate' first.");
|
|
11115
|
-
else {
|
|
11116
|
-
lines.push(` ${formatDiffSummary(result.diff)}`);
|
|
11117
|
-
lines.push("");
|
|
11118
|
-
lines.push(formatMigrationDiff(result.diff));
|
|
11119
|
-
}
|
|
11120
|
-
lines.push("");
|
|
11121
|
-
}
|
|
11122
|
-
return lines.join("\n");
|
|
11123
|
-
}
|
|
11124
11271
|
|
|
11125
11272
|
//#endregion
|
|
11126
11273
|
//#region src/cli/commands/deploy/workflow.ts
|
|
@@ -11134,7 +11281,7 @@ function formatMigrationCheckResults(results) {
|
|
|
11134
11281
|
async function applyWorkflow(client, result, phase = "create-update") {
|
|
11135
11282
|
const { changeSet, appName, appId } = result;
|
|
11136
11283
|
if (phase === "create-update") {
|
|
11137
|
-
const jobFunctionVersions = await registerJobFunctions(client, changeSet, appName, appId, result.unchangedWorkflowJobNames);
|
|
11284
|
+
const jobFunctionVersions = await registerJobFunctions(client, changeSet, appName, appId, result.unchangedWorkflowJobNames, result.jobFunctionPublishEvents);
|
|
11138
11285
|
await Promise.all([...changeSet.creates.map(async (create) => {
|
|
11139
11286
|
const filteredVersions = filterJobFunctionVersions(jobFunctionVersions, create.usedJobNames);
|
|
11140
11287
|
const shape = buildWorkflowValidationShape(create.workspaceId, create.workflow);
|
|
@@ -11144,7 +11291,8 @@ async function applyWorkflow(client, result, phase = "create-update") {
|
|
|
11144
11291
|
mainJobFunctionName: shape.mainJobFunctionName,
|
|
11145
11292
|
retryPolicy: shape.retryPolicy,
|
|
11146
11293
|
concurrencyPolicy: shape.concurrencyPolicy,
|
|
11147
|
-
jobFunctions: filteredVersions
|
|
11294
|
+
jobFunctions: filteredVersions,
|
|
11295
|
+
publishExecutionEvents: shape.publishExecutionEvents
|
|
11148
11296
|
});
|
|
11149
11297
|
await client.setMetadata(create.metaRequest);
|
|
11150
11298
|
}), ...changeSet.updates.map(async (update) => {
|
|
@@ -11156,7 +11304,8 @@ async function applyWorkflow(client, result, phase = "create-update") {
|
|
|
11156
11304
|
mainJobFunctionName: shape.mainJobFunctionName,
|
|
11157
11305
|
retryPolicy: shape.retryPolicy,
|
|
11158
11306
|
concurrencyPolicy: shape.concurrencyPolicy,
|
|
11159
|
-
jobFunctions: filteredVersions
|
|
11307
|
+
jobFunctions: filteredVersions,
|
|
11308
|
+
publishExecutionEvents: shape.publishExecutionEvents
|
|
11160
11309
|
});
|
|
11161
11310
|
await client.setMetadata(update.metaRequest);
|
|
11162
11311
|
})]);
|
|
@@ -11217,9 +11366,10 @@ function filterJobFunctionVersions(allVersions, usedJobNames) {
|
|
|
11217
11366
|
* @param appName - Application name
|
|
11218
11367
|
* @param appId - Application ID used for job function metadata when available
|
|
11219
11368
|
* @param unchangedWorkflowJobNames - Job function names used by unchanged workflows
|
|
11369
|
+
* @param jobFunctionPublishEvents - Resolved `publishExecutionEvents` keyed by job function name
|
|
11220
11370
|
* @returns Map of job function names to versions
|
|
11221
11371
|
*/
|
|
11222
|
-
async function registerJobFunctions(client, changeSet, appName, appId, unchangedWorkflowJobNames = /* @__PURE__ */ new Set()) {
|
|
11372
|
+
async function registerJobFunctions(client, changeSet, appName, appId, unchangedWorkflowJobNames = /* @__PURE__ */ new Set(), jobFunctionPublishEvents = /* @__PURE__ */ new Map()) {
|
|
11223
11373
|
const jobFunctionVersions = {};
|
|
11224
11374
|
const firstWorkflow = changeSet.creates[0] || changeSet.updates[0] || changeSet.deletes[0];
|
|
11225
11375
|
if (!firstWorkflow) return jobFunctionVersions;
|
|
@@ -11238,15 +11388,14 @@ async function registerJobFunctions(client, changeSet, appName, appId, unchanged
|
|
|
11238
11388
|
const existingJobNamesSet = new Set(existingJobFunctions);
|
|
11239
11389
|
if (changeSet.creates.length > 0 || changeSet.updates.length > 0) {
|
|
11240
11390
|
const results = await Promise.all(Array.from(allUsedJobNames).map(async (jobName) => {
|
|
11241
|
-
const
|
|
11242
|
-
|
|
11243
|
-
jobFunctionName: jobName,
|
|
11244
|
-
scriptRef: workflowJobFunctionName(jobName)
|
|
11245
|
-
}) : await client.createWorkflowJobFunction({
|
|
11391
|
+
const isExisting = existingJobNamesSet.has(jobName);
|
|
11392
|
+
const request = {
|
|
11246
11393
|
workspaceId,
|
|
11247
11394
|
jobFunctionName: jobName,
|
|
11248
|
-
scriptRef: workflowJobFunctionName(jobName)
|
|
11249
|
-
|
|
11395
|
+
scriptRef: workflowJobFunctionName(jobName),
|
|
11396
|
+
publishExecutionEvents: jobFunctionPublishEvents.get(jobName) ?? false
|
|
11397
|
+
};
|
|
11398
|
+
const response = isExisting ? await client.updateWorkflowJobFunction(request) : await client.createWorkflowJobFunction(request);
|
|
11250
11399
|
await client.setMetadata(await buildMetaRequest({
|
|
11251
11400
|
trn: resourceTrn(workspaceId, "workflow_job_function", jobName),
|
|
11252
11401
|
appName,
|
|
@@ -11293,9 +11442,64 @@ function buildWorkflowValidationShape(workspaceId, workflow) {
|
|
|
11293
11442
|
workflowName: workflow.name,
|
|
11294
11443
|
mainJobFunctionName: workflow.mainJob.name,
|
|
11295
11444
|
...workflow.retryPolicy && { retryPolicy: toRetryPolicy(workflow.retryPolicy) },
|
|
11296
|
-
...workflow.concurrencyPolicy && { concurrencyPolicy: toConcurrencyPolicy(workflow.concurrencyPolicy) }
|
|
11445
|
+
...workflow.concurrencyPolicy && { concurrencyPolicy: toConcurrencyPolicy(workflow.concurrencyPolicy) },
|
|
11446
|
+
publishExecutionEvents: workflow.publishEvents ?? false
|
|
11297
11447
|
};
|
|
11298
11448
|
}
|
|
11449
|
+
const NO_EVENT_SUBSCRIBERS = { workflowNames: /* @__PURE__ */ new Set() };
|
|
11450
|
+
function isSubscribed(subscribers, workflowName) {
|
|
11451
|
+
return subscribers.workflowNames.has(workflowName);
|
|
11452
|
+
}
|
|
11453
|
+
function resolvePublishEvents(params) {
|
|
11454
|
+
const { explicit, subscribed, remote, conflictError } = params;
|
|
11455
|
+
if (explicit === false && subscribed) throw new Error(conflictError);
|
|
11456
|
+
if (explicit !== void 0) return explicit;
|
|
11457
|
+
return subscribed || (remote ?? false);
|
|
11458
|
+
}
|
|
11459
|
+
/**
|
|
11460
|
+
* Resolve `publishExecutionEvents` for every job function used by a workflow.
|
|
11461
|
+
*
|
|
11462
|
+
* A job execution trigger names a workflow rather than a job, so a subscription
|
|
11463
|
+
* opts in every job that workflow runs.
|
|
11464
|
+
* @param params - Workflows, their job dependencies, subscribers, explicit job flags, and existing job functions
|
|
11465
|
+
* @returns Resolved flags keyed by job function name
|
|
11466
|
+
*/
|
|
11467
|
+
function resolveJobPublishEvents(params) {
|
|
11468
|
+
const { workflows, mainJobDeps, subscribers, explicit, existing } = params;
|
|
11469
|
+
const usedJobNames = /* @__PURE__ */ new Set();
|
|
11470
|
+
const subscribedJobNames = /* @__PURE__ */ new Set();
|
|
11471
|
+
for (const workflow of Object.values(workflows)) {
|
|
11472
|
+
const jobNames = mainJobDeps[workflow.mainJob.name];
|
|
11473
|
+
if (!jobNames) continue;
|
|
11474
|
+
const subscribed = isSubscribed(subscribers, workflow.name);
|
|
11475
|
+
for (const jobName of jobNames) {
|
|
11476
|
+
usedJobNames.add(jobName);
|
|
11477
|
+
if (subscribed) subscribedJobNames.add(jobName);
|
|
11478
|
+
}
|
|
11479
|
+
}
|
|
11480
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
11481
|
+
for (const jobName of usedJobNames) resolved.set(jobName, resolvePublishEvents({
|
|
11482
|
+
explicit: explicit.get(jobName),
|
|
11483
|
+
subscribed: subscribedJobNames.has(jobName),
|
|
11484
|
+
remote: existing.get(jobName)?.publishExecutionEvents,
|
|
11485
|
+
conflictError: `Job "${jobName}" has "publishEvents: false", but executors with a workflowJobExecution trigger subscribe to a workflow that runs it. Either remove "publishEvents: false" or remove the matching executor triggers.`
|
|
11486
|
+
}));
|
|
11487
|
+
return resolved;
|
|
11488
|
+
}
|
|
11489
|
+
/**
|
|
11490
|
+
* Collect job functions whose remote publishing flag no longer matches the plan.
|
|
11491
|
+
* @param existing - Existing job functions keyed by name
|
|
11492
|
+
* @param resolved - Resolved `publishExecutionEvents` keyed by job function name
|
|
11493
|
+
* @returns Job function names needing re-registration
|
|
11494
|
+
*/
|
|
11495
|
+
function collectStaleJobFunctionNames(existing, resolved) {
|
|
11496
|
+
const stale = /* @__PURE__ */ new Set();
|
|
11497
|
+
for (const [jobName, publishEvents] of resolved) {
|
|
11498
|
+
const remote = existing.get(jobName);
|
|
11499
|
+
if (remote && remote.publishExecutionEvents !== publishEvents) stale.add(jobName);
|
|
11500
|
+
}
|
|
11501
|
+
return stale;
|
|
11502
|
+
}
|
|
11299
11503
|
/**
|
|
11300
11504
|
* Plan workflow changes and job functions based on current and desired state.
|
|
11301
11505
|
* @param client - Operator client instance
|
|
@@ -11305,15 +11509,26 @@ function buildWorkflowValidationShape(workspaceId, workflow) {
|
|
|
11305
11509
|
* @param workflows - Parsed workflows
|
|
11306
11510
|
* @param mainJobDeps - Main job dependencies by workflow
|
|
11307
11511
|
* @param unchangedJobFunctions - Job functions already proven unchanged by function registry plan
|
|
11512
|
+
* @param eventPublishing - Executor subscriptions and explicit job flags driving execution event publishing
|
|
11308
11513
|
* @returns Planned workflow changes
|
|
11309
11514
|
*/
|
|
11310
|
-
async function planWorkflow(client, workspaceId, appName, appId, workflows, mainJobDeps, unchangedJobFunctions = /* @__PURE__ */ new Set()) {
|
|
11515
|
+
async function planWorkflow(client, workspaceId, appName, appId, workflows, mainJobDeps, unchangedJobFunctions = /* @__PURE__ */ new Set(), eventPublishing = {}) {
|
|
11311
11516
|
const changeSet = createChangeSet("Workflows");
|
|
11312
11517
|
const conflicts = [];
|
|
11313
11518
|
const unmanaged = [];
|
|
11314
11519
|
const resourceOwners = /* @__PURE__ */ new Set();
|
|
11315
11520
|
const unchangedWorkflowJobNames = /* @__PURE__ */ new Set();
|
|
11316
11521
|
const retainedWorkflowJobNames = /* @__PURE__ */ new Set();
|
|
11522
|
+
const executionSubscribers = eventPublishing.execution ?? NO_EVENT_SUBSCRIBERS;
|
|
11523
|
+
const existingJobFunctions = await fetchExistingJobFunctions(client, workspaceId);
|
|
11524
|
+
const jobFunctionPublishEvents = resolveJobPublishEvents({
|
|
11525
|
+
workflows,
|
|
11526
|
+
mainJobDeps,
|
|
11527
|
+
subscribers: eventPublishing.jobExecution ?? NO_EVENT_SUBSCRIBERS,
|
|
11528
|
+
explicit: eventPublishing.jobPublishEvents ?? /* @__PURE__ */ new Map(),
|
|
11529
|
+
existing: existingJobFunctions
|
|
11530
|
+
});
|
|
11531
|
+
const staleJobFunctionNames = collectStaleJobFunctionNames(existingJobFunctions, jobFunctionPublishEvents);
|
|
11317
11532
|
const existingWorkflows = await fetchExistingResourcesWithLabels({
|
|
11318
11533
|
client,
|
|
11319
11534
|
fetchPage: async (pageToken, pageSize) => {
|
|
@@ -11337,6 +11552,15 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
|
|
|
11337
11552
|
const usedJobNames = mainJobDeps[workflow.mainJob.name];
|
|
11338
11553
|
if (!usedJobNames) throw new Error(`Job "${workflow.mainJob.name}" (mainJob of workflow "${workflow.name}") was not found.\n\nPossible causes:\n - The job is not exported as a named export\n - The file containing the job is not included in workflow.files glob pattern\n\nSolution:\n export const ${workflow.mainJob.name} = createWorkflowJob({ name: "${workflow.mainJob.name}", ... })`);
|
|
11339
11554
|
usedJobNames.forEach((jobName) => retainedWorkflowJobNames.add(jobName));
|
|
11555
|
+
const desiredWorkflow = {
|
|
11556
|
+
...workflow,
|
|
11557
|
+
publishEvents: resolvePublishEvents({
|
|
11558
|
+
explicit: workflow.publishEvents,
|
|
11559
|
+
subscribed: isSubscribed(executionSubscribers, workflow.name),
|
|
11560
|
+
remote: existing?.resource.publishExecutionEvents,
|
|
11561
|
+
conflictError: `Workflow "${workflow.name}" has "publishEvents: false", but executors with a workflowExecution trigger subscribe to it. Either remove "publishEvents: false" or remove the matching executor triggers.`
|
|
11562
|
+
})
|
|
11563
|
+
};
|
|
11340
11564
|
if (existing) {
|
|
11341
11565
|
if (trackDesiredResourceOwnership({
|
|
11342
11566
|
labels: existing.allLabels,
|
|
@@ -11347,13 +11571,19 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
|
|
|
11347
11571
|
resourceName: workflow.name,
|
|
11348
11572
|
conflicts,
|
|
11349
11573
|
unmanaged
|
|
11350
|
-
}) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && canTreatWorkflowAsUnchanged(
|
|
11574
|
+
}) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && canTreatWorkflowAsUnchanged({
|
|
11575
|
+
existing: existing.resource,
|
|
11576
|
+
workflow: desiredWorkflow,
|
|
11577
|
+
usedJobNames,
|
|
11578
|
+
unchangedJobFunctions,
|
|
11579
|
+
staleJobFunctionNames
|
|
11580
|
+
})) {
|
|
11351
11581
|
changeSet.unchanged.push({ name: workflow.name });
|
|
11352
11582
|
for (const jobName of usedJobNames) unchangedWorkflowJobNames.add(jobName);
|
|
11353
11583
|
} else changeSet.updates.push({
|
|
11354
11584
|
name: workflow.name,
|
|
11355
11585
|
workspaceId,
|
|
11356
|
-
workflow,
|
|
11586
|
+
workflow: desiredWorkflow,
|
|
11357
11587
|
usedJobNames,
|
|
11358
11588
|
metaRequest
|
|
11359
11589
|
});
|
|
@@ -11361,7 +11591,7 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
|
|
|
11361
11591
|
} else changeSet.creates.push({
|
|
11362
11592
|
name: workflow.name,
|
|
11363
11593
|
workspaceId,
|
|
11364
|
-
workflow,
|
|
11594
|
+
workflow: desiredWorkflow,
|
|
11365
11595
|
usedJobNames,
|
|
11366
11596
|
metaRequest
|
|
11367
11597
|
});
|
|
@@ -11391,6 +11621,7 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
|
|
|
11391
11621
|
workspaceId,
|
|
11392
11622
|
appName,
|
|
11393
11623
|
appId,
|
|
11624
|
+
existingJobFunctionNames: [...existingJobFunctions.keys()],
|
|
11394
11625
|
retainedWorkflowJobNames
|
|
11395
11626
|
});
|
|
11396
11627
|
const deletableJobNames = new Set(jobFunctionDeletes.map((del) => del.jobFunctionName));
|
|
@@ -11406,20 +11637,24 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
|
|
|
11406
11637
|
appName,
|
|
11407
11638
|
appId,
|
|
11408
11639
|
unchangedWorkflowJobNames,
|
|
11409
|
-
jobFunctionDeletes
|
|
11640
|
+
jobFunctionDeletes,
|
|
11641
|
+
jobFunctionPublishEvents
|
|
11410
11642
|
};
|
|
11411
11643
|
}
|
|
11412
|
-
async function
|
|
11413
|
-
const
|
|
11414
|
-
const existingJobFunctions = await fetchAll(async (pageToken, maxPageSize) => {
|
|
11644
|
+
async function fetchExistingJobFunctions(client, workspaceId) {
|
|
11645
|
+
const jobFunctions = await fetchAll(async (pageToken, maxPageSize) => {
|
|
11415
11646
|
const response = await client.listWorkflowJobFunctions({
|
|
11416
11647
|
workspaceId,
|
|
11417
11648
|
pageToken,
|
|
11418
11649
|
pageSize: maxPageSize
|
|
11419
11650
|
});
|
|
11420
|
-
return [response.jobFunctions
|
|
11651
|
+
return [response.jobFunctions, response.nextPageToken];
|
|
11421
11652
|
});
|
|
11422
|
-
|
|
11653
|
+
return new Map(jobFunctions.map((jobFunction) => [jobFunction.name, jobFunction]));
|
|
11654
|
+
}
|
|
11655
|
+
async function planWorkflowJobFunctionDeletes(params) {
|
|
11656
|
+
const { client, workspaceId, appName, appId, existingJobFunctionNames, retainedWorkflowJobNames } = params;
|
|
11657
|
+
const candidates = existingJobFunctionNames.filter((jobName) => !retainedWorkflowJobNames.has(jobName));
|
|
11423
11658
|
return (await Promise.all(candidates.map(async (jobFunctionName) => {
|
|
11424
11659
|
const { metadata } = await client.getMetadata({ trn: resourceTrn(workspaceId, "workflow_job_function", jobFunctionName) });
|
|
11425
11660
|
return isOwnedByApp(metadata?.labels, appName, appId) ? {
|
|
@@ -11437,12 +11672,14 @@ async function planWorkflowJobFunctionDeletes(params) {
|
|
|
11437
11672
|
function formatWorkflowChangeEntries(changeSet, workflowJobFunctionChanges) {
|
|
11438
11673
|
return formatChangeEntriesWithFunctionRegistry("workflow", changeSet, workflowJobFunctionChanges, (item) => "usedJobNames" in item ? item.usedJobNames.map((jobName) => workflowJobFunctionName(jobName)) : []);
|
|
11439
11674
|
}
|
|
11440
|
-
function canTreatWorkflowAsUnchanged(
|
|
11675
|
+
function canTreatWorkflowAsUnchanged(params) {
|
|
11676
|
+
const { existing, workflow, usedJobNames, unchangedJobFunctions, staleJobFunctionNames } = params;
|
|
11441
11677
|
if (!usedJobNames.every((jobName) => unchangedJobFunctions.has(jobName))) return false;
|
|
11678
|
+
if (usedJobNames.some((jobName) => staleJobFunctionNames.has(jobName))) return false;
|
|
11442
11679
|
return areWorkflowsEqual(existing, workflow, usedJobNames);
|
|
11443
11680
|
}
|
|
11444
11681
|
function areWorkflowsEqual(existing, workflow, usedJobNames) {
|
|
11445
|
-
return existing.mainJobFunctionName === workflow.mainJob.name && areNormalizedEqual(normalizeComparableExistingWorkflowRetryPolicy(existing.retryPolicy), normalizeComparableWorkflowRetryPolicy(workflow.retryPolicy)) && areNormalizedEqual(normalizeComparableConcurrencyPolicy(existing.concurrencyPolicy), normalizeComparableConcurrencyPolicy(workflow.concurrencyPolicy)) && areNormalizedEqual(normalizeComparableWorkflowJobNames(existing.jobFunctions), normalizeComparableWorkflowJobNames(usedJobNames));
|
|
11682
|
+
return existing.mainJobFunctionName === workflow.mainJob.name && (existing.publishExecutionEvents ?? false) === (workflow.publishEvents ?? false) && areNormalizedEqual(normalizeComparableExistingWorkflowRetryPolicy(existing.retryPolicy), normalizeComparableWorkflowRetryPolicy(workflow.retryPolicy)) && areNormalizedEqual(normalizeComparableConcurrencyPolicy(existing.concurrencyPolicy), normalizeComparableConcurrencyPolicy(workflow.concurrencyPolicy)) && areNormalizedEqual(normalizeComparableWorkflowJobNames(existing.jobFunctions), normalizeComparableWorkflowJobNames(usedJobNames));
|
|
11446
11683
|
}
|
|
11447
11684
|
function normalizeComparableExistingWorkflowRetryPolicy(policy) {
|
|
11448
11685
|
if (!policy) return;
|
|
@@ -11699,6 +11936,9 @@ async function applyDeploymentPlans(client, workspaceId, deployments) {
|
|
|
11699
11936
|
const forEachDeployment = async (apply) => {
|
|
11700
11937
|
for (const deployment of deployments) await apply(deployment);
|
|
11701
11938
|
};
|
|
11939
|
+
await withSpan("apply.preflight", async () => {
|
|
11940
|
+
await forEachDeployment((d) => preflightTailorDB(client, d.tailorDB));
|
|
11941
|
+
});
|
|
11702
11942
|
await withSpan("apply.createUpdateServices", async () => {
|
|
11703
11943
|
await forEachDeployment((d) => applySecretManager(client, d.secretManager, "create-update", d.application));
|
|
11704
11944
|
await forEachDeployment((d) => applyFunctionRegistry(client, workspaceId, d.functionRegistry, "create-update"));
|
|
@@ -13137,6 +13377,39 @@ function collectExecutorUsedResolvers(owner, targets) {
|
|
|
13137
13377
|
}
|
|
13138
13378
|
return usedResolvers;
|
|
13139
13379
|
}
|
|
13380
|
+
/**
|
|
13381
|
+
* Resolve which workflows this target's executors subscribe to, per event
|
|
13382
|
+
* granularity level.
|
|
13383
|
+
*
|
|
13384
|
+
* Scoped to the owning target: unlike TailorDB, Auth and IdP, a workflow has no
|
|
13385
|
+
* `external` declaration, so no supported configuration shares a workflow and a
|
|
13386
|
+
* subscribing executor across configs.
|
|
13387
|
+
* @param target - Deployment target being planned
|
|
13388
|
+
* @returns Subscribers keyed by event granularity level
|
|
13389
|
+
*/
|
|
13390
|
+
function collectWorkflowEventSubscribers(target) {
|
|
13391
|
+
const execution = { workflowNames: /* @__PURE__ */ new Set() };
|
|
13392
|
+
const jobExecution = { workflowNames: /* @__PURE__ */ new Set() };
|
|
13393
|
+
for (const executor of Object.values(target.application.executorService?.executors ?? {})) {
|
|
13394
|
+
const { trigger } = executor;
|
|
13395
|
+
if (trigger.kind !== "workflowExecution" && trigger.kind !== "workflowJobExecution") continue;
|
|
13396
|
+
(trigger.kind === "workflowExecution" ? execution : jobExecution).workflowNames.add(trigger.workflowName);
|
|
13397
|
+
}
|
|
13398
|
+
return {
|
|
13399
|
+
execution,
|
|
13400
|
+
jobExecution
|
|
13401
|
+
};
|
|
13402
|
+
}
|
|
13403
|
+
/**
|
|
13404
|
+
* Collect explicit `publishEvents` values declared on this target's workflow jobs.
|
|
13405
|
+
* @param target - Deployment target being planned
|
|
13406
|
+
* @returns Explicit flags keyed by job name
|
|
13407
|
+
*/
|
|
13408
|
+
function collectWorkflowJobPublishEvents(target) {
|
|
13409
|
+
const jobPublishEvents = /* @__PURE__ */ new Map();
|
|
13410
|
+
for (const job of target.application.workflowService?.jobs ?? []) if (job.publishEvents !== void 0) jobPublishEvents.set(job.name, job.publishEvents);
|
|
13411
|
+
return jobPublishEvents;
|
|
13412
|
+
}
|
|
13140
13413
|
function collectExpectedLocalStaticWebsiteNames(targets) {
|
|
13141
13414
|
const websiteNames = /* @__PURE__ */ new Set();
|
|
13142
13415
|
for (const target of targets) for (const website of target.application.staticWebsiteServices) websiteNames.add(website.name);
|
|
@@ -13738,7 +14011,10 @@ async function planDeploymentTarget(params) {
|
|
|
13738
14011
|
withSpan("plan.pipeline", () => planPipeline(ctx)),
|
|
13739
14012
|
withSpan("plan.application", () => planApplication(ctx, httpAdapterBuildResult)),
|
|
13740
14013
|
withSpan("plan.executor", () => planExecutor(ctx)),
|
|
13741
|
-
withSpan("plan.workflow", () => planWorkflow(client, workspaceId, application.name, application.id, workflowService?.workflows ?? {}, workflowBuildResult?.mainJobDeps ?? {}, unchangedWorkflowJobs
|
|
14014
|
+
withSpan("plan.workflow", () => planWorkflow(client, workspaceId, application.name, application.id, workflowService?.workflows ?? {}, workflowBuildResult?.mainJobDeps ?? {}, unchangedWorkflowJobs, {
|
|
14015
|
+
...collectWorkflowEventSubscribers(target),
|
|
14016
|
+
jobPublishEvents: collectWorkflowJobPublishEvents(target)
|
|
14017
|
+
})),
|
|
13742
14018
|
withSpan("plan.workflowExecutionPolicy", () => planWorkflowJobFunctionExecutionPolicy(client, workspaceId, application.name, application.id, config.workflow?.executionPolicies ?? {})),
|
|
13743
14019
|
withSpan("plan.secretManager", () => planSecretManager(ctx))
|
|
13744
14020
|
]);
|
|
@@ -14553,6 +14829,12 @@ function formatEventTriggerConfig(config) {
|
|
|
14553
14829
|
eventType: config.eventType,
|
|
14554
14830
|
condition: config.condition?.expr || ""
|
|
14555
14831
|
};
|
|
14832
|
+
if (typedConfig.case === "workflow") return {
|
|
14833
|
+
kind: typedConfig.case,
|
|
14834
|
+
eventTypes: typedConfig.value.eventTypes,
|
|
14835
|
+
condition: typedConfig.value.condition?.expr || "",
|
|
14836
|
+
...typedConfig.value.workflowName && { workflowName: typedConfig.value.workflowName }
|
|
14837
|
+
};
|
|
14556
14838
|
const base = {
|
|
14557
14839
|
kind: typedConfig.case,
|
|
14558
14840
|
eventTypes: typedConfig.value.eventTypes,
|
|
@@ -18860,8 +19142,13 @@ async function generateDiffFiles(diff, migrationsDir, migrationNumber, previousS
|
|
|
18860
19142
|
function generateMigrationScript(diff) {
|
|
18861
19143
|
const updates = [];
|
|
18862
19144
|
for (const change of diff.changes) {
|
|
18863
|
-
const
|
|
18864
|
-
|
|
19145
|
+
const decimalScaleScript = generateDecimalScaleChangeScript(change);
|
|
19146
|
+
updates.push(...generateChangeScripts(change, decimalScaleScript !== null));
|
|
19147
|
+
if (decimalScaleScript) {
|
|
19148
|
+
updates.push(decimalScaleScript);
|
|
19149
|
+
const uniqueConstraintScript = generateUniqueConstraintScript(change);
|
|
19150
|
+
if (uniqueConstraintScript) updates.push(uniqueConstraintScript);
|
|
19151
|
+
}
|
|
18865
19152
|
}
|
|
18866
19153
|
if (updates.length === 0) updates.push(` // No data migration needed for this schema change
|
|
18867
19154
|
// Add custom data transformations if required`);
|
|
@@ -18886,18 +19173,19 @@ ${updates.join("\n\n")}
|
|
|
18886
19173
|
`;
|
|
18887
19174
|
}
|
|
18888
19175
|
/**
|
|
18889
|
-
* Generate
|
|
19176
|
+
* Generate scripts for a single change
|
|
18890
19177
|
* @param {DiffChange} change - Diff change to generate script for
|
|
18891
|
-
* @
|
|
19178
|
+
* @param {boolean} deferUniqueConstraint - Generate the unique check after decimal re-serialization
|
|
19179
|
+
* @returns {string[]} Script contents, or an empty array if no script is needed
|
|
18892
19180
|
*/
|
|
18893
|
-
function
|
|
19181
|
+
function generateChangeScripts(change, deferUniqueConstraint = false) {
|
|
18894
19182
|
if (change.kind === "index_added" || change.kind === "index_modified") {
|
|
18895
19183
|
const before = change.kind === "index_modified" ? change.before : void 0;
|
|
18896
|
-
if (!isBreakingIndexChange(change.typeName, change.indexName, before, change.after)) return
|
|
19184
|
+
if (!isBreakingIndexChange(change.typeName, change.indexName, before, change.after)) return [];
|
|
18897
19185
|
const fields = change.after.fields;
|
|
18898
19186
|
const fieldList = fields.map((f) => `"${f}"`).join(", ");
|
|
18899
19187
|
const whereClauses = fields.map((f) => `.where("${f}", "=", dup.${f})`).join("\n ");
|
|
18900
|
-
return ` // Resolve duplicate (${fields.join(", ")}) combinations before unique index "${change.indexName}" is enforced
|
|
19188
|
+
return [` // Resolve duplicate (${fields.join(", ")}) combinations before unique index "${change.indexName}" is enforced
|
|
18901
19189
|
{
|
|
18902
19190
|
const duplicates = await trx
|
|
18903
19191
|
.selectFrom("${change.typeName}")
|
|
@@ -18920,81 +19208,135 @@ function generateChangeScript(change) {
|
|
|
18920
19208
|
.execute();
|
|
18921
19209
|
}
|
|
18922
19210
|
}
|
|
18923
|
-
}
|
|
19211
|
+
}`];
|
|
18924
19212
|
}
|
|
18925
19213
|
if (change.kind === "field_added") {
|
|
18926
|
-
if (change.after.required) return ` // Populate ${change.fieldName} for existing ${change.typeName} records
|
|
19214
|
+
if (change.after.required) return [` // Populate ${change.fieldName} for existing ${change.typeName} records
|
|
18927
19215
|
await trx
|
|
18928
19216
|
.updateTable("${change.typeName}")
|
|
18929
19217
|
.set({
|
|
18930
19218
|
${change.fieldName}: null, // TODO: Set appropriate default value
|
|
18931
19219
|
})
|
|
18932
|
-
.execute()
|
|
18933
|
-
return
|
|
19220
|
+
.execute();`];
|
|
19221
|
+
return [];
|
|
18934
19222
|
}
|
|
18935
|
-
if (change.kind !== "field_modified") return
|
|
19223
|
+
if (change.kind !== "field_modified") return [];
|
|
18936
19224
|
const { before, after } = change;
|
|
18937
|
-
|
|
19225
|
+
const scripts = [];
|
|
19226
|
+
if (!before.required && after.required) scripts.push(` // Set ${change.fieldName} for ${change.typeName} records where it is null
|
|
18938
19227
|
await trx
|
|
18939
19228
|
.updateTable("${change.typeName}")
|
|
18940
19229
|
.set({
|
|
18941
19230
|
${change.fieldName}: null, // TODO: Set appropriate default value
|
|
18942
19231
|
})
|
|
18943
19232
|
.where("${change.fieldName}", "is", null)
|
|
18944
|
-
.execute()
|
|
18945
|
-
if (!
|
|
18946
|
-
|
|
18947
|
-
|
|
18948
|
-
|
|
18949
|
-
.groupBy("${change.fieldName}")
|
|
18950
|
-
.having((eb) => eb.fn.count("id"), ">", 1)
|
|
18951
|
-
.execute();
|
|
18952
|
-
for (const dup of duplicates) {
|
|
18953
|
-
// Keep first record, add suffix to others
|
|
18954
|
-
const records = await trx
|
|
18955
|
-
.selectFrom("${change.typeName}")
|
|
18956
|
-
.select(["id", "${change.fieldName}"])
|
|
18957
|
-
.where("${change.fieldName}", "=", dup.${change.fieldName})
|
|
18958
|
-
.execute();
|
|
18959
|
-
for (let i = 1; i < records.length; i++) {
|
|
18960
|
-
await trx
|
|
18961
|
-
.updateTable("${change.typeName}")
|
|
18962
|
-
.set({ ${change.fieldName}: \`\${records[i].${change.fieldName}}_\${i}\` }) // TODO: Set appropriate unique value
|
|
18963
|
-
.where("id", "=", records[i].id)
|
|
18964
|
-
.execute();
|
|
18965
|
-
}
|
|
18966
|
-
}`;
|
|
19233
|
+
.execute();`);
|
|
19234
|
+
if (!deferUniqueConstraint) {
|
|
19235
|
+
const uniqueConstraintScript = generateUniqueConstraintScript(change);
|
|
19236
|
+
if (uniqueConstraintScript) scripts.push(uniqueConstraintScript);
|
|
19237
|
+
}
|
|
18967
19238
|
if (before.type === "enum" && after.type === "enum") {
|
|
18968
19239
|
const beforeValues = (before.allowedValues ?? []).map((v) => v.value);
|
|
18969
19240
|
const afterValues = (after.allowedValues ?? []).map((v) => v.value);
|
|
18970
19241
|
const removedValues = beforeValues.filter((v) => !afterValues.includes(v));
|
|
18971
19242
|
if (removedValues.length > 0) {
|
|
18972
19243
|
const defaultValue = afterValues[0] ?? "NEW_VALUE";
|
|
18973
|
-
|
|
19244
|
+
scripts.push(` // Migrate records with removed enum values: ${removedValues.join(", ")}
|
|
18974
19245
|
await trx
|
|
18975
19246
|
.updateTable("${change.typeName}")
|
|
18976
19247
|
.set({ ${change.fieldName}: "${defaultValue}" }) // TODO: Set appropriate value
|
|
18977
19248
|
.where("${change.fieldName}", "in", [${removedValues.map((v) => `"${v}"`).join(", ")}])
|
|
18978
|
-
.execute()
|
|
19249
|
+
.execute();`);
|
|
18979
19250
|
}
|
|
18980
19251
|
}
|
|
18981
|
-
if (before.foreignKeyType && after.foreignKeyType && before.foreignKeyType !== after.foreignKeyType)
|
|
19252
|
+
if (before.foreignKeyType && after.foreignKeyType && before.foreignKeyType !== after.foreignKeyType) scripts.push(` // Migrate ${change.fieldName} references from ${before.foreignKeyType} to ${after.foreignKeyType}
|
|
18982
19253
|
// Find records that don't have a valid reference in the new target table
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
19254
|
+
{
|
|
19255
|
+
const orphanedRecords = await trx
|
|
19256
|
+
.selectFrom("${change.typeName}")
|
|
19257
|
+
.leftJoin("${after.foreignKeyType}", "${change.typeName}.${change.fieldName}", "${after.foreignKeyType}.id")
|
|
19258
|
+
.select(["${change.typeName}.id", "${change.typeName}.${change.fieldName}"])
|
|
19259
|
+
.where("${after.foreignKeyType}.id", "is", null)
|
|
19260
|
+
.where("${change.typeName}.${change.fieldName}", "is not", null)
|
|
19261
|
+
.execute();
|
|
19262
|
+
for (const record of orphanedRecords) {
|
|
19263
|
+
await trx
|
|
19264
|
+
.updateTable("${change.typeName}")
|
|
19265
|
+
.set({ ${change.fieldName}: null }) // TODO: Set appropriate new reference
|
|
19266
|
+
.where("id", "=", record.id)
|
|
19267
|
+
.execute();
|
|
19268
|
+
}
|
|
19269
|
+
}`);
|
|
19270
|
+
return scripts;
|
|
19271
|
+
}
|
|
19272
|
+
function generateUniqueConstraintScript(change) {
|
|
19273
|
+
if (change.kind !== "field_modified") return null;
|
|
19274
|
+
const { before, after } = change;
|
|
19275
|
+
if ((before.unique ?? false) || !(after.unique ?? false)) return null;
|
|
19276
|
+
return ` // Ensure ${change.fieldName} values are unique before adding constraint
|
|
19277
|
+
{
|
|
19278
|
+
const duplicates = await trx
|
|
19279
|
+
.selectFrom("${change.typeName}")
|
|
19280
|
+
.select(["${change.fieldName}"])
|
|
19281
|
+
.groupBy("${change.fieldName}")
|
|
19282
|
+
.having((eb) => eb.fn.count("id"), ">", 1)
|
|
18995
19283
|
.execute();
|
|
19284
|
+
for (const dup of duplicates) {
|
|
19285
|
+
// Keep first record, add suffix to others
|
|
19286
|
+
const records = await trx
|
|
19287
|
+
.selectFrom("${change.typeName}")
|
|
19288
|
+
.select(["id", "${change.fieldName}"])
|
|
19289
|
+
.where("${change.fieldName}", "=", dup.${change.fieldName})
|
|
19290
|
+
.execute();
|
|
19291
|
+
for (let i = 1; i < records.length; i++) {
|
|
19292
|
+
await trx
|
|
19293
|
+
.updateTable("${change.typeName}")
|
|
19294
|
+
.set({ ${change.fieldName}: \`\${records[i].${change.fieldName}}_\${i}\` }) // TODO: Set appropriate unique value
|
|
19295
|
+
.where("id", "=", records[i].id)
|
|
19296
|
+
.execute();
|
|
19297
|
+
}
|
|
19298
|
+
}
|
|
19299
|
+
}`;
|
|
19300
|
+
}
|
|
19301
|
+
function generateDecimalScaleChangeScript(change) {
|
|
19302
|
+
if (change.kind !== "field_modified") return null;
|
|
19303
|
+
const { before, after } = change;
|
|
19304
|
+
if (before.type !== "decimal" || after.type !== "decimal" || before.scale === after.scale) return null;
|
|
19305
|
+
const valueExpression = !before.required && after.required ? `row.${change.fieldName}!` : `row.${change.fieldName}`;
|
|
19306
|
+
const beforeScale = before.scale ?? 6;
|
|
19307
|
+
const roundingWarning = (after.scale ?? 6) < beforeScale ? `
|
|
19308
|
+
// Values that exceed the new scale may be rounded half-up, so review the
|
|
19309
|
+
// resulting precision before deploying.` : "";
|
|
19310
|
+
return ` // Re-save existing ${change.typeName} rows so ${change.fieldName} is stored under the new scale.
|
|
19311
|
+
// This is a workaround for a platform-side gap where rows written under the
|
|
19312
|
+
// previous scale could fail on later updates until re-saved. Keep it unless
|
|
19313
|
+
// your platform is confirmed to handle stored values across scale changes.${roundingWarning}
|
|
19314
|
+
{
|
|
19315
|
+
let lastId: string | undefined;
|
|
19316
|
+
while (true) {
|
|
19317
|
+
let query = trx
|
|
19318
|
+
.selectFrom("${change.typeName}")
|
|
19319
|
+
.select(["id", "${change.fieldName}"])
|
|
19320
|
+
.where("${change.fieldName}", "is not", null)
|
|
19321
|
+
.orderBy("id", "asc")
|
|
19322
|
+
.limit(100);
|
|
19323
|
+
if (lastId) {
|
|
19324
|
+
query = query.where("id", ">", lastId);
|
|
19325
|
+
}
|
|
19326
|
+
const rows = await query.execute();
|
|
19327
|
+
if (rows.length === 0) break;
|
|
19328
|
+
|
|
19329
|
+
for (const row of rows) {
|
|
19330
|
+
await trx
|
|
19331
|
+
.updateTable("${change.typeName}")
|
|
19332
|
+
.set({ ${change.fieldName}: ${valueExpression} })
|
|
19333
|
+
.where("id", "=", row.id)
|
|
19334
|
+
.where("${change.fieldName}", "=", ${valueExpression})
|
|
19335
|
+
.execute();
|
|
19336
|
+
}
|
|
19337
|
+
lastId = rows[rows.length - 1]!.id;
|
|
19338
|
+
}
|
|
18996
19339
|
}`;
|
|
18997
|
-
return null;
|
|
18998
19340
|
}
|
|
18999
19341
|
|
|
19000
19342
|
//#endregion
|
|
@@ -19063,7 +19405,7 @@ async function generate(options) {
|
|
|
19063
19405
|
if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
|
|
19064
19406
|
let pluginManager;
|
|
19065
19407
|
if (plugins.length > 0) pluginManager = new PluginManager(plugins);
|
|
19066
|
-
const { defineApplication } = await import("./application-
|
|
19408
|
+
const { defineApplication } = await import("./application-C-zsrNjn.mjs");
|
|
19067
19409
|
const application = defineApplication({
|
|
19068
19410
|
config,
|
|
19069
19411
|
pluginManager
|
|
@@ -20277,8 +20619,13 @@ async function bundleQueryScript(engine, baseDir) {
|
|
|
20277
20619
|
const entryContent = engine === "sql" ? createSqlEntry() : createGqlEntry();
|
|
20278
20620
|
fs$1.writeFileSync(entryPath, entryContent);
|
|
20279
20621
|
const tsconfig = await resolveTSConfigWithFallback(baseDir);
|
|
20280
|
-
|
|
20281
|
-
|
|
20622
|
+
const bundleLog = createBundleLog({ tsconfig });
|
|
20623
|
+
const result = await rolldown.build({
|
|
20624
|
+
plugins: [
|
|
20625
|
+
createGeneratedEntryResolverPlugin(entryPath, baseDir),
|
|
20626
|
+
createTsconfigPathsPlugin(),
|
|
20627
|
+
platformBundleDefinePlugin
|
|
20628
|
+
],
|
|
20282
20629
|
input: entryPath,
|
|
20283
20630
|
write: false,
|
|
20284
20631
|
output: {
|
|
@@ -20296,8 +20643,10 @@ async function bundleQueryScript(engine, baseDir) {
|
|
|
20296
20643
|
annotations: true,
|
|
20297
20644
|
unknownGlobalSideEffects: false
|
|
20298
20645
|
},
|
|
20299
|
-
|
|
20300
|
-
})
|
|
20646
|
+
...bundleLog.options
|
|
20647
|
+
});
|
|
20648
|
+
bundleLog.assertAllResolved();
|
|
20649
|
+
return result.output[0].code;
|
|
20301
20650
|
}
|
|
20302
20651
|
|
|
20303
20652
|
//#endregion
|
|
@@ -21191,5 +21540,5 @@ async function registerTypeScriptRuntime(hookUrl) {
|
|
|
21191
21540
|
}
|
|
21192
21541
|
|
|
21193
21542
|
//#endregion
|
|
21194
|
-
export { listFolders as $,
|
|
21195
|
-
//# sourceMappingURL=register-typescript-runtime-
|
|
21543
|
+
export { listFolders as $, writePlatformConfig as $n, logRemoteDriftGuidance as $t, generate as A, hasChanges as An, startCommand as At, remove as B, deleteUserTokens as Bn, deploy as Bt, waitWorkflowExecution as C, isValidMigrationNumber as Cn, listCommand$8 as Ct, listWorkflows as D, parseMigrationNumberArg as Dn, jobsCommand as Dt, listCommand$2 as E, formatMigrationNumber as En, getExecutorWaitFailureMessage as Et, openInConfiguredEditor as F, generateUserTypes as Fn, getWorkflowExecution as Ft, treeCommand as G, loadConsoleBaseUrl as Gn, createWorkspace$1 as Gt, updateCommand$1 as H, hasAnyUserTokenEntry as Hn, listCommand$9 as Ht, show as I, prompt as In, listWorkflowExecutions as It, getCommand$1 as J, loadWorkspaceId as Jn, ensureConfigId as Jt, listCommand$3 as K, loadMachineUserName as Kn, formatKeyValueTable as Kt, showCommand as L, apiCall as Ln, functionExecutionStatusToString as Lt, generateMigrationScript as M, resourceTrn as Mn, getCommand$5 as Mt, writeDbTypesFile as N, sdkNameLabelKey as Nn, getWorkflow as Nt, truncate as O, formatDiffSummary as On, listExecutorJobs as Ot, getConfiguredEditorCommand as P, PluginManager as Pn, executionsCommand as Pt, listCommand$4 as Q, saveUserTokens as Qn, checkMigrationDiffs as Qt, extractOwnedNamespaces as R, assertWritable as Rn, getCommand$6 as Rt, waitCommand as S, getNextMigrationNumber as Sn, triggerExecutor as St, resumeWorkflow as T, reconstructSnapshotFromMigrations as Tn, getExecutorJob as Tt, updateOrganization as U, hasUserTokenEntry as Un, listWorkspaces as Ut, removeCommand$1 as V, fetchLatestToken as Vn, deployFromCLI as Vt, organizationTree as W, loadAccessToken as Wn, createCommand$1 as Wt, updateCommand$2 as X, readPlatformConfig as Xn, waitForExecution as Xt, getOrganization as Y, platformConfigFromProfile as Yn, executeScript as Yt, updateFolder as Z, resolveUserTokenKey as Zn, bundleMigrationScript as Zt, deleteWorkspace as _, formatSchemaDrifts as _n, getCommand$4 as _t, updateUser as a, compareSnapshotWithRemote as an, isVerbose as ar, createFolder as at, getAppHealth as b, getMigrationFilePath as bn, webhookCommand as bt, listCommand as c, DB_TYPES_FILE_NAME as cn, paginationArgs as cr, getCommand$3 as ct, inviteUser as d, MIGRATE_FILE_NAME as dn, workspaceArgs as dr, tokenCommand as dt, toTailorDBDeployInput as en, defineAppCommand as er, getCommand$2 as et, restoreCommand as f, SCHEMA_FILE_NAME as fn, listCommand$6 as ft, deleteCommand as g, createSnapshotFromLocalTypes as gn, listFunctionRegistries as gt, getWorkspace as h, compareSnapshots as hn, listCommand$7 as ht, updateCommand as i, parseMigrationLabelNumber as in, deploymentArgs as ir, createCommand as it, generateCommand as j, getNamespacesWithMigrations as jn, startWorkflow as jt, truncateCommand as k, formatMigrationDiff as kn, watchExecutorJob as kt, listUsers as l, DIFF_FILE_NAME as ln, resolveMachineUserInputSource as lr, getOAuth2Client as lt, getCommand as m, compareLocalTypesWithSnapshot as mn, generate$1 as mt, query as n, MIGRATION_LABEL_KEY as nn, configArg as nr, deleteCommand$1 as nt, removeCommand as o, generateAllTypeManifestsFromSnapshot as on, multiConfigArg as or, listCommand$5 as ot, restoreWorkspace as p, assertValidMigrationFiles as pn, listMachineUsers as pt, listOrganizations as q, loadStoredUserTokens as qn, workspaceNameSchema as qt, queryCommand as r, handleOptionalToRequiredError as rn, confirmationArgs as rr, deleteFolder as rt, removeUser as s, protoGqlPermission as sn, pagedLogArgs as sr, listOAuth2Clients as st, registerTypeScriptRuntime as t, verifyRemoteSchema as tn, commonArgs as tr, getFolder as tt, inviteCommand as u, INITIAL_SCHEMA_NUMBER as un, toPageDirection as ur, getMachineUserToken as ut, listApps as v, getLatestMigrationNumber as vn, getFunctionRegistry as vt, resumeCommand as w, loadDiff as wn, listExecutors as wt, healthCommand as x, getMigrationFiles as xn, triggerCommand as xt, listCommand$1 as y, getMigrationDirPath as yn, listWebhookExecutors as yt, logBetaWarning as z, loadConfig as zn, getExecutor as zt };
|
|
21544
|
+
//# sourceMappingURL=register-typescript-runtime-nG-n9lPw.mjs.map
|