@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
|
@@ -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
|
|
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 {
|
|
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 };
|
|
@@ -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,
|
|
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
|
/**
|
package/dist/cli/index.mjs
CHANGED
|
@@ -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-
|
|
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
|
|
7
|
-
import { A as
|
|
8
|
-
import { n as ExecutorSchema } from "../service-
|
|
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-
|
|
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:
|
|
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[
|
|
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
|
-
|
|
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[
|
|
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-
|
|
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-
|
|
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
|
|