@prisma-next/cli 0.4.0-dev.5 → 0.4.0-dev.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/dist/cli-errors-BUuJr6py.mjs +5 -0
- package/dist/{cli-errors-DStABy9d.d.mts → cli-errors-Dic2eADK.d.mts} +1 -0
- package/dist/cli.mjs +9 -16
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-tdnbk0OR.mjs → client-DUs1DH-1.mjs} +2 -2
- package/dist/{client-tdnbk0OR.mjs.map → client-DUs1DH-1.mjs.map} +1 -1
- package/dist/commands/contract-emit.mjs +1 -6
- package/dist/commands/contract-infer.mjs +1 -7
- package/dist/commands/db-init.mjs +5 -6
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -6
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.mjs +4 -5
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.mjs +5 -6
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +4 -5
- package/dist/commands/db-verify.mjs.map +1 -1
- package/dist/commands/migration-apply.mjs +6 -7
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-emit.d.mts +38 -0
- package/dist/commands/migration-emit.d.mts.map +1 -0
- package/dist/commands/migration-emit.mjs +81 -0
- package/dist/commands/migration-emit.mjs.map +1 -0
- package/dist/commands/migration-new.mjs +5 -5
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +13 -32
- package/dist/commands/migration-plan.mjs.map +1 -1
- package/dist/commands/migration-ref.d.mts +1 -1
- package/dist/commands/migration-ref.mjs +2 -2
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.mjs +4 -4
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.mjs +1 -6
- package/dist/{contract-emit-Ctn6mH9H.mjs → contract-emit-7jqH6dq9.mjs} +5 -5
- package/dist/{contract-emit-Ctn6mH9H.mjs.map → contract-emit-7jqH6dq9.mjs.map} +1 -1
- package/dist/contract-emit-C2_J2U7A.mjs +4 -0
- package/dist/{contract-emit-CRoS1nx5.mjs → contract-emit-CKig_Lra.mjs} +4 -4
- package/dist/{contract-emit-CRoS1nx5.mjs.map → contract-emit-CKig_Lra.mjs.map} +1 -1
- package/dist/{contract-infer-Ba1SE57Q.mjs → contract-infer-BFlIbyl9.mjs} +3 -3
- package/dist/{contract-infer-Ba1SE57Q.mjs.map → contract-infer-BFlIbyl9.mjs.map} +1 -1
- package/dist/exports/control-api.mjs +2 -4
- package/dist/exports/index.mjs +1 -6
- package/dist/exports/index.mjs.map +1 -1
- package/dist/{framework-components-BAsliT4V.mjs → framework-components-Bsr1GaIj.mjs} +2 -2
- package/dist/{framework-components-BAsliT4V.mjs.map → framework-components-Bsr1GaIj.mjs.map} +1 -1
- package/dist/{init-CYWnL7gq.mjs → init-DlFLMBaU.mjs} +2 -2
- package/dist/{init-CYWnL7gq.mjs.map → init-DlFLMBaU.mjs.map} +1 -1
- package/dist/{inspect-live-schema-gYQiWfpl.mjs → inspect-live-schema-gjmUZ8xm.mjs} +4 -4
- package/dist/{inspect-live-schema-gYQiWfpl.mjs.map → inspect-live-schema-gjmUZ8xm.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-x4n_ZhAh.mjs → migration-command-scaffold-CfllKppa.mjs} +4 -4
- package/dist/{migration-command-scaffold-x4n_ZhAh.mjs.map → migration-command-scaffold-CfllKppa.mjs.map} +1 -1
- package/dist/migration-emit-dRXV6QSz.mjs +72 -0
- package/dist/migration-emit-dRXV6QSz.mjs.map +1 -0
- package/dist/{migration-status-DyVDf5NI.mjs → migration-status-BwKCQB_a.mjs} +5 -5
- package/dist/{migration-status-DyVDf5NI.mjs.map → migration-status-BwKCQB_a.mjs.map} +1 -1
- package/dist/{migrations-DTZBYXm1.mjs → migrations-BIsjFjSV.mjs} +6 -15
- package/dist/migrations-BIsjFjSV.mjs.map +1 -0
- package/dist/{result-handler-oK_vA-Fn.mjs → result-handler-AFK4hxyX.mjs} +2 -2
- package/dist/result-handler-AFK4hxyX.mjs.map +1 -0
- package/dist/{validate-contract-deps-esa-VQ0h.mjs → validate-contract-deps-DBH6iTAD.mjs} +1 -1
- package/dist/{validate-contract-deps-esa-VQ0h.mjs.map → validate-contract-deps-DBH6iTAD.mjs.map} +1 -1
- package/dist/{verify-DlFQ2FOw.mjs → verify-C56CuQc7.mjs} +2 -2
- package/dist/{verify-DlFQ2FOw.mjs.map → verify-C56CuQc7.mjs.map} +1 -1
- package/package.json +19 -19
- package/src/cli.ts +4 -4
- package/src/commands/migration-apply.ts +2 -2
- package/src/commands/migration-emit.ts +132 -0
- package/src/commands/migration-new.ts +3 -3
- package/src/commands/migration-plan.ts +15 -57
- package/src/commands/migration-show.ts +1 -1
- package/src/commands/migration-status.ts +1 -1
- package/src/lib/migration-emit.ts +113 -0
- package/src/utils/cli-errors.ts +5 -0
- package/src/utils/formatters/help.ts +1 -1
- package/src/utils/formatters/migrations.ts +6 -20
- package/dist/cli-errors-BDCYR5ap.mjs +0 -4
- package/dist/commands/migration-verify.d.mts +0 -16
- package/dist/commands/migration-verify.d.mts.map +0 -1
- package/dist/commands/migration-verify.mjs +0 -110
- package/dist/commands/migration-verify.mjs.map +0 -1
- package/dist/contract-emit-CVUWsFfx.mjs +0 -6
- package/dist/migrations-DTZBYXm1.mjs.map +0 -1
- package/dist/result-handler-oK_vA-Fn.mjs.map +0 -1
- package/src/commands/migration-verify.ts +0 -180
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { MigrationToolsError } from '@prisma-next/migration-tools/types';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { loadConfig } from '../config-loader';
|
|
5
|
+
import { emitMigration } from '../lib/migration-emit';
|
|
6
|
+
import {
|
|
7
|
+
CliStructuredError,
|
|
8
|
+
errorRuntime,
|
|
9
|
+
errorTargetMigrationNotSupported,
|
|
10
|
+
errorUnexpected,
|
|
11
|
+
} from '../utils/cli-errors';
|
|
12
|
+
import {
|
|
13
|
+
addGlobalOptions,
|
|
14
|
+
getTargetMigrations,
|
|
15
|
+
setCommandDescriptions,
|
|
16
|
+
setCommandExamples,
|
|
17
|
+
} from '../utils/command-helpers';
|
|
18
|
+
import { formatMigrationEmitCommandOutput } from '../utils/formatters/migrations';
|
|
19
|
+
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
20
|
+
import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
|
|
21
|
+
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
22
|
+
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
23
|
+
import { handleResult } from '../utils/result-handler';
|
|
24
|
+
import { TerminalUI } from '../utils/terminal-ui';
|
|
25
|
+
|
|
26
|
+
export interface MigrationEmitOptions extends CommonCommandOptions {
|
|
27
|
+
readonly dir: string;
|
|
28
|
+
readonly config?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface MigrationEmitResult {
|
|
32
|
+
readonly ok: boolean;
|
|
33
|
+
readonly dir: string;
|
|
34
|
+
readonly migrationId: string;
|
|
35
|
+
readonly summary: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function executeMigrationEmitCommand(
|
|
39
|
+
options: MigrationEmitOptions,
|
|
40
|
+
flags: GlobalFlags,
|
|
41
|
+
ui: TerminalUI,
|
|
42
|
+
): Promise<Result<MigrationEmitResult, CliStructuredError>> {
|
|
43
|
+
const dir = options.dir;
|
|
44
|
+
|
|
45
|
+
if (!flags.json && !flags.quiet) {
|
|
46
|
+
const header = formatStyledHeader({
|
|
47
|
+
command: 'migration emit',
|
|
48
|
+
description: 'Emit ops.json from migration.ts and compute migrationId',
|
|
49
|
+
details: [{ label: 'dir', value: dir }],
|
|
50
|
+
flags,
|
|
51
|
+
});
|
|
52
|
+
ui.stderr(header);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const config = await loadConfig(options.config);
|
|
57
|
+
const migrations = getTargetMigrations(config.target);
|
|
58
|
+
if (!migrations) {
|
|
59
|
+
throw errorTargetMigrationNotSupported({
|
|
60
|
+
why: `Target "${config.target.id}" does not support migrations`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
64
|
+
config.family.familyId,
|
|
65
|
+
config.target.targetId,
|
|
66
|
+
[config.target, config.adapter, ...(config.extensionPacks ?? [])],
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const { migrationId } = await emitMigration(dir, {
|
|
70
|
+
targetId: config.target.targetId,
|
|
71
|
+
migrations,
|
|
72
|
+
frameworkComponents,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return ok({
|
|
76
|
+
ok: true,
|
|
77
|
+
dir,
|
|
78
|
+
migrationId,
|
|
79
|
+
summary: `Emitted ops.json and attested migrationId: ${migrationId}`,
|
|
80
|
+
});
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (CliStructuredError.is(error)) {
|
|
83
|
+
return notOk(error);
|
|
84
|
+
}
|
|
85
|
+
if (MigrationToolsError.is(error)) {
|
|
86
|
+
return notOk(
|
|
87
|
+
errorRuntime(error.message, {
|
|
88
|
+
why: error.why,
|
|
89
|
+
fix: error.fix,
|
|
90
|
+
meta: { code: error.code, ...(error.details ?? {}) },
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return notOk(
|
|
95
|
+
errorUnexpected(error instanceof Error ? error.message : String(error), {
|
|
96
|
+
why: `Failed to emit migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function createMigrationEmitCommand(): Command {
|
|
103
|
+
const command = new Command('emit');
|
|
104
|
+
setCommandDescriptions(
|
|
105
|
+
command,
|
|
106
|
+
'Emit ops.json from migration.ts and compute migrationId',
|
|
107
|
+
'Evaluates migration.ts in the package directory, resolves it to ops.json,\n' +
|
|
108
|
+
'then computes and persists the content-addressed migrationId in manifest.json.',
|
|
109
|
+
);
|
|
110
|
+
setCommandExamples(command, ['prisma-next migration emit --dir migrations/20250101-add-users']);
|
|
111
|
+
addGlobalOptions(command)
|
|
112
|
+
.requiredOption('--dir <path>', 'Path to the migration package directory')
|
|
113
|
+
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
114
|
+
.action(async (options: MigrationEmitOptions) => {
|
|
115
|
+
const flags = parseGlobalFlags(options);
|
|
116
|
+
const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
|
|
117
|
+
|
|
118
|
+
const result = await executeMigrationEmitCommand(options, flags, ui);
|
|
119
|
+
|
|
120
|
+
const exitCode = handleResult(result, flags, ui, (emitResult) => {
|
|
121
|
+
if (flags.json) {
|
|
122
|
+
ui.output(JSON.stringify(emitResult, null, 2));
|
|
123
|
+
} else if (!flags.quiet) {
|
|
124
|
+
ui.log(formatMigrationEmitCommandOutput(emitResult, flags));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
process.exit(exitCode);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return command;
|
|
132
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `migration new` — scaffolds a migration package with a migration.ts file
|
|
3
3
|
* for manual authoring. The user writes operation descriptors and data
|
|
4
|
-
* transforms; `migration
|
|
4
|
+
* transforms; `migration emit` resolves them to ops.json.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { readFileSync } from 'node:fs';
|
|
@@ -214,7 +214,7 @@ export function createMigrationNewCommand(): Command {
|
|
|
214
214
|
'Scaffold a new migration for manual authoring',
|
|
215
215
|
'Creates a migration package with a migration.ts file for manual authoring.\n' +
|
|
216
216
|
'Write operation descriptors and data transforms in migration.ts, then run\n' +
|
|
217
|
-
'`migration
|
|
217
|
+
'`migration emit` to resolve and attest the package.',
|
|
218
218
|
);
|
|
219
219
|
setCommandExamples(command, [
|
|
220
220
|
'prisma-next migration new --name split-name',
|
|
@@ -248,7 +248,7 @@ export function createMigrationNewCommand(): Command {
|
|
|
248
248
|
ui.output(` from: ${value.from}`);
|
|
249
249
|
ui.output(` to: ${value.to}`);
|
|
250
250
|
ui.output(
|
|
251
|
-
`\nEdit migration.ts, then run \`prisma-next migration
|
|
251
|
+
`\nEdit migration.ts, then run \`prisma-next migration emit --dir "${value.dir}"\` to attest.`,
|
|
252
252
|
);
|
|
253
253
|
}
|
|
254
254
|
});
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
|
-
import type { OperationDescriptor } from '@prisma-next/framework-components/control';
|
|
4
|
-
import { attestMigration } from '@prisma-next/migration-tools/attestation';
|
|
5
3
|
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
6
4
|
import { findLatestMigration } from '@prisma-next/migration-tools/dag';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
writeMigrationOps,
|
|
10
|
-
writeMigrationPackage,
|
|
11
|
-
} from '@prisma-next/migration-tools/io';
|
|
12
|
-
import {
|
|
13
|
-
evaluateMigrationTs,
|
|
14
|
-
scaffoldMigrationTs,
|
|
15
|
-
} from '@prisma-next/migration-tools/migration-ts';
|
|
5
|
+
import { formatMigrationDirName, writeMigrationPackage } from '@prisma-next/migration-tools/io';
|
|
6
|
+
import { scaffoldMigrationTs } from '@prisma-next/migration-tools/migration-ts';
|
|
16
7
|
import { type MigrationManifest, MigrationToolsError } from '@prisma-next/migration-tools/types';
|
|
17
8
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
18
9
|
import { Command } from 'commander';
|
|
19
10
|
import { join, relative } from 'pathe';
|
|
20
11
|
import { loadConfig } from '../config-loader';
|
|
21
12
|
import { extractSqlDdl } from '../control-api/operations/extract-sql-ddl';
|
|
13
|
+
import { emitMigration } from '../lib/migration-emit';
|
|
22
14
|
import {
|
|
23
15
|
type CliErrorConflict,
|
|
24
16
|
CliStructuredError,
|
|
@@ -178,7 +170,7 @@ async function executeMigrationPlanCommand(
|
|
|
178
170
|
return notOk(
|
|
179
171
|
errorRuntime('A draft migration to this contract already exists', {
|
|
180
172
|
why: `Draft migration at "${existingDraft.dirName}" already targets ${toStorageHash}`,
|
|
181
|
-
fix: `Run 'prisma-next migration
|
|
173
|
+
fix: `Run 'prisma-next migration emit --dir ${migrationsRelative}/${existingDraft.dirName}' to attest it, or delete it and re-plan.`,
|
|
182
174
|
}),
|
|
183
175
|
);
|
|
184
176
|
}
|
|
@@ -302,56 +294,22 @@ async function executeMigrationPlanCommand(
|
|
|
302
294
|
};
|
|
303
295
|
|
|
304
296
|
try {
|
|
305
|
-
// Always write migration.ts with the descriptors
|
|
306
|
-
// Write package with empty ops first (draft)
|
|
307
297
|
await writeMigrationPackage(packageDir, manifest, []);
|
|
308
298
|
await scaffoldMigrationTs(packageDir, {
|
|
309
299
|
descriptors: descriptorResult.descriptors,
|
|
310
300
|
contractJsonPath: contractPathAbsolute,
|
|
311
301
|
});
|
|
312
302
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
operations: descriptorResult.descriptors.map((d) => ({
|
|
322
|
-
id: (d as { kind: string }).kind,
|
|
323
|
-
label: (d as { kind: string }).kind,
|
|
324
|
-
operationClass: 'data' as const,
|
|
325
|
-
})),
|
|
326
|
-
sql: [],
|
|
327
|
-
summary: `Planned ${descriptorResult.descriptors.length} operation(s) — data migration required. Edit migration.ts and run \`migration verify --dir ${relative(process.cwd(), packageDir)}\` to attest.`,
|
|
328
|
-
timings: { total: Date.now() - startTime },
|
|
329
|
-
};
|
|
330
|
-
return ok(result);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// No data migration — evaluate, resolve, write ops, attest
|
|
334
|
-
const evaluatedDescriptors = await evaluateMigrationTs(packageDir);
|
|
335
|
-
|
|
336
|
-
if (!migrations.resolveDescriptors) {
|
|
337
|
-
throw errorTargetMigrationNotSupported({
|
|
338
|
-
why: `Target "${config.target.targetId}" does not implement resolveDescriptors; cannot finalize migration plan with migration.ts`,
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const resolvedOps = migrations.resolveDescriptors(
|
|
343
|
-
evaluatedDescriptors as OperationDescriptor[],
|
|
344
|
-
{
|
|
345
|
-
fromContract,
|
|
346
|
-
toContract: toContractJson,
|
|
347
|
-
frameworkComponents,
|
|
348
|
-
},
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
await writeMigrationOps(packageDir, resolvedOps);
|
|
352
|
-
const migrationId = await attestMigration(packageDir);
|
|
303
|
+
// Always run emit inline; structured errors thrown during evaluation
|
|
304
|
+
// (e.g. invalid migration.ts shape, missing file) propagate through
|
|
305
|
+
// emitMigration to the CLI envelope.
|
|
306
|
+
const { operations, migrationId } = await emitMigration(packageDir, {
|
|
307
|
+
targetId: config.target.targetId,
|
|
308
|
+
migrations,
|
|
309
|
+
frameworkComponents,
|
|
310
|
+
});
|
|
353
311
|
|
|
354
|
-
const sql = extractSqlDdl(
|
|
312
|
+
const sql = extractSqlDdl(operations);
|
|
355
313
|
const result: MigrationPlanResult = {
|
|
356
314
|
ok: true,
|
|
357
315
|
noOp: false,
|
|
@@ -359,13 +317,13 @@ async function executeMigrationPlanCommand(
|
|
|
359
317
|
to: toStorageHash,
|
|
360
318
|
migrationId,
|
|
361
319
|
dir: relative(process.cwd(), packageDir),
|
|
362
|
-
operations:
|
|
320
|
+
operations: operations.map((op) => ({
|
|
363
321
|
id: op.id,
|
|
364
322
|
label: op.label,
|
|
365
323
|
operationClass: op.operationClass,
|
|
366
324
|
})),
|
|
367
325
|
sql,
|
|
368
|
-
summary: `Planned ${
|
|
326
|
+
summary: `Planned ${operations.length} operation(s)`,
|
|
369
327
|
timings: { total: Date.now() - startTime },
|
|
370
328
|
};
|
|
371
329
|
return ok(result);
|
|
@@ -137,7 +137,7 @@ async function executeMigrationShowCommand(
|
|
|
137
137
|
return notOk(
|
|
138
138
|
errorRuntime('No attested migrations found', {
|
|
139
139
|
why: `All migrations in ${migrationsRelative} are drafts (migrationId: null)`,
|
|
140
|
-
fix: 'Run `prisma-next migration
|
|
140
|
+
fix: 'Run `prisma-next migration emit --dir <path>` to attest a draft migration.',
|
|
141
141
|
}),
|
|
142
142
|
);
|
|
143
143
|
}
|
|
@@ -460,7 +460,7 @@ async function executeMigrationStatusCommand(
|
|
|
460
460
|
severity: 'warn',
|
|
461
461
|
message: `${drafts.length} draft migration(s) found: ${drafts.map((d) => d.dirName).join(', ')}`,
|
|
462
462
|
hints: [
|
|
463
|
-
"Run 'prisma-next migration
|
|
463
|
+
"Run 'prisma-next migration emit --dir <path>' to attest draft migrations before applying",
|
|
464
464
|
],
|
|
465
465
|
});
|
|
466
466
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for emitting `ops.json` from a migration package's
|
|
3
|
+
* `migration.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Two flows are dispatched here:
|
|
6
|
+
* - Descriptor flow (Postgres): the framework evaluates `migration.ts` (which
|
|
7
|
+
* re-exports the planner's descriptor list), calls the target's
|
|
8
|
+
* `resolveDescriptors` to produce display-oriented operations, and writes
|
|
9
|
+
* `ops.json` + `manifest.json`.
|
|
10
|
+
* - Class flow (Mongo): the target owns the source-loading and ops
|
|
11
|
+
* serialization step via its `emit` capability. The capability
|
|
12
|
+
* dynamic-imports `migration.ts`, invokes its class to produce
|
|
13
|
+
* operations, and calls `writeMigrationOps`. The framework helper
|
|
14
|
+
* then attests the package (single source of truth for
|
|
15
|
+
* `migrationId`).
|
|
16
|
+
*
|
|
17
|
+
* Used by `migration emit` (always) and `migration plan` (always, after
|
|
18
|
+
* scaffolding `migration.ts`). Both flows run in-process so that structured
|
|
19
|
+
* errors thrown during evaluation propagate as real exceptions and the
|
|
20
|
+
* CLI's error envelope renders them with full structured metadata.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import assert from 'node:assert/strict';
|
|
24
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
25
|
+
import type {
|
|
26
|
+
MigrationPlanOperation,
|
|
27
|
+
OperationDescriptor,
|
|
28
|
+
TargetMigrationsCapability,
|
|
29
|
+
} from '@prisma-next/framework-components/control';
|
|
30
|
+
import { attestMigration } from '@prisma-next/migration-tools/attestation';
|
|
31
|
+
import { readMigrationPackage, writeMigrationOps } from '@prisma-next/migration-tools/io';
|
|
32
|
+
import { evaluateMigrationTs, hasMigrationTs } from '@prisma-next/migration-tools/migration-ts';
|
|
33
|
+
import { errorMigrationFileMissing, errorTargetMigrationNotSupported } from '../utils/cli-errors';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Context passed to `emitMigration`. Captures everything the helper needs to
|
|
37
|
+
* dispatch to the right flow without re-loading the config.
|
|
38
|
+
*/
|
|
39
|
+
export interface EmitMigrationContext {
|
|
40
|
+
readonly targetId: string;
|
|
41
|
+
readonly migrations: TargetMigrationsCapability;
|
|
42
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Result of a successful emit: the operations that were written to `ops.json`
|
|
47
|
+
* (display-oriented shape) and the content-addressed migrationId persisted to
|
|
48
|
+
* `manifest.json`.
|
|
49
|
+
*/
|
|
50
|
+
export interface EmitMigrationResult {
|
|
51
|
+
readonly operations: readonly MigrationPlanOperation[];
|
|
52
|
+
readonly migrationId: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Emit `ops.json` and attest `migrationId` for the migration package at `dir`.
|
|
57
|
+
*
|
|
58
|
+
* Dispatches to descriptor flow when the target implements `resolveDescriptors`,
|
|
59
|
+
* otherwise to the target's `emit` capability. Throws a structured error if
|
|
60
|
+
* `migration.ts` is missing or the target supports neither flow. Other
|
|
61
|
+
* structured errors thrown during evaluation propagate unchanged.
|
|
62
|
+
*/
|
|
63
|
+
export async function emitMigration(
|
|
64
|
+
dir: string,
|
|
65
|
+
ctx: EmitMigrationContext,
|
|
66
|
+
): Promise<EmitMigrationResult> {
|
|
67
|
+
if (!(await hasMigrationTs(dir))) {
|
|
68
|
+
throw errorMigrationFileMissing(dir);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (ctx.migrations.resolveDescriptors) {
|
|
72
|
+
return emitDescriptorFlow(dir, ctx.migrations, ctx);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (ctx.migrations.emit) {
|
|
76
|
+
const operations = await ctx.migrations.emit({
|
|
77
|
+
dir,
|
|
78
|
+
frameworkComponents: ctx.frameworkComponents,
|
|
79
|
+
});
|
|
80
|
+
const migrationId = await attestMigration(dir);
|
|
81
|
+
return { operations, migrationId };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
throw errorTargetMigrationNotSupported({
|
|
85
|
+
why: `Target "${ctx.targetId}" does not implement resolveDescriptors or emit; cannot emit a migration package`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Descriptor flow: evaluate `migration.ts` to obtain a list of operation
|
|
91
|
+
* descriptors, hand them to the target's `resolveDescriptors` along with the
|
|
92
|
+
* manifest's contract bookends, then persist `ops.json` and attest the package.
|
|
93
|
+
*/
|
|
94
|
+
async function emitDescriptorFlow(
|
|
95
|
+
dir: string,
|
|
96
|
+
migrations: TargetMigrationsCapability,
|
|
97
|
+
ctx: EmitMigrationContext,
|
|
98
|
+
): Promise<EmitMigrationResult> {
|
|
99
|
+
assert(
|
|
100
|
+
migrations.resolveDescriptors,
|
|
101
|
+
'emitDescriptorFlow requires resolveDescriptors; gated by caller',
|
|
102
|
+
);
|
|
103
|
+
const pkg = await readMigrationPackage(dir);
|
|
104
|
+
const descriptors = await evaluateMigrationTs(dir);
|
|
105
|
+
const operations = migrations.resolveDescriptors(descriptors as OperationDescriptor[], {
|
|
106
|
+
fromContract: pkg.manifest.fromContract,
|
|
107
|
+
toContract: pkg.manifest.toContract,
|
|
108
|
+
frameworkComponents: ctx.frameworkComponents,
|
|
109
|
+
});
|
|
110
|
+
await writeMigrationOps(dir, operations);
|
|
111
|
+
const migrationId = await attestMigration(dir);
|
|
112
|
+
return { operations, migrationId };
|
|
113
|
+
}
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -30,3 +30,8 @@ export {
|
|
|
30
30
|
errorSchemaVerificationFailed,
|
|
31
31
|
errorTargetMismatch,
|
|
32
32
|
} from '@prisma-next/errors/execution';
|
|
33
|
+
export {
|
|
34
|
+
errorMigrationFileMissing,
|
|
35
|
+
errorMigrationInvalidDefaultExport,
|
|
36
|
+
errorMigrationPlanNotArray,
|
|
37
|
+
} from '@prisma-next/errors/migration';
|
|
@@ -137,7 +137,7 @@ function getCommandDocsUrl(commandPath: string): string | undefined {
|
|
|
137
137
|
'migration apply': 'https://pris.ly/migration-apply',
|
|
138
138
|
'migration show': 'https://pris.ly/migration-show',
|
|
139
139
|
'migration status': 'https://pris.ly/migration-status',
|
|
140
|
-
'migration
|
|
140
|
+
'migration emit': 'https://pris.ly/migration-emit',
|
|
141
141
|
};
|
|
142
142
|
return docsMap[commandPath];
|
|
143
143
|
}
|
|
@@ -136,9 +136,8 @@ export interface MigrationApplyCommandOutputResult {
|
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export interface
|
|
140
|
-
readonly
|
|
141
|
-
readonly migrationId?: string;
|
|
139
|
+
export interface MigrationEmitCommandOutputResult {
|
|
140
|
+
readonly migrationId: string;
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
export function formatMigrationApplyCommandOutput(
|
|
@@ -183,8 +182,8 @@ export function formatMigrationApplyCommandOutput(
|
|
|
183
182
|
return lines.join('\n');
|
|
184
183
|
}
|
|
185
184
|
|
|
186
|
-
export function
|
|
187
|
-
result:
|
|
185
|
+
export function formatMigrationEmitCommandOutput(
|
|
186
|
+
result: MigrationEmitCommandOutputResult,
|
|
188
187
|
flags: GlobalFlags,
|
|
189
188
|
): string {
|
|
190
189
|
if (flags.quiet) {
|
|
@@ -194,23 +193,10 @@ export function formatMigrationVerifyCommandOutput(
|
|
|
194
193
|
const lines: string[] = [];
|
|
195
194
|
const useColor = flags.color !== false;
|
|
196
195
|
const formatGreen = createColorFormatter(useColor, green);
|
|
197
|
-
const formatYellow = createColorFormatter(useColor, yellow);
|
|
198
196
|
const formatDimText = (text: string) => formatDim(useColor, text);
|
|
199
197
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
lines.push(`${formatGreen('✔')} Migration verified`);
|
|
203
|
-
if (result.migrationId) {
|
|
204
|
-
lines.push(formatDimText(` migrationId: ${result.migrationId}`));
|
|
205
|
-
}
|
|
206
|
-
break;
|
|
207
|
-
case 'attested':
|
|
208
|
-
lines.push(`${formatYellow('◉')} Draft migration attested`);
|
|
209
|
-
if (result.migrationId) {
|
|
210
|
-
lines.push(formatDimText(` migrationId: ${result.migrationId}`));
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
198
|
+
lines.push(`${formatGreen('✔')} Emitted ops.json and attested migration`);
|
|
199
|
+
lines.push(formatDimText(` migrationId: ${result.migrationId}`));
|
|
214
200
|
|
|
215
201
|
return lines.join('\n');
|
|
216
202
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { CliStructuredError, errorConfigValidation as errorConfigValidation$1, errorContractConfigMissing as errorContractConfigMissing$1, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFileNotFound, errorMigrationPlanningFailed, errorTargetMigrationNotSupported, errorUnexpected as errorUnexpected$1 } from "@prisma-next/errors/control";
|
|
2
|
-
import { ERROR_CODE_DESTRUCTIVE_CHANGES, errorDestructiveChanges, errorHashMismatch, errorMarkerMissing, errorRunnerFailed, errorRuntime as errorRuntime$1, errorTargetMismatch } from "@prisma-next/errors/execution";
|
|
3
|
-
|
|
4
|
-
export { errorUnexpected$1 as _, errorContractValidationFailed as a, errorDriverRequired as c, errorMarkerMissing as d, errorMigrationPlanningFailed as f, errorTargetMismatch as g, errorTargetMigrationNotSupported as h, errorContractConfigMissing$1 as i, errorFileNotFound as l, errorRuntime$1 as m, ERROR_CODE_DESTRUCTIVE_CHANGES as n, errorDatabaseConnectionRequired as o, errorRunnerFailed as p, errorConfigValidation$1 as r, errorDestructiveChanges as s, CliStructuredError as t, errorHashMismatch as u };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
2
|
-
|
|
3
|
-
//#region src/commands/migration-verify.d.ts
|
|
4
|
-
interface MigrationVerifyResult {
|
|
5
|
-
readonly ok: boolean;
|
|
6
|
-
readonly status: 'verified' | 'attested';
|
|
7
|
-
readonly dir: string;
|
|
8
|
-
readonly migrationId?: string;
|
|
9
|
-
readonly storedMigrationId?: string;
|
|
10
|
-
readonly computedMigrationId?: string;
|
|
11
|
-
readonly summary: string;
|
|
12
|
-
}
|
|
13
|
-
declare function createMigrationVerifyCommand(): Command;
|
|
14
|
-
//#endregion
|
|
15
|
-
export { MigrationVerifyResult, createMigrationVerifyCommand };
|
|
16
|
-
//# sourceMappingURL=migration-verify.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration-verify.d.mts","names":[],"sources":["../../src/commands/migration-verify.ts"],"sourcesContent":[],"mappings":";;;UAkCiB,qBAAA;;EAAA,SAAA,MAAA,EAAA,UAAqB,GAAA,UAAA;EAkHtB,SAAA,GAAA,EAAA,MAAA;;;;;;iBAAA,4BAAA,CAAA,GAAgC"}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { t as loadConfig } from "../config-loader-C4VXKl8f.mjs";
|
|
2
|
-
import { _ as errorUnexpected, h as errorTargetMigrationNotSupported, m as errorRuntime, t as CliStructuredError } from "../cli-errors-BDCYR5ap.mjs";
|
|
3
|
-
import { t as assertFrameworkComponentsCompatible } from "../framework-components-BAsliT4V.mjs";
|
|
4
|
-
import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, r as getTargetMigrations, t as handleResult, u as setCommandDescriptions } from "../result-handler-oK_vA-Fn.mjs";
|
|
5
|
-
import { t as TerminalUI } from "../terminal-ui-C5k88MmW.mjs";
|
|
6
|
-
import { o as formatMigrationVerifyCommandOutput } from "../migrations-DTZBYXm1.mjs";
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
import { notOk, ok } from "@prisma-next/utils/result";
|
|
9
|
-
import { ifDefined } from "@prisma-next/utils/defined";
|
|
10
|
-
import { readMigrationPackage, writeMigrationOps } from "@prisma-next/migration-tools/io";
|
|
11
|
-
import { MigrationToolsError } from "@prisma-next/migration-tools/types";
|
|
12
|
-
import { evaluateMigrationTs, hasMigrationTs } from "@prisma-next/migration-tools/migration-ts";
|
|
13
|
-
import { attestMigration, verifyMigration } from "@prisma-next/migration-tools/attestation";
|
|
14
|
-
|
|
15
|
-
//#region src/commands/migration-verify.ts
|
|
16
|
-
async function executeMigrationVerifyCommand(options, flags, ui) {
|
|
17
|
-
const dir = options.dir;
|
|
18
|
-
if (!flags.json && !flags.quiet) {
|
|
19
|
-
const header = formatStyledHeader({
|
|
20
|
-
command: "migration verify",
|
|
21
|
-
description: "Verify migration package integrity",
|
|
22
|
-
details: [{
|
|
23
|
-
label: "dir",
|
|
24
|
-
value: dir
|
|
25
|
-
}],
|
|
26
|
-
flags
|
|
27
|
-
});
|
|
28
|
-
ui.stderr(header);
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
if (await hasMigrationTs(dir)) {
|
|
32
|
-
const pkg = await readMigrationPackage(dir);
|
|
33
|
-
const descriptors = await evaluateMigrationTs(dir);
|
|
34
|
-
const config = await loadConfig(options.config);
|
|
35
|
-
const migrations = getTargetMigrations(config.target);
|
|
36
|
-
if (!migrations?.resolveDescriptors) throw errorTargetMigrationNotSupported({ why: `Target "${config.target.targetId}" does not implement resolveDescriptors; cannot verify a migration package that uses migration.ts` });
|
|
37
|
-
const frameworkComponents = assertFrameworkComponentsCompatible(config.family.familyId, config.target.targetId, [
|
|
38
|
-
config.target,
|
|
39
|
-
config.adapter,
|
|
40
|
-
...config.extensionPacks ?? []
|
|
41
|
-
]);
|
|
42
|
-
await writeMigrationOps(dir, migrations.resolveDescriptors(descriptors, {
|
|
43
|
-
fromContract: pkg.manifest.fromContract,
|
|
44
|
-
toContract: pkg.manifest.toContract,
|
|
45
|
-
frameworkComponents
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
const result = await verifyMigration(dir);
|
|
49
|
-
if (result.ok) return ok({
|
|
50
|
-
ok: true,
|
|
51
|
-
status: "verified",
|
|
52
|
-
dir,
|
|
53
|
-
...ifDefined("migrationId", result.storedMigrationId),
|
|
54
|
-
...ifDefined("storedMigrationId", result.storedMigrationId),
|
|
55
|
-
...ifDefined("computedMigrationId", result.computedMigrationId),
|
|
56
|
-
summary: "Migration package verified — migrationId matches"
|
|
57
|
-
});
|
|
58
|
-
if (result.reason === "draft") {
|
|
59
|
-
const migrationId$1 = await attestMigration(dir);
|
|
60
|
-
return ok({
|
|
61
|
-
ok: true,
|
|
62
|
-
status: "attested",
|
|
63
|
-
dir,
|
|
64
|
-
migrationId: migrationId$1,
|
|
65
|
-
summary: `Draft migration attested with migrationId: ${migrationId$1}`
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
const migrationId = await attestMigration(dir);
|
|
69
|
-
return ok({
|
|
70
|
-
ok: true,
|
|
71
|
-
status: "attested",
|
|
72
|
-
dir,
|
|
73
|
-
migrationId,
|
|
74
|
-
summary: `Migration re-attested with migrationId: ${migrationId}`
|
|
75
|
-
});
|
|
76
|
-
} catch (error) {
|
|
77
|
-
if (CliStructuredError.is(error)) return notOk(error);
|
|
78
|
-
if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
|
|
79
|
-
why: error.why,
|
|
80
|
-
fix: error.fix,
|
|
81
|
-
meta: {
|
|
82
|
-
code: error.code,
|
|
83
|
-
...error.details ?? {}
|
|
84
|
-
}
|
|
85
|
-
}));
|
|
86
|
-
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to verify migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function createMigrationVerifyCommand() {
|
|
90
|
-
const command = new Command("verify");
|
|
91
|
-
setCommandDescriptions(command, "Verify a migration package migrationId", "Recomputes the content-addressed migrationId for a migration package and compares\nit against the stored value. Draft migrations (migrationId: null) are automatically\nattested. If migration.ts exists, it is always re-evaluated and ops.json is refreshed.");
|
|
92
|
-
setCommandExamples(command, ["prisma-next migration verify --dir migrations/20250101-add-users"]);
|
|
93
|
-
addGlobalOptions(command).requiredOption("--dir <path>", "Path to the migration package directory").option("--config <path>", "Path to prisma-next.config.ts (required when migration.ts exists)").action(async (options) => {
|
|
94
|
-
const flags = parseGlobalFlags(options);
|
|
95
|
-
const ui = new TerminalUI({
|
|
96
|
-
color: flags.color,
|
|
97
|
-
interactive: flags.interactive
|
|
98
|
-
});
|
|
99
|
-
const exitCode = handleResult(await executeMigrationVerifyCommand(options, flags, ui), flags, ui, (verifyResult) => {
|
|
100
|
-
if (flags.json) ui.output(JSON.stringify(verifyResult, null, 2));
|
|
101
|
-
else if (!flags.quiet) ui.log(formatMigrationVerifyCommandOutput(verifyResult, flags));
|
|
102
|
-
});
|
|
103
|
-
process.exit(exitCode);
|
|
104
|
-
});
|
|
105
|
-
return command;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
//#endregion
|
|
109
|
-
export { createMigrationVerifyCommand };
|
|
110
|
-
//# sourceMappingURL=migration-verify.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration-verify.mjs","names":["migrationId"],"sources":["../../src/commands/migration-verify.ts"],"sourcesContent":["import type { OperationDescriptor } from '@prisma-next/framework-components/control';\nimport { attestMigration, verifyMigration } from '@prisma-next/migration-tools/attestation';\nimport { readMigrationPackage, writeMigrationOps } from '@prisma-next/migration-tools/io';\nimport { evaluateMigrationTs, hasMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n CliStructuredError,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationVerifyCommandOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationVerifyOptions extends CommonCommandOptions {\n readonly dir: string;\n readonly config?: string;\n}\n\nexport interface MigrationVerifyResult {\n readonly ok: boolean;\n readonly status: 'verified' | 'attested';\n readonly dir: string;\n readonly migrationId?: string;\n readonly storedMigrationId?: string;\n readonly computedMigrationId?: string;\n readonly summary: string;\n}\n\nasync function executeMigrationVerifyCommand(\n options: MigrationVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationVerifyResult, CliStructuredError>> {\n const dir = options.dir;\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration verify',\n description: 'Verify migration package integrity',\n details: [{ label: 'dir', value: dir }],\n flags,\n });\n ui.stderr(header);\n }\n\n try {\n // If migration.ts exists, always evaluate and resolve to ops.json.\n // This ensures ops.json is always fresh relative to migration.ts.\n if (await hasMigrationTs(dir)) {\n const pkg = await readMigrationPackage(dir);\n const descriptors = await evaluateMigrationTs(dir);\n\n const config = await loadConfig(options.config);\n const migrations = getTargetMigrations(config.target);\n if (!migrations?.resolveDescriptors) {\n throw errorTargetMigrationNotSupported({\n why: `Target \"${config.target.targetId}\" does not implement resolveDescriptors; cannot verify a migration package that uses migration.ts`,\n });\n }\n\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n\n const resolvedOps = migrations.resolveDescriptors(descriptors as OperationDescriptor[], {\n fromContract: pkg.manifest.fromContract,\n toContract: pkg.manifest.toContract,\n frameworkComponents,\n });\n\n await writeMigrationOps(dir, resolvedOps);\n }\n\n // Now verify/attest with the (potentially updated) ops.json\n const result = await verifyMigration(dir);\n\n if (result.ok) {\n return ok({\n ok: true,\n status: 'verified',\n dir,\n ...ifDefined('migrationId', result.storedMigrationId),\n ...ifDefined('storedMigrationId', result.storedMigrationId),\n ...ifDefined('computedMigrationId', result.computedMigrationId),\n summary: 'Migration package verified — migrationId matches',\n });\n }\n\n if (result.reason === 'draft') {\n const migrationId = await attestMigration(dir);\n return ok({\n ok: true,\n status: 'attested',\n dir,\n migrationId,\n summary: `Draft migration attested with migrationId: ${migrationId}`,\n });\n }\n\n // Mismatch — ops.json was just rewritten by migration.ts evaluation above,\n // so this means the stored migrationId is stale. Re-attest.\n const migrationId = await attestMigration(dir);\n return ok({\n ok: true,\n status: 'attested',\n dir,\n migrationId,\n summary: `Migration re-attested with migrationId: ${migrationId}`,\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nexport function createMigrationVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Verify a migration package migrationId',\n 'Recomputes the content-addressed migrationId for a migration package and compares\\n' +\n 'it against the stored value. Draft migrations (migrationId: null) are automatically\\n' +\n 'attested. If migration.ts exists, it is always re-evaluated and ops.json is refreshed.',\n );\n setCommandExamples(command, ['prisma-next migration verify --dir migrations/20250101-add-users']);\n addGlobalOptions(command)\n .requiredOption('--dir <path>', 'Path to the migration package directory')\n .option('--config <path>', 'Path to prisma-next.config.ts (required when migration.ts exists)')\n .action(async (options: MigrationVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationVerifyCommand(options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (verifyResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(verifyResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationVerifyCommandOutput(verifyResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|