@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.
Files changed (70) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/application-C-zsrNjn.mjs +3 -0
  3. package/dist/{application-Cp0FxIm2.mjs → application-m5tYtz0-.mjs} +246 -68
  4. package/dist/application-m5tYtz0-.mjs.map +1 -0
  5. package/dist/cli/commands/deploy/tailordb/index.d.mts +2 -0
  6. package/dist/cli/commands/generate/seed/bundler.d.mts +2 -1
  7. package/dist/cli/commands/generate/service.d.mts +1 -1
  8. package/dist/cli/commands/generate/types.d.mts +1 -1
  9. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +11 -1
  10. package/dist/cli/commands/tailordb/migrate/schema-checks.d.mts +5 -0
  11. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
  12. package/dist/cli/index.mjs +291 -29
  13. package/dist/cli/index.mjs.map +1 -1
  14. package/dist/cli/lib.d.mts +1 -1
  15. package/dist/cli/lib.mjs +92 -36
  16. package/dist/cli/lib.mjs.map +1 -1
  17. package/dist/cli/shared/client.d.mts +28 -3
  18. package/dist/cli/skills.d.mts +1 -1
  19. package/dist/completion/zsh-worker.zsh +85 -22
  20. package/dist/configure/index.d.mts +2 -2
  21. package/dist/configure/index.mjs +170 -2
  22. package/dist/configure/index.mjs.map +1 -1
  23. package/dist/configure/services/executor/index.d.mts +2 -2
  24. package/dist/configure/services/executor/trigger/event.d.mts +245 -2
  25. package/dist/configure/services/executor/trigger/index.d.mts +3 -3
  26. package/dist/configure/services/index.d.mts +2 -2
  27. package/dist/configure/services/tailordb/index.d.mts +0 -1
  28. package/dist/configure/services/workflow/job.d.mts +9 -0
  29. package/dist/configure/services/workflow/workflow.d.mts +10 -0
  30. package/dist/node-builtins-CmaL2Cbq.mjs +36 -0
  31. package/dist/node-builtins-CmaL2Cbq.mjs.map +1 -0
  32. package/dist/plugin/builtin/seed/index.mjs +1 -1
  33. package/dist/{register-typescript-runtime-CCHyKeXO.mjs → register-typescript-runtime-nG-n9lPw.mjs} +752 -403
  34. package/dist/register-typescript-runtime-nG-n9lPw.mjs.map +1 -0
  35. package/dist/{seed-DFFigL8V.mjs → seed-6eTFj-3Q.mjs} +158 -41
  36. package/dist/seed-6eTFj-3Q.mjs.map +1 -0
  37. package/dist/{service-B0MaodSg.mjs → service-CPJWhTLn.mjs} +29 -2
  38. package/dist/service-CPJWhTLn.mjs.map +1 -0
  39. package/dist/service-Cigg_U-v.mjs +3 -0
  40. package/dist/{service_pb-BwZRiNug.mjs → service_pb-D5--My_M.mjs} +5 -5
  41. package/dist/service_pb-D5--My_M.mjs.map +1 -0
  42. package/dist/{service_pb-wRkxUta6.mjs → service_pb-i8CmnQP4.mjs} +1 -1
  43. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +106 -1
  44. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +24 -1
  45. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +49 -1
  46. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +89 -6
  47. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +26 -1
  48. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +101 -1
  49. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +22 -1
  50. package/dist/types/executor.generated.d.mts +23 -3
  51. package/dist/vitest/index.mjs +3 -35
  52. package/dist/vitest/index.mjs.map +1 -1
  53. package/dist/{workspace_resource_pb-UGK1SSn_.mjs → workspace_resource_pb-DXnO2AT-.mjs} +7 -7
  54. package/dist/workspace_resource_pb-DXnO2AT-.mjs.map +1 -0
  55. package/docs/cli/tailordb.md +36 -12
  56. package/docs/cli-reference.md +16 -15
  57. package/docs/generator/builtin.md +7 -0
  58. package/docs/services/executor.md +83 -3
  59. package/docs/services/idp.md +3 -3
  60. package/docs/services/tailordb-migration.md +24 -4
  61. package/docs/services/workflow.md +26 -0
  62. package/package.json +17 -18
  63. package/dist/application-CP7JKG9R.mjs +0 -3
  64. package/dist/application-Cp0FxIm2.mjs.map +0 -1
  65. package/dist/register-typescript-runtime-CCHyKeXO.mjs.map +0 -1
  66. package/dist/seed-DFFigL8V.mjs.map +0 -1
  67. package/dist/service-B0MaodSg.mjs.map +0 -1
  68. package/dist/service-KnAiVofD.mjs +0 -3
  69. package/dist/service_pb-BwZRiNug.mjs.map +0 -1
  70. package/dist/workspace_resource_pb-UGK1SSn_.mjs.map +0 -1
@@ -4,5 +4,7 @@ import "../../../../tailor-proto/src/tailor/v1/tailordb_pb.mjs";
4
4
  import "../../../../tailor-proto/src/tailor/v1/metadata_pb.mjs";
5
5
  import "../../../shared/client.mjs";
6
6
  import "../types.mjs";
7
+ import "../../tailordb/migrate/config.mjs";
7
8
  import "../../tailordb/migrate/snapshot.mjs";
9
+ import "../../tailordb/migrate/schema-checks.mjs";
8
10
  import "@bufbuild/protobuf";
@@ -19,8 +19,9 @@ type SeedBundleResult = {
19
19
  * 4. Exports as main() for TestExecScript
20
20
  * @param namespace - TailorDB namespace
21
21
  * @param typeNames - List of type names to include in the seed
22
+ * @param baseDir - Directory whose dependencies and tsconfig the generated entry uses
22
23
  * @returns Bundled seed script result
23
24
  */
24
- declare function bundleSeedScript(namespace: string, typeNames: string[]): Promise<SeedBundleResult>;
25
+ declare function bundleSeedScript(namespace: string, typeNames: string[], baseDir?: string): Promise<SeedBundleResult>;
25
26
  //#endregion
26
27
  export { SeedBundleResult, bundleSeedScript };
@@ -3,7 +3,7 @@ import "../../../plugin/types.mjs";
3
3
  import "../../../plugin/manager.mjs";
4
4
  import "../../shared/config-loader.mjs";
5
5
  import "../../services/application.mjs";
6
- import { CodeGenerator } from "./types.mjs";
6
+ import "./types.mjs";
7
7
  import { GenerateOptions } from "./options.mjs";
8
8
  //#region src/cli/commands/generate/service.d.ts
9
9
  /**
@@ -1,6 +1,6 @@
1
1
  import { PluginAttachment } from "../../../configure/services/tailordb/types.mjs";
2
2
  import { IdProvider, OAuth2Client } from "../../../types/auth.generated.mjs";
3
- import { PluginGeneratedTypeSource, TailorDBType, TypeSourceInfoEntry, UserDefinedTypeSource } from "../../../parser/service/tailordb/types.mjs";
3
+ import { TailorDBType, TypeSourceInfoEntry } from "../../../parser/service/tailordb/types.mjs";
4
4
  import { Executor } from "../../../types/executor.generated.mjs";
5
5
  import { Resolver } from "../../../types/resolver.generated.mjs";
6
6
  import "../../../plugin/types.mjs";
@@ -174,6 +174,16 @@ interface MigrationDiff {
174
174
  warnings: WarningChangeInfo[];
175
175
  /** Whether a migration script is required to handle data migration */
176
176
  requiresMigrationScript: boolean;
177
+ /** Explicit acknowledgment that this migration needs no script despite breaking changes */
178
+ scriptSkipped?: ScriptSkippedInfo;
179
+ }
180
+ /**
181
+ * Acknowledgment that a migration requiring a script intentionally has none.
182
+ * Recorded by `tailordb migration script <n> --no-script --reason "..."`.
183
+ */
184
+ interface ScriptSkippedInfo {
185
+ reason: string;
186
+ acknowledgedAt: string;
177
187
  }
178
188
  /**
179
189
  * Breaking change information in migration diff
@@ -219,4 +229,4 @@ declare function formatMigrationDiff(diff: MigrationDiff): string;
219
229
  */
220
230
  declare function formatDiffSummary(diff: MigrationDiff): string;
221
231
  //#endregion
222
- export { BreakingChangeInfo, DiffChange, FieldAddedChange, FieldModifiedChange, FieldRemovedChange, FileAddedChange, FileModifiedChange, FileRemovedChange, IndexAddedChange, IndexModifiedChange, IndexRemovedChange, MigrationDiff, PermissionModifiedChange, RelationshipAddedChange, RelationshipModifiedChange, RelationshipRemovedChange, SnapshotPermissionState, SnapshotTypeSettingsState, TypeAddedChange, TypeModifiedChange, TypeRemovedChange, TypeSettingsModifiedChange, TypeSettingsPatch, WarningChangeInfo, formatDiffSummary, formatMigrationDiff, hasChanges };
232
+ export { BreakingChangeInfo, DiffChange, FieldAddedChange, FieldModifiedChange, FieldRemovedChange, FileAddedChange, FileModifiedChange, FileRemovedChange, IndexAddedChange, IndexModifiedChange, IndexRemovedChange, MigrationDiff, PermissionModifiedChange, RelationshipAddedChange, RelationshipModifiedChange, RelationshipRemovedChange, ScriptSkippedInfo, SnapshotPermissionState, SnapshotTypeSettingsState, TypeAddedChange, TypeModifiedChange, TypeRemovedChange, TypeSettingsModifiedChange, TypeSettingsPatch, WarningChangeInfo, formatDiffSummary, formatMigrationDiff, hasChanges };
@@ -0,0 +1,5 @@
1
+ import "../../../services/tailordb/service.mjs";
2
+ import "../../../shared/config-loader.mjs";
3
+ import "../../../shared/client.mjs";
4
+ import "./config.mjs";
5
+ import "./snapshot.mjs";
@@ -1,6 +1,6 @@
1
1
  import { TailorDBType } from "../../../../parser/service/tailordb/types.mjs";
2
2
  import "../../../../tailor-proto/src/tailor/v1/tailordb_resource_pb.mjs";
3
- import { NormalizedSchemaSnapshot, SchemaSnapshot, SnapshotActionPermission, SnapshotEnumValue, SnapshotFieldConfig, SnapshotFieldRefOperand, SnapshotGqlAction, SnapshotGqlPermission, SnapshotGqlPermissionPolicy, SnapshotHook, SnapshotIndexConfig, SnapshotPermissionCondition, SnapshotPermissionOperand, SnapshotPermissionOperator, SnapshotRecordPermission, SnapshotRelationship, SnapshotSerial, SnapshotValidation, SnapshotValueOperand, TailorDBSnapshotType } from "./snapshot-types.mjs";
3
+ import { NormalizedSchemaSnapshot, SchemaSnapshot, SnapshotActionPermission, SnapshotEnumValue, SnapshotFieldConfig, SnapshotGqlPermission, SnapshotGqlPermissionPolicy, SnapshotIndexConfig, SnapshotPermissionCondition, SnapshotPermissionOperand, SnapshotRecordPermission, SnapshotRelationship, TailorDBSnapshotType } from "./snapshot-types.mjs";
4
4
  import { MigrationDiff } from "./diff-calculator.mjs";
5
5
  //#region src/cli/commands/tailordb/migrate/snapshot.d.ts
6
6
  /**
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { r as parseInputFields } from "../schema-CYrle8JZ.mjs";
3
- import { At as PATScope, Ct as AuthInvokerSchema, E as CustomDomainStatus, W as FunctionExecution_Type } from "../workspace_resource_pb-UGK1SSn_.mjs";
3
+ import { At as PATScope, Ct as AuthInvokerSchema, E as CustomDomainStatus, W as FunctionExecution_Type } from "../workspace_resource_pb-DXnO2AT-.mjs";
4
4
  import { t as assertDefined } from "../assert-DBxo8jPo.mjs";
5
5
  import { n as logger, r as styles } from "../logger-CXQq9YIp.mjs";
6
- import { $n as deploymentArgs, $t as handleOptionalToRequiredError, An as generateUserTypes, At as startCommand, Bn as loadConsoleBaseUrl, Ct as listCommand$7, Dn as resourceTrn, Dt as jobsCommand, E as listCommand$13, En as getNamespacesWithMigrations, F as openInConfiguredEditor, Fn as deleteUserTokens, G as treeCommand, Gn as readPlatformConfig, H as updateCommand$3, Hn as loadStoredUserTokens, Ht as listCommand$16, In as fetchLatestToken, J as getCommand$5, Jn as writePlatformConfig, Jt as ensureConfigId, K as listCommand$12, Kn as resolveUserTokenKey, Kt as formatKeyValueTable, L as showCommand, Ln as hasAnyUserTokenEntry, Lt as functionExecutionStatusToString, M as generateMigrationScript, Mn as apiCall, Mt as getCommand$6, N as writeDbTypesFile, Nn as assertWritable, On as sdkNameLabelKey, P as getConfiguredEditorCommand, Pn as loadConfig, Pt as executionsCommand, Q as listCommand$11, Qn as confirmationArgs, Qt as MIGRATION_LABEL_KEY, R as extractOwnedNamespaces, Rn as hasUserTokenEntry, Rt as getCommand$1, S as waitCommand, Sn as parseMigrationNumberArg, Tn as hasChanges, Un as loadWorkspaceId, V as removeCommand$1, Vn as loadMachineUserName, Vt as deployFromCLI, Wn as platformConfigFromProfile, Wt as createCommand$4, X as updateCommand$2, Xn as commonArgs, Yn as defineAppCommand, Yt as executeScript, Zn as configArg, _t as getCommand$2, ar as toPageDirection, bn as reconstructSnapshotFromMigrations, bt as webhookCommand, c as listCommand$15, ct as getCommand$3, dt as tokenCommand, en as parseMigrationLabelNumber, er as isVerbose, et as getCommand$4, f as restoreCommand, fn as createSnapshotFromLocalTypes, ft as listCommand$9, g as deleteCommand$5, gn as getMigrationFiles, hn as getMigrationFilePath, ht as listCommand$8, i as updateCommand$4, ir as resolveMachineUserInputSource, it as createCommand$3, j as generateCommand$1, jn as prompt, k as truncateCommand, kn as PluginManager, ln as assertValidMigrationFiles, m as getCommand$7, mt as generate, nn as generateAllTypeManifestsFromSnapshot, nr as pagedLogArgs, nt as deleteCommand$4, o as removeCommand, on as INITIAL_SCHEMA_NUMBER, or as workspaceArgs, ot as listCommand$10, pn as getLatestMigrationNumber, qn as saveUserTokens, qt as workspaceNameSchema, r as queryCommand, rn as protoGqlPermission, rr as paginationArgs, t as registerTypeScriptRuntime, tn as compareSnapshotWithRemote, tr as multiConfigArg, u as inviteCommand, un as compareLocalTypesWithSnapshot, vn as isValidMigrationNumber, w as resumeCommand, wn as formatMigrationDiff, x as healthCommand, xn as formatMigrationNumber, xt as triggerCommand, y as listCommand$14, yn as loadDiff, z as logBetaWarning, zn as loadAccessToken } from "../register-typescript-runtime-CCHyKeXO.mjs";
7
- import { A as defaultPlatformBaseUrl, D as hashContent$1, E as getDistDir, F as fetchPlatformMachineUserToken, H as initOperatorClient, I as fetchUserInfo, M as fetchAllTolerant, P as fetchPaged, S as resolveBundleLogLevel, U as isDefaultPlatform, V as initOAuth2Client, a as resolveInlineSourcemap, b as composeFunctionTreeshakeOptions, c as ResolverSchema, j as fetchAll, k as closeConnectionPool, p as buildResolverPermissionAndInputCheckExpr, s as WorkflowJobSchema, t as defineApplication, u as INVOKER_EXPR, v as resolveTSConfigWithFallback, x as createLogLevelTreeshakeOptions, y as platformBundleDefinePlugin, z as getOrNull } from "../application-Cp0FxIm2.mjs";
8
- import { n as ExecutorSchema } from "../service-B0MaodSg.mjs";
6
+ import { $n as writePlatformConfig, $t as logRemoteDriftGuidance, An as hasChanges, At as startCommand, Bn as deleteUserTokens, Cn as isValidMigrationNumber, Ct as listCommand$7, Dn as parseMigrationNumberArg, Dt as jobsCommand, E as listCommand$13, En as formatMigrationNumber, F as openInConfiguredEditor, Fn as generateUserTypes, G as treeCommand, Gn as loadConsoleBaseUrl, H as updateCommand$3, Hn as hasAnyUserTokenEntry, Ht as listCommand$16, In as prompt, J as getCommand$5, Jn as loadWorkspaceId, Jt as ensureConfigId, K as listCommand$12, Kn as loadMachineUserName, Kt as formatKeyValueTable, L as showCommand, Ln as apiCall, Lt as functionExecutionStatusToString, M as generateMigrationScript, Mn as resourceTrn, Mt as getCommand$6, N as writeDbTypesFile, Nn as sdkNameLabelKey, On as formatDiffSummary, P as getConfiguredEditorCommand, Pn as PluginManager, Pt as executionsCommand, Q as listCommand$11, Qn as saveUserTokens, Qt as checkMigrationDiffs, R as extractOwnedNamespaces, Rn as assertWritable, Rt as getCommand$1, S as waitCommand, Tn as reconstructSnapshotFromMigrations, Un as hasUserTokenEntry, V as removeCommand$1, Vn as fetchLatestToken, Vt as deployFromCLI, Wn as loadAccessToken, Wt as createCommand$4, X as updateCommand$2, Xn as readPlatformConfig, Yn as platformConfigFromProfile, Yt as executeScript, Zn as resolveUserTokenKey, _n as formatSchemaDrifts, _t as getCommand$2, an as compareSnapshotWithRemote, ar as isVerbose, bn as getMigrationFilePath, bt as webhookCommand, c as listCommand$15, cr as paginationArgs, ct as getCommand$3, dr as workspaceArgs, dt as tokenCommand, en as toTailorDBDeployInput, er as defineAppCommand, et as getCommand$4, f as restoreCommand, ft as listCommand$9, g as deleteCommand$5, gn as createSnapshotFromLocalTypes, ht as listCommand$8, i as updateCommand$4, in as parseMigrationLabelNumber, ir as deploymentArgs, it as createCommand$3, j as generateCommand$1, jn as getNamespacesWithMigrations, k as truncateCommand, kn as formatMigrationDiff, lr as resolveMachineUserInputSource, m as getCommand$7, mn as compareLocalTypesWithSnapshot, mt as generate, nn as MIGRATION_LABEL_KEY, nr as configArg, nt as deleteCommand$4, o as removeCommand, on as generateAllTypeManifestsFromSnapshot, or as multiConfigArg, ot as listCommand$10, pn as assertValidMigrationFiles, qn as loadStoredUserTokens, qt as workspaceNameSchema, r as queryCommand, rn as handleOptionalToRequiredError, rr as confirmationArgs, sn as protoGqlPermission, sr as pagedLogArgs, t as registerTypeScriptRuntime, tn as verifyRemoteSchema, tr as commonArgs, u as inviteCommand, un as INITIAL_SCHEMA_NUMBER, ur as toPageDirection, vn as getLatestMigrationNumber, w as resumeCommand, wn as loadDiff, x as healthCommand, xn as getMigrationFiles, xt as triggerCommand, y as listCommand$14, z as logBetaWarning, zn as loadConfig } from "../register-typescript-runtime-nG-n9lPw.mjs";
7
+ import { A as hashContent$1, C as createLogLevelTreeshakeOptions, F as fetchAllTolerant, G as initOperatorClient, H as getOrNull, K as isDefaultPlatform, L as fetchPaged, M as closeConnectionPool, N as defaultPlatformBaseUrl, P as fetchAll, R as fetchPlatformMachineUserToken, S as composeFunctionTreeshakeOptions, T as createBundleLog, W as initOAuth2Client, a as resolveInlineSourcemap, b as resolveTSConfigWithFallback, c as ResolverSchema, k as getDistDir, m as assertUniqueLocalTailorDBTypeNames, p as buildResolverPermissionAndInputCheckExpr, s as WorkflowJobSchema, t as defineApplication, u as INVOKER_EXPR, v as createGeneratedEntryResolverPlugin, w as resolveBundleLogLevel, x as platformBundleDefinePlugin, y as createTsconfigPathsPlugin, z as fetchUserInfo } from "../application-m5tYtz0-.mjs";
8
+ import { n as ExecutorSchema } from "../service-CPJWhTLn.mjs";
9
9
  import { t as multiline } from "../multiline-sfHpTZZK.mjs";
10
10
  import { t as isPluginGeneratedType } from "../type-source-DH_LH20p.mjs";
11
11
  import { t as readPackageJson } from "../package-json-8b0O9TlX.mjs";
12
12
  import { t as userAgent } from "../user-agent-DX2Jnw0-.mjs";
13
13
  import { n as errorToJson, r as isCLIError, t as createCLIError } from "../errors-DVFS0AZk.mjs";
14
- import { t as OperatorService } from "../service_pb-BwZRiNug.mjs";
14
+ import { t as OperatorService } from "../service_pb-D5--My_M.mjs";
15
15
  import { a as JSON_FOOTER_MARKER, i as CRASH_LOG_EXTENSION, o as parseCrashReportConfig, r as sendCrashReport, t as initCrashReporting } from "../crashreport-DMYuHnBN.mjs";
16
16
  import { arg, defineCommand, runCommand, runMain } from "politty";
17
17
  import { withCompletionCommand } from "politty/completion";
@@ -1706,22 +1706,29 @@ async function bundleForTestRun(options) {
1706
1706
  const entryContent = generateEntry(detected, sourceFile, env, machineUser, workspaceId);
1707
1707
  fs$1.writeFileSync(entryPath, entryContent);
1708
1708
  const tsconfig = await resolveTSConfigWithFallback(baseDir);
1709
+ const bundleLog = createBundleLog({ tsconfig });
1710
+ const buildResult = await rolldown.build({
1711
+ plugins: [
1712
+ createGeneratedEntryResolverPlugin(entryPath, baseDir),
1713
+ createTsconfigPathsPlugin(),
1714
+ platformBundleDefinePlugin
1715
+ ],
1716
+ input: entryPath,
1717
+ write: false,
1718
+ output: {
1719
+ format: "esm",
1720
+ sourcemap: inlineSourcemap ? "inline" : true,
1721
+ minify: inlineSourcemap ? { mangle: { keepNames: true } } : true,
1722
+ codeSplitting: false,
1723
+ dir: process.cwd()
1724
+ },
1725
+ tsconfig,
1726
+ treeshake: composeFunctionTreeshakeOptions([createLogLevelTreeshakeOptions(bundleLogLevel)]),
1727
+ ...bundleLog.options
1728
+ });
1729
+ bundleLog.assertAllResolved();
1709
1730
  return {
1710
- bundledCode: (await rolldown.build({
1711
- plugins: [platformBundleDefinePlugin],
1712
- input: entryPath,
1713
- write: false,
1714
- output: {
1715
- format: "esm",
1716
- sourcemap: inlineSourcemap ? "inline" : true,
1717
- minify: inlineSourcemap ? { mangle: { keepNames: true } } : true,
1718
- codeSplitting: false,
1719
- dir: process.cwd()
1720
- },
1721
- tsconfig,
1722
- treeshake: composeFunctionTreeshakeOptions([createLogLevelTreeshakeOptions(bundleLogLevel)]),
1723
- logLevel: "silent"
1724
- })).output[0].code,
1731
+ bundledCode: buildResult.output[0].code,
1725
1732
  scriptName
1726
1733
  };
1727
1734
  }
@@ -6469,6 +6476,42 @@ const erdCommand = defineCommand({
6469
6476
  * automatically require one.
6470
6477
  */
6471
6478
  /**
6479
+ * Record in diff.json that a migration requiring a script intentionally has none.
6480
+ * @param {MarkScriptSkippedOptions} options - Target migration and skip reason
6481
+ * @returns {ScriptSkippedInfo} The recorded acknowledgment
6482
+ */
6483
+ function markMigrationScriptSkipped(options) {
6484
+ const { migrationsDir, migrationNumber, reason } = options;
6485
+ const label = formatMigrationNumber(migrationNumber);
6486
+ const normalizedReason = reason.trim();
6487
+ if (!normalizedReason) throw new Error("Migration script skip reason must not be empty.");
6488
+ const diffPath = getMigrationFilePath(migrationsDir, migrationNumber, "diff");
6489
+ if (!fs$1.existsSync(diffPath)) throw new Error(`Migration ${label} not found in ${migrationsDir}. Expected ${diffPath}.`);
6490
+ const diff = loadDiff(diffPath);
6491
+ if (!diff.requiresMigrationScript) throw new Error(`Migration ${label} does not require a migration script; nothing to skip.`);
6492
+ if (diff.scriptSkipped) throw new Error(`Migration ${label} already has a script skip recorded (${diff.scriptSkipped.acknowledgedAt}: ${diff.scriptSkipped.reason}).`);
6493
+ const migratePath = getMigrationFilePath(migrationsDir, migrationNumber, "migrate");
6494
+ if (fs$1.existsSync(migratePath)) throw new Error(`Migration script exists at ${migratePath}. Delete migrate.ts first if this migration should run without a script.`);
6495
+ const scriptSkipped = {
6496
+ reason: normalizedReason,
6497
+ acknowledgedAt: (/* @__PURE__ */ new Date()).toISOString()
6498
+ };
6499
+ const raw = JSON.parse(fs$1.readFileSync(diffPath, "utf-8"));
6500
+ raw.scriptSkipped = scriptSkipped;
6501
+ fs$1.writeFileSync(diffPath, JSON.stringify(raw, null, 2));
6502
+ return scriptSkipped;
6503
+ }
6504
+ /**
6505
+ * Remove a script skip acknowledgment after a real migration script is created.
6506
+ * @param diffPath - Migration diff file to update
6507
+ */
6508
+ function clearMigrationScriptSkipped(diffPath) {
6509
+ const raw = JSON.parse(fs$1.readFileSync(diffPath, "utf-8"));
6510
+ if (!Object.hasOwn(raw, "scriptSkipped")) return;
6511
+ delete raw.scriptSkipped;
6512
+ fs$1.writeFileSync(diffPath, JSON.stringify(raw, null, 2));
6513
+ }
6514
+ /**
6472
6515
  * Add a migrate.ts template to an existing migration directory.
6473
6516
  * @param {ScriptOptions} options - Command options
6474
6517
  */
@@ -6481,6 +6524,20 @@ async function script(options) {
6481
6524
  if (namespacesWithMigrations.length === 0) throw new Error("No TailorDB services with migrations configuration found");
6482
6525
  const targetNamespace = resolveTargetNamespace(namespacesWithMigrations, options.namespace);
6483
6526
  const { migrationsDir } = assertDefined(namespacesWithMigrations.find((ns) => ns.namespace === targetNamespace), "namespace with migrations not found");
6527
+ if (options.noScript) {
6528
+ const reason = options.reason?.trim();
6529
+ if (!reason) throw new Error("--reason is required with --no-script.");
6530
+ const scriptSkipped = markMigrationScriptSkipped({
6531
+ migrationsDir,
6532
+ migrationNumber,
6533
+ reason
6534
+ });
6535
+ logger.success(`Recorded that migration ${styles.bold(options.number)} in namespace ${styles.bold(targetNamespace)} intentionally has no migration script`);
6536
+ logger.info(` Reason: ${scriptSkipped.reason}`);
6537
+ logger.info(` Diff file: ${getMigrationFilePath(migrationsDir, migrationNumber, "diff")}`);
6538
+ return;
6539
+ }
6540
+ if (options.reason !== void 0) throw new Error("--reason can only be used together with --no-script.");
6484
6541
  const diffPath = getMigrationFilePath(migrationsDir, migrationNumber, "diff");
6485
6542
  if (!fs$1.existsSync(diffPath)) throw new Error(`Migration ${options.number} not found in ${migrationsDir}. Expected ${diffPath}.`);
6486
6543
  const migratePath = getMigrationFilePath(migrationsDir, migrationNumber, "migrate");
@@ -6491,6 +6548,7 @@ async function script(options) {
6491
6548
  const scriptContent = generateMigrationScript(diff);
6492
6549
  await fsPromises.writeFile(migratePath, scriptContent);
6493
6550
  await writeDbTypesFile(previousSnapshot, migrationsDir, migrationNumber, diff);
6551
+ clearMigrationScriptSkipped(diffPath);
6494
6552
  logger.success(`Added migration script for migration ${styles.bold(options.number)} in namespace ${styles.bold(targetNamespace)}`);
6495
6553
  logger.info(` Migration script: ${migratePath}`);
6496
6554
  logger.info(` DB types: ${getMigrationFilePath(migrationsDir, migrationNumber, "db")}`);
@@ -6520,7 +6578,7 @@ function resolveTargetNamespace(namespacesWithMigrations, requested) {
6520
6578
  }
6521
6579
  const scriptCommand = defineAppCommand({
6522
6580
  name: "script",
6523
- description: "Add a migration script (migrate.ts) template to an existing migration directory.",
6581
+ description: "Add a migration script (migrate.ts) template to an existing migration directory, or record with --no-script that a migration intentionally has none.",
6524
6582
  args: z.object({
6525
6583
  ...configArg,
6526
6584
  number: arg(z.string(), {
@@ -6530,13 +6588,17 @@ const scriptCommand = defineAppCommand({
6530
6588
  namespace: arg(z.string().optional(), {
6531
6589
  alias: "n",
6532
6590
  description: "Target TailorDB namespace (required if multiple namespaces exist)"
6533
- })
6591
+ }),
6592
+ "no-script": arg(z.boolean().optional(), { description: "Record that this migration intentionally runs without a migration script (requires --reason)" }),
6593
+ reason: arg(z.string().optional(), { description: "Reason why no migration script is needed (used with --no-script)" })
6534
6594
  }).strict(),
6535
6595
  run: async (args) => {
6536
6596
  await script({
6537
6597
  configPath: args.config,
6538
6598
  number: args.number,
6539
- namespace: args.namespace
6599
+ namespace: args.namespace,
6600
+ noScript: args["no-script"],
6601
+ reason: args.reason
6540
6602
  });
6541
6603
  }
6542
6604
  });
@@ -6575,7 +6637,7 @@ async function set(options) {
6575
6637
  let currentMigration;
6576
6638
  try {
6577
6639
  const { metadata } = await client.getMetadata({ trn });
6578
- const label = metadata?.labels["sdk-migration"];
6640
+ const label = metadata?.labels[MIGRATION_LABEL_KEY];
6579
6641
  currentMigration = label ? parseMigrationLabelNumber(label) ?? 0 : 0;
6580
6642
  } catch {
6581
6643
  currentMigration = 0;
@@ -6609,7 +6671,7 @@ async function set(options) {
6609
6671
  trn,
6610
6672
  labels: {
6611
6673
  ...existingLabels,
6612
- "sdk-migration": `m${formatMigrationNumber(migrationNumber)}`
6674
+ [MIGRATION_LABEL_KEY]: `m${formatMigrationNumber(migrationNumber)}`
6613
6675
  }
6614
6676
  });
6615
6677
  logger.success(`Migration checkpoint set to ${styles.bold(formatMigrationNumber(migrationNumber))} for namespace ${styles.bold(targetNamespace)}`);
@@ -6661,7 +6723,7 @@ async function collectMigrationStatuses(options) {
6661
6723
  let currentMigration;
6662
6724
  try {
6663
6725
  const { metadata } = await client.getMetadata({ trn });
6664
- const label = metadata?.labels["sdk-migration"];
6726
+ const label = metadata?.labels[MIGRATION_LABEL_KEY];
6665
6727
  currentMigration = label ? parseMigrationLabelNumber(label) ?? 0 : 0;
6666
6728
  } catch {
6667
6729
  currentMigration = 0;
@@ -6784,7 +6846,7 @@ async function fetchRemoteTypes(client, workspaceId, namespace) {
6784
6846
  async function assertMigrationsReproduceLocalTypes(loaded, target) {
6785
6847
  const { config, plugins } = loaded;
6786
6848
  const pluginManager = plugins.length > 0 ? new PluginManager(plugins) : void 0;
6787
- const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-CP7JKG9R.mjs");
6849
+ const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-C-zsrNjn.mjs");
6788
6850
  const application = defineApplication({
6789
6851
  config,
6790
6852
  pluginManager
@@ -6796,7 +6858,7 @@ async function assertMigrationsReproduceLocalTypes(loaded, target) {
6796
6858
  await service.processNamespacePlugins();
6797
6859
  }
6798
6860
  const pluginExecutorFiles = generatePluginFilesIfNeeded(pluginManager, application.tailorDBServices, config.path);
6799
- const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-KnAiVofD.mjs")).createExecutorService({
6861
+ const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-Cigg_U-v.mjs")).createExecutorService({
6800
6862
  config: { files: [] },
6801
6863
  baseDir: path.dirname(config.path)
6802
6864
  }) : void 0);
@@ -7015,6 +7077,204 @@ const syncCommand = defineAppCommand({
7015
7077
  }
7016
7078
  });
7017
7079
 
7080
+ //#endregion
7081
+ //#region src/cli/commands/tailordb/migrate/validate.ts
7082
+ /**
7083
+ * Assert that every migration in the local history whose diff requires a data
7084
+ * migration script has a migrate.ts on disk or an explicit skip acknowledgment
7085
+ * @param {string} migrationsDir - Migrations directory path
7086
+ * @param {string} namespace - TailorDB namespace (for error messages)
7087
+ */
7088
+ function assertRequiredMigrationScripts(migrationsDir, namespace) {
7089
+ const missing = [];
7090
+ for (const file of getMigrationFiles(migrationsDir)) {
7091
+ if (file.type !== "diff") continue;
7092
+ const diff = loadDiff(file.path);
7093
+ if (!diff.requiresMigrationScript || diff.scriptSkipped) continue;
7094
+ if (!fs$1.existsSync(getMigrationFilePath(migrationsDir, file.number, "migrate"))) missing.push(file.number);
7095
+ }
7096
+ if (missing.length > 0) throw new Error(`Migration(s) ${missing.map(formatMigrationNumber).join(", ")} in namespace "${namespace}" require a migration script but have no migrate.ts. Add one with 'tailor-sdk tailordb migration script <number>', or record that no script is needed with 'tailor-sdk tailordb migration script <number> --no-script --reason "..."'.`);
7097
+ }
7098
+ /**
7099
+ * Build per-namespace reports from the checks that completed
7100
+ * @param {BuildValidationReportsOptions} options - Completed validation results
7101
+ * @returns {NamespaceValidationReport[]} Validation reports per namespace
7102
+ */
7103
+ function buildValidationReports(options) {
7104
+ const { targetNamespaces, migrationFileErrors, localResults, remoteResults } = options;
7105
+ return targetNamespaces.map((target) => {
7106
+ const fileError = migrationFileErrors.get(target.namespace);
7107
+ if (fileError !== void 0) return {
7108
+ namespace: target.namespace,
7109
+ valid: false,
7110
+ migrationFiles: {
7111
+ valid: false,
7112
+ error: fileError
7113
+ }
7114
+ };
7115
+ const local = assertDefined(localResults.find((result) => result.namespace === target.namespace), `local schema check result missing for namespace "${target.namespace}"`);
7116
+ const localSchema = {
7117
+ hasDiff: local.hasDiff,
7118
+ ...local.diff ? { diff: local.diff } : {}
7119
+ };
7120
+ if (remoteResults === void 0) return {
7121
+ namespace: target.namespace,
7122
+ valid: false,
7123
+ migrationFiles: { valid: true },
7124
+ localSchema,
7125
+ remoteSchema: { skipped: "check_failed" }
7126
+ };
7127
+ const remote = assertDefined(remoteResults.find((result) => result.namespace === target.namespace), `remote schema check result missing for namespace "${target.namespace}"`);
7128
+ const checkpointMissingLocal = remote.checkpointMissingLocal === true;
7129
+ const remoteSchema = {
7130
+ remoteMigrationNumber: remote.remoteMigrationNumber,
7131
+ hasDrift: remote.hasDrift,
7132
+ drifts: remote.drifts,
7133
+ ...remote.skipped ? { skipped: remote.skipped } : {},
7134
+ ...checkpointMissingLocal ? { checkpointMissingLocal: true } : {}
7135
+ };
7136
+ return {
7137
+ namespace: target.namespace,
7138
+ valid: !localSchema.hasDiff && !remoteSchema.hasDrift && !checkpointMissingLocal,
7139
+ migrationFiles: { valid: true },
7140
+ localSchema,
7141
+ remoteSchema
7142
+ };
7143
+ });
7144
+ }
7145
+ /**
7146
+ * Run all migration validation checks and collect per-namespace reports
7147
+ * @param {ValidateOptions} options - Command options
7148
+ * @returns {Promise<CollectedValidationReports>} Validation reports and any remote error
7149
+ */
7150
+ async function collectValidationReports(options) {
7151
+ const { config, plugins } = await loadConfig(options.configPath);
7152
+ const namespacesWithMigrations = getNamespacesWithMigrations(config, path.dirname(config.path));
7153
+ if (namespacesWithMigrations.length === 0) throw new Error("No TailorDB services with migrations configuration found");
7154
+ const targetNamespaces = options.namespace ? namespacesWithMigrations.filter((ns) => ns.namespace === options.namespace) : namespacesWithMigrations;
7155
+ if (targetNamespaces.length === 0) throw new Error(`Namespace "${options.namespace}" not found or does not have migrations configured`);
7156
+ const pluginManager = plugins.length > 0 ? new PluginManager(plugins) : void 0;
7157
+ const { defineApplication } = await import("../application-C-zsrNjn.mjs");
7158
+ const application = defineApplication({
7159
+ config,
7160
+ pluginManager
7161
+ });
7162
+ for (const service of application.tailorDBServices) {
7163
+ await service.loadTypes();
7164
+ await service.processNamespacePlugins();
7165
+ }
7166
+ assertUniqueLocalTailorDBTypeNames({ tailorDBServices: application.tailorDBServices });
7167
+ for (const { namespace } of targetNamespaces) if (!application.tailorDBServices.some((s) => s.namespace === namespace)) throw new Error(`No TailorDB service found for namespace "${namespace}"`);
7168
+ const tailorDBInputs = application.tailorDBServices.map(toTailorDBDeployInput);
7169
+ const typesByNamespace = new Map(tailorDBInputs.map((input) => [input.namespace, input.types]));
7170
+ const migrationFileErrors = /* @__PURE__ */ new Map();
7171
+ const checkableNamespaces = [];
7172
+ for (const target of targetNamespaces) try {
7173
+ assertValidMigrationFiles(target.migrationsDir, target.namespace);
7174
+ reconstructSnapshotFromMigrations(target.migrationsDir);
7175
+ assertRequiredMigrationScripts(target.migrationsDir, target.namespace);
7176
+ checkableNamespaces.push(target);
7177
+ } catch (error) {
7178
+ migrationFileErrors.set(target.namespace, error instanceof Error ? error.message : String(error));
7179
+ }
7180
+ const localReportOptions = {
7181
+ targetNamespaces,
7182
+ migrationFileErrors,
7183
+ localResults: await checkMigrationDiffs(typesByNamespace, checkableNamespaces)
7184
+ };
7185
+ if (checkableNamespaces.length === 0) return { reports: buildValidationReports(localReportOptions) };
7186
+ let remoteResults;
7187
+ try {
7188
+ remoteResults = await verifyRemoteSchema(await initOperatorClient(await loadAccessToken({ profile: options.profile })), await loadWorkspaceId({
7189
+ workspaceId: options.workspaceId,
7190
+ profile: options.profile
7191
+ }), checkableNamespaces, config, tailorDBInputs);
7192
+ } catch (remoteError) {
7193
+ return {
7194
+ reports: buildValidationReports(localReportOptions),
7195
+ remoteError
7196
+ };
7197
+ }
7198
+ return { reports: buildValidationReports({
7199
+ ...localReportOptions,
7200
+ remoteResults
7201
+ }) };
7202
+ }
7203
+ function printValidationReports(reports) {
7204
+ for (const report of reports) {
7205
+ logger.newline();
7206
+ logger.info(`Namespace: ${styles.bold(report.namespace)}`);
7207
+ if (!report.migrationFiles.valid) {
7208
+ logger.log(` Migration files: ${styles.error("invalid")}`);
7209
+ logger.log(` ${report.migrationFiles.error}`);
7210
+ continue;
7211
+ }
7212
+ logger.log(` Migration files: ${styles.success("OK")}`);
7213
+ const local = report.localSchema;
7214
+ if (local?.hasDiff) if (local.diff) {
7215
+ logger.log(` Local schema: ${styles.error("changes not in migration files")}`);
7216
+ logger.log(` ${formatDiffSummary(local.diff)}`);
7217
+ logger.log(formatMigrationDiff(local.diff));
7218
+ } else logger.log(` Local schema: ${styles.error("no migration snapshot found")}`);
7219
+ else logger.log(` Local schema: ${styles.success("OK")}`);
7220
+ const remote = report.remoteSchema;
7221
+ if (remote?.skipped === "check_failed") logger.log(` Remote schema: ${styles.error("not checked")}`);
7222
+ else if (remote?.checkpointMissingLocal) logger.log(` Remote schema: ${styles.error(`remote migration ${formatMigrationNumber(remote.remoteMigrationNumber)} is not in the local migration history`)}`);
7223
+ else if (remote?.hasDrift) {
7224
+ logger.log(` Remote schema: ${styles.error("drift detected")} (remote migration: ${formatMigrationNumber(remote.remoteMigrationNumber)})`);
7225
+ logger.log(formatSchemaDrifts(remote.drifts));
7226
+ } else if (remote?.skipped === "not_deployed") logger.log(` Remote schema: ${styles.dim("skipped (namespace not deployed)")}`);
7227
+ else if (remote?.skipped === "no_migration_label") logger.log(` Remote schema: ${styles.dim("skipped (deployed namespace has no migration state)")}`);
7228
+ else if (remote?.skipped === "no_snapshot") logger.log(` Remote schema: ${styles.dim(`skipped (no local snapshot for remote migration ${formatMigrationNumber(remote.remoteMigrationNumber)})`)}`);
7229
+ else if (remote) logger.log(` Remote schema: ${styles.success("OK")} (remote migration: ${formatMigrationNumber(remote.remoteMigrationNumber)})`);
7230
+ }
7231
+ logger.newline();
7232
+ }
7233
+ function printResolutionHints(reports) {
7234
+ if (reports.some((r) => r.localSchema?.hasDiff && !r.localSchema.diff)) logger.info("Run 'tailor-sdk tailordb migration generate' to create the initial snapshot.");
7235
+ if (reports.some((r) => r.localSchema?.diff)) logger.info("Run 'tailor-sdk tailordb migration generate' to create migration files.");
7236
+ if (reports.some((r) => r.remoteSchema?.checkpointMissingLocal)) logger.info("The remote migration checkpoint is ahead of the local history. Pull the latest migration files, or run 'tailor-sdk tailordb migration status' to compare.");
7237
+ if (reports.some((r) => r.remoteSchema?.hasDrift)) logRemoteDriftGuidance();
7238
+ }
7239
+ /**
7240
+ * Validate migration files and schema state without deploying
7241
+ * @param {ValidateOptions} options - Command options
7242
+ */
7243
+ async function validate(options) {
7244
+ logBetaWarning("tailordb migration");
7245
+ const collected = await collectValidationReports(options);
7246
+ const { reports } = collected;
7247
+ const invalidCount = reports.filter((r) => !r.valid).length;
7248
+ if (options.json) logger.out(reports);
7249
+ else {
7250
+ printValidationReports(reports);
7251
+ if (invalidCount === 0 && !("remoteError" in collected)) logger.success("All migration validation checks passed.");
7252
+ else printResolutionHints(reports);
7253
+ }
7254
+ if ("remoteError" in collected) throw collected.remoteError;
7255
+ if (invalidCount > 0) throw new Error(`Migration validation failed for ${invalidCount} namespace(s)`);
7256
+ }
7257
+ const validateCommand = defineAppCommand({
7258
+ name: "validate",
7259
+ description: "Validate the full migration history and detect schema drift (local types vs. migration snapshot, remote schema vs. migration checkpoint) without deploying. This includes the migration and schema-drift checks used by 'deploy' and exits with a non-zero code when issues are found.",
7260
+ args: z.object({
7261
+ ...deploymentArgs,
7262
+ namespace: arg(z.string().optional(), {
7263
+ alias: "n",
7264
+ description: "Target TailorDB namespace (validates all namespaces if not specified)"
7265
+ })
7266
+ }).strict(),
7267
+ run: async (args) => {
7268
+ await validate({
7269
+ configPath: args.config,
7270
+ namespace: args.namespace,
7271
+ workspaceId: args["workspace-id"],
7272
+ profile: args.profile,
7273
+ json: logger.jsonMode
7274
+ });
7275
+ }
7276
+ });
7277
+
7018
7278
  //#endregion
7019
7279
  //#region src/cli/commands/tailordb/migrate/index.ts
7020
7280
  /**
@@ -7026,6 +7286,7 @@ const syncCommand = defineAppCommand({
7026
7286
  * - set: Set migration checkpoint to a specific number
7027
7287
  * - status: Show migration status for TailorDB namespaces
7028
7288
  * - sync: Sync remote TailorDB schema to a specific migration snapshot
7289
+ * - validate: Validate migration files and detect schema drift without deploying
7029
7290
  */
7030
7291
  const migrationCommand = defineCommand({
7031
7292
  name: "migration",
@@ -7035,7 +7296,8 @@ const migrationCommand = defineCommand({
7035
7296
  script: scriptCommand,
7036
7297
  set: setCommand,
7037
7298
  status: statusCommand,
7038
- sync: syncCommand
7299
+ sync: syncCommand,
7300
+ validate: validateCommand
7039
7301
  }
7040
7302
  });
7041
7303