@prisma-next/cli 0.8.0-dev.6 → 0.8.0-dev.8
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 +7 -8
- package/dist/{cli-errors-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
- package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
- package/dist/cli.mjs +66 -18
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-4d26awB-.mjs → client-XkUw4xD0.mjs} +10 -9
- package/dist/client-XkUw4xD0.mjs.map +1 -0
- package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
- package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +7 -7
- package/dist/commands/db-schema.mjs +5 -5
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +67 -25
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +37 -9
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +28 -0
- package/dist/commands/migrate.d.mts.map +1 -0
- package/dist/commands/{migration-apply.mjs → migrate.mjs} +54 -36
- package/dist/commands/migrate.mjs.map +1 -0
- package/dist/commands/migration-check.d.mts +18 -0
- package/dist/commands/migration-check.d.mts.map +1 -0
- package/dist/commands/migration-check.mjs +284 -0
- package/dist/commands/migration-check.mjs.map +1 -0
- package/dist/commands/migration-graph.d.mts +16 -0
- package/dist/commands/migration-graph.d.mts.map +1 -0
- package/dist/commands/migration-graph.mjs +141 -0
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +20 -0
- package/dist/commands/migration-list.d.mts.map +1 -0
- package/dist/commands/migration-list.mjs +107 -0
- package/dist/commands/migration-list.mjs.map +1 -0
- package/dist/commands/migration-log.d.mts +21 -0
- package/dist/commands/migration-log.d.mts.map +1 -0
- package/dist/commands/migration-log.mjs +146 -0
- package/dist/commands/migration-log.mjs.map +1 -0
- package/dist/commands/migration-new.mjs +5 -5
- package/dist/commands/migration-plan.d.mts +2 -2
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +85 -47
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +3 -15
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +732 -1
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/ref.d.mts +34 -0
- package/dist/commands/ref.d.mts.map +1 -0
- package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
- package/dist/commands/ref.mjs.map +1 -0
- package/dist/{contract-emit-DLc5GYbr.mjs → contract-emit-CgoFk9AU.mjs} +3 -3
- package/dist/{contract-emit-DLc5GYbr.mjs.map → contract-emit-CgoFk9AU.mjs.map} +1 -1
- package/dist/{contract-emit-BhKR-D9Y.mjs → contract-emit-GpxW5RLe.mjs} +6 -6
- package/dist/{contract-emit-BhKR-D9Y.mjs.map → contract-emit-GpxW5RLe.mjs.map} +1 -1
- package/dist/{contract-infer-Bnla2kuK.mjs → contract-infer-D8edZOCi.mjs} +5 -5
- package/dist/{contract-infer-Bnla2kuK.mjs.map → contract-infer-D8edZOCi.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-D68YpuPR.mjs} +3 -3
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-D68YpuPR.mjs.map} +1 -1
- package/dist/{db-verify-DitNxDiE.mjs → db-verify-DtRB9iHJ.mjs} +7 -7
- package/dist/{db-verify-DitNxDiE.mjs.map → db-verify-DtRB9iHJ.mjs.map} +1 -1
- package/dist/errors-Cw6kyTyV.mjs +56 -0
- package/dist/errors-Cw6kyTyV.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
- package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
- package/dist/{migration-status-Do4Ei0i_.mjs → graph-render-eJDcLWny.mjs} +3 -692
- package/dist/graph-render-eJDcLWny.mjs.map +1 -0
- package/dist/{init-Wt3xjWgX.mjs → init-e5Q4s1_5.mjs} +7 -6
- package/dist/{init-Wt3xjWgX.mjs.map → init-e5Q4s1_5.mjs.map} +1 -1
- package/dist/{inspect-live-schema-CyzAzPzF.mjs → inspect-live-schema-CPPqCips.mjs} +4 -4
- package/dist/{inspect-live-schema-CyzAzPzF.mjs.map → inspect-live-schema-CPPqCips.mjs.map} +1 -1
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-Jp1rosw8.mjs → migration-command-scaffold-B_ezTTwX.mjs} +4 -4
- package/dist/{migration-command-scaffold-Jp1rosw8.mjs.map → migration-command-scaffold-B_ezTTwX.mjs.map} +1 -1
- package/dist/{migration-plan-DTwYi61q.mjs → migration-plan-DWB-NTxH.mjs} +26 -24
- package/dist/migration-plan-DWB-NTxH.mjs.map +1 -0
- package/dist/migration-types-D2FW63pr.d.mts +15 -0
- package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
- package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
- package/dist/migrations-DyUf5lTt.mjs.map +1 -0
- package/dist/{output-DEg3SSnJ.mjs → output-B60Gw5fu.mjs} +1 -1
- package/dist/{output-DEg3SSnJ.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
- package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
- package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
- package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
- package/dist/{types-LItU7E4l.d.mts → types-BS_wpjAY.d.mts} +2 -2
- package/dist/{types-LItU7E4l.d.mts.map → types-BS_wpjAY.d.mts.map} +1 -1
- package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
- package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
- package/package.json +39 -23
- package/src/cli.ts +78 -15
- package/src/commands/db-sign.ts +102 -32
- package/src/commands/db-update.ts +56 -4
- package/src/commands/{migration-apply.ts → migrate.ts} +54 -70
- package/src/commands/migration-check/exit-codes.ts +3 -0
- package/src/commands/migration-check.ts +369 -0
- package/src/commands/migration-graph.ts +184 -0
- package/src/commands/migration-list.ts +155 -0
- package/src/commands/migration-log.ts +218 -0
- package/src/commands/migration-plan.ts +29 -22
- package/src/commands/migration-show.ts +132 -60
- package/src/commands/migration-status.ts +77 -64
- package/src/commands/{migration-ref.ts → ref.ts} +32 -86
- package/src/control-api/operations/apply-aggregate.ts +4 -4
- package/src/control-api/operations/db-apply-aggregate.ts +3 -2
- package/src/control-api/operations/migration-apply.ts +4 -3
- package/src/migration-cli.ts +1 -1
- package/src/utils/cli-errors.ts +37 -0
- package/src/utils/command-helpers.ts +28 -3
- package/src/utils/contract-space-aggregate-loader.ts +2 -2
- package/src/utils/contract-space-seed-phase.ts +1 -1
- package/src/utils/formatters/help.ts +12 -2
- package/src/utils/formatters/migrations.ts +2 -2
- package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
- package/dist/client-4d26awB-.mjs.map +0 -1
- package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
- package/dist/commands/migration-apply.d.mts +0 -51
- package/dist/commands/migration-apply.d.mts.map +0 -1
- package/dist/commands/migration-apply.mjs.map +0 -1
- package/dist/commands/migration-ref.d.mts +0 -45
- package/dist/commands/migration-ref.d.mts.map +0 -1
- package/dist/commands/migration-ref.mjs.map +0 -1
- package/dist/migration-plan-DTwYi61q.mjs.map +0 -1
- package/dist/migration-status-Do4Ei0i_.mjs.map +0 -1
- package/dist/migrations-CTsyBXCA.mjs.map +0 -1
- package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
- /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
2
|
+
import { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';
|
|
2
3
|
import type { RefEntry } from '@prisma-next/migration-tools/refs';
|
|
3
4
|
import {
|
|
4
5
|
deleteRef,
|
|
5
|
-
readRef,
|
|
6
6
|
readRefs,
|
|
7
7
|
validateRefName,
|
|
8
8
|
validateRefValue,
|
|
@@ -16,9 +16,11 @@ import {
|
|
|
16
16
|
errorRuntime,
|
|
17
17
|
errorUnexpected,
|
|
18
18
|
mapMigrationToolsError,
|
|
19
|
+
mapRefResolutionError,
|
|
19
20
|
} from '../utils/cli-errors';
|
|
20
21
|
import {
|
|
21
22
|
addGlobalOptions,
|
|
23
|
+
loadMigrationPackages,
|
|
22
24
|
resolveMigrationPaths,
|
|
23
25
|
setCommandDescriptions,
|
|
24
26
|
} from '../utils/command-helpers';
|
|
@@ -34,13 +36,6 @@ interface RefSetResult {
|
|
|
34
36
|
readonly invariants: readonly string[];
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
interface RefGetResult {
|
|
38
|
-
readonly ok: true;
|
|
39
|
-
readonly ref: string;
|
|
40
|
-
readonly hash: string;
|
|
41
|
-
readonly invariants: readonly string[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
39
|
interface RefDeleteResult {
|
|
45
40
|
readonly ok: true;
|
|
46
41
|
readonly ref: string;
|
|
@@ -66,53 +61,42 @@ function cliErrorInvalidRefName(name: string): CliStructuredError {
|
|
|
66
61
|
});
|
|
67
62
|
}
|
|
68
63
|
|
|
69
|
-
function
|
|
70
|
-
return errorRuntime(`Invalid contract hash "${hash}"`, {
|
|
71
|
-
why: `"${hash}" is not a valid contract hash`,
|
|
72
|
-
fix: 'Contract hashes must match the format "sha256:<64 hex chars>". Copy the hash from `prisma-next contract emit` or `migration status --json`.',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function executeRefSetCommand(
|
|
64
|
+
export async function executeRefSetCommand(
|
|
77
65
|
name: string,
|
|
78
|
-
|
|
66
|
+
contractInput: string,
|
|
79
67
|
options: { config?: string },
|
|
80
68
|
): Promise<Result<RefSetResult, CliStructuredError>> {
|
|
81
69
|
if (!validateRefName(name)) {
|
|
82
70
|
return notOk(cliErrorInvalidRefName(name));
|
|
83
71
|
}
|
|
84
|
-
if (!validateRefValue(hash)) {
|
|
85
|
-
return notOk(cliErrorInvalidRefValue(hash));
|
|
86
|
-
}
|
|
87
72
|
|
|
88
73
|
try {
|
|
89
74
|
const config = await loadConfig(options.config);
|
|
90
|
-
const { refsDir } = resolveMigrationPaths(options.config, config);
|
|
91
|
-
|
|
75
|
+
const { appMigrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
|
|
76
|
+
|
|
77
|
+
let resolvedHash: string;
|
|
78
|
+
if (validateRefValue(contractInput)) {
|
|
79
|
+
resolvedHash = contractInput;
|
|
80
|
+
} else {
|
|
81
|
+
const { graph } = await loadMigrationPackages(appMigrationsDir);
|
|
82
|
+
const refs = await readRefs(refsDir);
|
|
83
|
+
const refResult = parseContractRef(contractInput, { graph, refs });
|
|
84
|
+
if (!refResult.ok) {
|
|
85
|
+
return notOk(mapRefResolutionError(refResult.failure));
|
|
86
|
+
}
|
|
87
|
+
resolvedHash = refResult.value.hash;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const entry: RefEntry = { hash: resolvedHash, invariants: [] };
|
|
92
91
|
await writeRef(refsDir, name, entry);
|
|
93
|
-
return ok({ ok: true as const, ref: name, hash, invariants: [] });
|
|
94
|
-
} catch (error) {
|
|
95
|
-
if (error instanceof CliStructuredError) return notOk(error);
|
|
96
|
-
return notOk(mapError(error));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function executeRefGetCommand(
|
|
101
|
-
name: string,
|
|
102
|
-
options: { config?: string },
|
|
103
|
-
): Promise<Result<RefGetResult, CliStructuredError>> {
|
|
104
|
-
try {
|
|
105
|
-
const config = await loadConfig(options.config);
|
|
106
|
-
const { refsDir } = resolveMigrationPaths(options.config, config);
|
|
107
|
-
const entry = await readRef(refsDir, name);
|
|
108
|
-
return ok({ ok: true as const, ref: name, hash: entry.hash, invariants: entry.invariants });
|
|
92
|
+
return ok({ ok: true as const, ref: name, hash: resolvedHash, invariants: [] });
|
|
109
93
|
} catch (error) {
|
|
110
94
|
if (error instanceof CliStructuredError) return notOk(error);
|
|
111
95
|
return notOk(mapError(error));
|
|
112
96
|
}
|
|
113
97
|
}
|
|
114
98
|
|
|
115
|
-
async function executeRefDeleteCommand(
|
|
99
|
+
export async function executeRefDeleteCommand(
|
|
116
100
|
name: string,
|
|
117
101
|
options: { config?: string },
|
|
118
102
|
): Promise<Result<RefDeleteResult, CliStructuredError>> {
|
|
@@ -127,7 +111,7 @@ async function executeRefDeleteCommand(
|
|
|
127
111
|
}
|
|
128
112
|
}
|
|
129
113
|
|
|
130
|
-
async function executeRefListCommand(options: {
|
|
114
|
+
export async function executeRefListCommand(options: {
|
|
131
115
|
config?: string;
|
|
132
116
|
}): Promise<Result<RefListResult, CliStructuredError>> {
|
|
133
117
|
try {
|
|
@@ -145,12 +129,15 @@ function createRefSetCommand(): Command {
|
|
|
145
129
|
const command = new Command('set');
|
|
146
130
|
setCommandDescriptions(
|
|
147
131
|
command,
|
|
148
|
-
'Set a ref to a contract
|
|
149
|
-
'Sets a named ref to point to a contract hash in migrations/refs/.',
|
|
132
|
+
'Set a ref to a contract reference',
|
|
133
|
+
'Sets a named ref to point to a resolved contract reference (hash, alias, or path) in migrations/refs/.',
|
|
150
134
|
);
|
|
151
135
|
addGlobalOptions(command)
|
|
152
136
|
.argument('<name>', 'Ref name (e.g., staging, production)')
|
|
153
|
-
.argument(
|
|
137
|
+
.argument(
|
|
138
|
+
'<contract>',
|
|
139
|
+
'Contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
|
|
140
|
+
)
|
|
154
141
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
155
142
|
.action(
|
|
156
143
|
async (
|
|
@@ -174,37 +161,6 @@ function createRefSetCommand(): Command {
|
|
|
174
161
|
return command;
|
|
175
162
|
}
|
|
176
163
|
|
|
177
|
-
function createRefGetCommand(): Command {
|
|
178
|
-
const command = new Command('get');
|
|
179
|
-
setCommandDescriptions(
|
|
180
|
-
command,
|
|
181
|
-
'Get the hash for a ref',
|
|
182
|
-
'Reads a named ref from migrations/refs/ and prints its contract hash.',
|
|
183
|
-
);
|
|
184
|
-
addGlobalOptions(command)
|
|
185
|
-
.argument('<name>', 'Ref name to look up')
|
|
186
|
-
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
187
|
-
.action(
|
|
188
|
-
async (
|
|
189
|
-
name: string,
|
|
190
|
-
options: { config?: string; json?: string | boolean; quiet?: boolean },
|
|
191
|
-
) => {
|
|
192
|
-
const flags = parseGlobalFlags(options);
|
|
193
|
-
const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
|
|
194
|
-
const result = await executeRefGetCommand(name, options);
|
|
195
|
-
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
196
|
-
if (flags.json) {
|
|
197
|
-
ui.output(JSON.stringify(value));
|
|
198
|
-
} else {
|
|
199
|
-
ui.output(value.hash);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
process.exit(exitCode);
|
|
203
|
-
},
|
|
204
|
-
);
|
|
205
|
-
return command;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
164
|
function createRefDeleteCommand(): Command {
|
|
209
165
|
const command = new Command('delete');
|
|
210
166
|
setCommandDescriptions(command, 'Delete a ref', 'Removes a named ref from migrations/refs/.');
|
|
@@ -262,20 +218,11 @@ function createRefListCommand(): Command {
|
|
|
262
218
|
return command;
|
|
263
219
|
}
|
|
264
220
|
|
|
265
|
-
export {
|
|
266
|
-
cliErrorInvalidRefName,
|
|
267
|
-
cliErrorInvalidRefValue,
|
|
268
|
-
executeRefDeleteCommand,
|
|
269
|
-
executeRefGetCommand,
|
|
270
|
-
executeRefListCommand,
|
|
271
|
-
executeRefSetCommand,
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
export function createMigrationRefCommand(): Command {
|
|
221
|
+
export function createRefCommand(): Command {
|
|
275
222
|
const command = new Command('ref');
|
|
276
223
|
setCommandDescriptions(
|
|
277
224
|
command,
|
|
278
|
-
'Manage
|
|
225
|
+
'Manage contract refs',
|
|
279
226
|
'Manage named refs in migrations/refs/. Refs map logical environment\n' +
|
|
280
227
|
'names (e.g., staging, production) to contract hashes.',
|
|
281
228
|
);
|
|
@@ -284,7 +231,6 @@ export function createMigrationRefCommand(): Command {
|
|
|
284
231
|
subcommandDescription: () => '',
|
|
285
232
|
});
|
|
286
233
|
command.addCommand(createRefSetCommand());
|
|
287
|
-
command.addCommand(createRefGetCommand());
|
|
288
234
|
command.addCommand(createRefDeleteCommand());
|
|
289
235
|
command.addCommand(createRefListCommand());
|
|
290
236
|
return command;
|
|
@@ -49,7 +49,7 @@ export interface ApplyAggregateInputs<TFamilyId extends string, TTargetId extend
|
|
|
49
49
|
* Per-space plans, keyed by `spaceId`. Produced by either the full
|
|
50
50
|
* {@link planAggregate} pipeline (`db init` / `db update` — synth
|
|
51
51
|
* for the app, graph-walk for extensions) or by direct
|
|
52
|
-
* {@link graphWalkStrategy} calls (`
|
|
52
|
+
* {@link graphWalkStrategy} calls (`migrate` — graph-walk
|
|
53
53
|
* for every member). Either way, the runner consumes the same shape.
|
|
54
54
|
*/
|
|
55
55
|
readonly perSpacePlans: ReadonlyMap<string, AggregatePerSpacePlan>;
|
|
@@ -100,7 +100,7 @@ export type ApplyAggregateResult = Result<ApplyAggregateValue, AggregateApplyRun
|
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Runner-driving tail shared by every aggregate apply caller — `db init`,
|
|
103
|
-
* `db update`, and `
|
|
103
|
+
* `db update`, and `migrate`. Consumes already-resolved per-space
|
|
104
104
|
* plans (the planner-vs-replay distinction is owned by the caller) and
|
|
105
105
|
* dispatches them to the multi-space runner in canonical order.
|
|
106
106
|
*
|
|
@@ -264,7 +264,7 @@ export function collectOrdered(
|
|
|
264
264
|
/**
|
|
265
265
|
* Action-appropriate label for the `spanStart` event the apply
|
|
266
266
|
* primitive emits. `applyAggregate` is shared by `db init`, `db update`,
|
|
267
|
-
* and `
|
|
267
|
+
* and `migrate`; the span label tracks the user-visible action
|
|
268
268
|
* so structured-progress output reads naturally for each surface.
|
|
269
269
|
*/
|
|
270
270
|
export function progressLabelForAction(action: AggregateApplyAction): string {
|
|
@@ -285,6 +285,6 @@ function labelForAction(action: AggregateApplyAction): string {
|
|
|
285
285
|
case 'dbUpdate':
|
|
286
286
|
return 'db update';
|
|
287
287
|
case 'migrationApply':
|
|
288
|
-
return '
|
|
288
|
+
return 'migrate';
|
|
289
289
|
}
|
|
290
290
|
}
|
|
@@ -207,9 +207,10 @@ export async function executeAggregateApply<TFamilyId extends string, TTargetId
|
|
|
207
207
|
|
|
208
208
|
// 5. Apply mode: hand off to the shared `applyAggregate` primitive.
|
|
209
209
|
// The runner-driving tail is identical for `db init` / `db update` /
|
|
210
|
-
// `
|
|
210
|
+
// `migrate` — only how each caller produces `perSpacePlans`
|
|
211
211
|
// differs (synth + graph-walk via planAggregate here; graph-walk
|
|
212
|
-
// only for
|
|
212
|
+
// only for migrate). Each caller produces perSpacePlans differently;
|
|
213
|
+
// this helper handles the shared apply tail.
|
|
213
214
|
const applied = await applyAggregate({
|
|
214
215
|
aggregate,
|
|
215
216
|
perSpacePlans: planResult.value.perSpace,
|
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
import { applyAggregate, buildPerSpaceBreakdown } from './apply-aggregate';
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Inputs for the aggregate-walking `
|
|
37
|
+
* Inputs for the aggregate-walking `migrate` control-api
|
|
38
38
|
* operation.
|
|
39
39
|
*
|
|
40
40
|
* The CLI command resolves the descriptor surface (config, refs,
|
|
@@ -110,7 +110,8 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
|
|
|
110
110
|
* shared with `db init` / `db update`). Marker advancement is
|
|
111
111
|
* inside the per-space transaction.
|
|
112
112
|
*
|
|
113
|
-
*
|
|
113
|
+
* Encodes the replay-only contract: every contract space must have an
|
|
114
|
+
* authored migration graph on disk before this operation can advance it.
|
|
114
115
|
*/
|
|
115
116
|
export async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(
|
|
116
117
|
options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,
|
|
@@ -461,7 +462,7 @@ function buildNeverPlannedFailure(spaceId: string, targetHash: string): Migratio
|
|
|
461
462
|
return {
|
|
462
463
|
code: 'MIGRATION_PATH_NOT_FOUND',
|
|
463
464
|
summary: `No on-disk migrations for contract space "${spaceId}"`,
|
|
464
|
-
why: `
|
|
465
|
+
why: `migrate is replay-only: every contract space must have an authored migration graph on disk. Space "${spaceId}" has no migrations under \`migrations/${spaceId}/\` but its head ref targets "${targetHash}". Run \`prisma-next migration plan\` first to materialise the path.`,
|
|
465
466
|
meta: { spaceId, target: targetHash, kind: 'neverPlanned' },
|
|
466
467
|
};
|
|
467
468
|
}
|
package/src/migration-cli.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `node migration.ts` directly.
|
|
4
4
|
*
|
|
5
5
|
* Naming: this is *not* a "migration runner" in the apply-time sense. The
|
|
6
|
-
* apply-time runner is the thing `prisma-next
|
|
6
|
+
* apply-time runner is the thing `prisma-next migrate` uses to
|
|
7
7
|
* execute migration JSON ops against a database. `MigrationCLI` is the
|
|
8
8
|
* tiny CLI surface owned by an authored `migration.ts` file: parse the
|
|
9
9
|
* file's argv, load the project's `prisma-next.config.ts`, assemble a
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from '@prisma-next/errors/control';
|
|
26
26
|
import { errorRuntime } from '@prisma-next/errors/execution';
|
|
27
27
|
import type { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
28
|
+
import type { RefResolutionError } from '@prisma-next/migration-tools/ref-resolution';
|
|
28
29
|
|
|
29
30
|
export {
|
|
30
31
|
ERROR_CODE_DESTRUCTIVE_CHANGES,
|
|
@@ -85,3 +86,39 @@ export function mapMigrationToolsError(error: MigrationToolsError): CliStructure
|
|
|
85
86
|
meta: { code: error.code, ...(error.details ?? {}) },
|
|
86
87
|
});
|
|
87
88
|
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Maps a `RefResolutionError` from the contract/migration reference
|
|
92
|
+
* resolver into a CLI structured error envelope.
|
|
93
|
+
*/
|
|
94
|
+
export function mapRefResolutionError(error: RefResolutionError): CliStructuredError {
|
|
95
|
+
switch (error.kind) {
|
|
96
|
+
case 'not-found':
|
|
97
|
+
return errorRuntime(`Not a known ${error.grammar} reference: "${error.input}"`, {
|
|
98
|
+
why: `No ${error.grammar} matching "${error.input}" exists in the migration graph or refs index.`,
|
|
99
|
+
fix:
|
|
100
|
+
error.grammar === 'contract'
|
|
101
|
+
? 'Provide a valid contract hash, ref name, or migration directory name.'
|
|
102
|
+
: 'Provide a valid migration directory name or migration hash.',
|
|
103
|
+
meta: { input: error.input, grammar: error.grammar },
|
|
104
|
+
});
|
|
105
|
+
case 'ambiguous':
|
|
106
|
+
return errorRuntime(`Ambiguous ${error.grammar} reference: "${error.input}"`, {
|
|
107
|
+
why: `"${error.input}" matches multiple ${error.grammar}s: ${error.candidates.join(', ')}`,
|
|
108
|
+
fix: 'Provide a longer prefix or use the full hash to disambiguate.',
|
|
109
|
+
meta: { input: error.input, candidates: error.candidates, grammar: error.grammar },
|
|
110
|
+
});
|
|
111
|
+
case 'wrong-grammar':
|
|
112
|
+
return errorRuntime(error.message, {
|
|
113
|
+
why: error.message,
|
|
114
|
+
fix: error.fix,
|
|
115
|
+
meta: { input: error.input, expectedGrammar: error.expectedGrammar },
|
|
116
|
+
});
|
|
117
|
+
case 'invalid-format':
|
|
118
|
+
return errorRuntime(`Invalid reference format: "${error.input}"`, {
|
|
119
|
+
why: error.reason,
|
|
120
|
+
fix: 'Provide a valid contract hash, ref name, or migration directory name.',
|
|
121
|
+
meta: { input: error.input },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -17,6 +17,10 @@ import { parseGlobalFlags } from './global-flags';
|
|
|
17
17
|
|
|
18
18
|
const longDescriptions = new WeakMap<Command, string>();
|
|
19
19
|
const commandExamples = new WeakMap<Command, readonly string[]>();
|
|
20
|
+
const commandSeeAlso = new WeakMap<
|
|
21
|
+
Command,
|
|
22
|
+
readonly { readonly verb: string; readonly oneLiner: string }[]
|
|
23
|
+
>();
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Sets both short and long descriptions for a command.
|
|
@@ -57,6 +61,27 @@ export function getCommandExamples(command: Command): readonly string[] | undefi
|
|
|
57
61
|
return commandExamples.get(command);
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Sets cross-references to related commands, rendered in a "See also"
|
|
66
|
+
* section below the Examples block in help output.
|
|
67
|
+
*/
|
|
68
|
+
export function setCommandSeeAlso(
|
|
69
|
+
command: Command,
|
|
70
|
+
refs: readonly { readonly verb: string; readonly oneLiner: string }[],
|
|
71
|
+
): Command {
|
|
72
|
+
commandSeeAlso.set(command, refs);
|
|
73
|
+
return command;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Gets the see-also cross-references from a command.
|
|
78
|
+
*/
|
|
79
|
+
export function getCommandSeeAlso(
|
|
80
|
+
command: Command,
|
|
81
|
+
): readonly { readonly verb: string; readonly oneLiner: string }[] | undefined {
|
|
82
|
+
return commandSeeAlso.get(command);
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
/**
|
|
61
86
|
* Shared CLI options interface for migration commands (db init, db update).
|
|
62
87
|
* These are the Commander.js parsed options common to both commands.
|
|
@@ -79,13 +104,13 @@ export function resolveContractPath(config: { contract?: { output?: string } }):
|
|
|
79
104
|
|
|
80
105
|
/**
|
|
81
106
|
* Resolves the migrations directory and config path from CLI options.
|
|
82
|
-
* Shared by
|
|
107
|
+
* Shared by migrate, migration-plan, and migration-status.
|
|
83
108
|
*
|
|
84
109
|
* - `migrationsDir` is the project's top-level `migrations/` directory
|
|
85
110
|
* (the root that the aggregate loader walks for every contract space).
|
|
86
111
|
* - `appMigrationsDir` is the app subspace directory under it
|
|
87
112
|
* (`<migrationsDir>/<APP_SPACE_ID>/`). Every per-app reader / writer
|
|
88
|
-
* (`migration new`, `migration plan`, `
|
|
113
|
+
* (`migration new`, `migration plan`, `migrate`,
|
|
89
114
|
* `migration status`, `migration show`, `migration ref`) operates on
|
|
90
115
|
* this directory. Extensions own their own `migrations/<spaceId>/`.
|
|
91
116
|
* - `refsDir` is the app's refs directory (`<appMigrationsDir>/refs/`).
|
|
@@ -159,7 +184,7 @@ export function collectDeclaredInvariants(graph: MigrationGraph): ReadonlySet<st
|
|
|
159
184
|
/**
|
|
160
185
|
* Maps a `MigrationEdge` to the structural-edge shape used in the
|
|
161
186
|
* `MIGRATION.NO_INVARIANT_PATH` error envelope. Shared between
|
|
162
|
-
* `
|
|
187
|
+
* `migrate` and `migration status` so both commands surface
|
|
163
188
|
* the same JSON wire shape when an invariant-aware route is unsatisfiable.
|
|
164
189
|
*/
|
|
165
190
|
export function toStructuralEdge(edge: MigrationEdge): NoInvariantPathStructuralEdge {
|
|
@@ -128,7 +128,7 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
|
|
|
128
128
|
* `migrations/` graph is not walked — the planner uses the synth
|
|
129
129
|
* strategy for the app member instead).
|
|
130
130
|
*
|
|
131
|
-
* `
|
|
131
|
+
* `migrate` callers thread the user's authored app-space
|
|
132
132
|
* packages (loaded via `loadMigrationPackages(appMigrationsDir)`)
|
|
133
133
|
* through here so the graph-walk strategy can plot a path through
|
|
134
134
|
* them — the prod-time replay path explicitly forbids synth.
|
|
@@ -144,7 +144,7 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
|
|
|
144
144
|
* (defaulting to `[]`). `db init` / `db update` leave it empty: the
|
|
145
145
|
* planner's `synth` strategy is used for the app member (driven by
|
|
146
146
|
* `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`
|
|
147
|
-
* graph does not need to be walked. `
|
|
147
|
+
* graph does not need to be walked. `migrate` threads the
|
|
148
148
|
* already-loaded app-space packages through so the graph-walk strategy
|
|
149
149
|
* can plot a path through them — replay forbids synth.
|
|
150
150
|
*
|
|
@@ -91,7 +91,7 @@ export interface ContractSpaceSeedPhaseResult {
|
|
|
91
91
|
* Output ordering is deterministic and alphabetical by spaceId (via
|
|
92
92
|
* {@link planAllSpaces}, which also detects duplicate spaceIds). This
|
|
93
93
|
* matches the canonical sort order used by every other aggregate
|
|
94
|
-
* surface (`
|
|
94
|
+
* surface (`migrate`, `migration status`, the runner).
|
|
95
95
|
*/
|
|
96
96
|
export async function runContractSpaceSeedPhase(
|
|
97
97
|
inputs: ContractSpaceSeedPhaseInputs,
|
|
@@ -2,7 +2,7 @@ import { blue, bold, cyan, dim, green, magenta } from 'colorette';
|
|
|
2
2
|
import type { Command } from 'commander';
|
|
3
3
|
import wrapAnsi from 'wrap-ansi';
|
|
4
4
|
|
|
5
|
-
import { getCommandExamples, getLongDescription } from '../command-helpers';
|
|
5
|
+
import { getCommandExamples, getCommandSeeAlso, getLongDescription } from '../command-helpers';
|
|
6
6
|
import type { GlobalFlags } from '../global-flags';
|
|
7
7
|
import { formatDim } from './helpers';
|
|
8
8
|
import { padToFixedWidth, renderCommandTree } from './styled';
|
|
@@ -134,7 +134,7 @@ function getCommandDocsUrl(commandPath: string): string | undefined {
|
|
|
134
134
|
'db verify': 'https://pris.ly/db-verify',
|
|
135
135
|
'db update': 'https://pris.ly/db-update',
|
|
136
136
|
'migration plan': 'https://pris.ly/migration-plan',
|
|
137
|
-
|
|
137
|
+
migrate: 'https://pris.ly/migrate',
|
|
138
138
|
'migration show': 'https://pris.ly/migration-show',
|
|
139
139
|
'migration status': 'https://pris.ly/migration-status',
|
|
140
140
|
};
|
|
@@ -268,6 +268,16 @@ export function formatCommandHelp(options: {
|
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
// See also (cross-references to related commands)
|
|
272
|
+
const seeAlso = getCommandSeeAlso(command);
|
|
273
|
+
if (seeAlso && seeAlso.length > 0) {
|
|
274
|
+
lines.push(formatDimText('│'));
|
|
275
|
+
lines.push(`${formatDimText('│')} ${formatDimText('See also:')}`);
|
|
276
|
+
for (const ref of seeAlso) {
|
|
277
|
+
lines.push(`${formatDimText('│')} ${ref.verb} ${formatDimText(ref.oneLiner)}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
271
281
|
// Multi-line description (if present) - shown after all other content
|
|
272
282
|
if (longDescription) {
|
|
273
283
|
lines.push(formatDimText('│'));
|
|
@@ -90,7 +90,7 @@ export interface MigrationCommandResult {
|
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Render the shared per-space execution block consumed by the `db init`
|
|
93
|
-
* / `db update` / `
|
|
93
|
+
* / `db update` / `migrate` summaries. Always shows: space
|
|
94
94
|
* label (`Extension space: <id>` or `App space`) → per-op lines under
|
|
95
95
|
* each space → per-space marker hash (when known).
|
|
96
96
|
*
|
|
@@ -254,7 +254,7 @@ export interface MigrationApplyCommandOutputResult {
|
|
|
254
254
|
/**
|
|
255
255
|
* Per-space breakdown in canonical schedule order (extensions
|
|
256
256
|
* alphabetically, then app). Always present for the aggregate-walking
|
|
257
|
-
* `
|
|
257
|
+
* `migrate` command.
|
|
258
258
|
*/
|
|
259
259
|
readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];
|
|
260
260
|
readonly timings?: {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli-errors-D3_sMh2K.mjs","names":[],"sources":["../src/utils/cli-errors.ts"],"sourcesContent":["/**\n * Re-export all domain error factories from @prisma-next/errors for convenience.\n * CLI-specific errors (e.g., Commander argument validation in the main CLI, or\n * clipanion parse errors in the migration-file CLI) can be added here if needed.\n */\nexport type { CliErrorConflict, CliErrorEnvelope } from '@prisma-next/errors/control';\n\nimport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport type { MigrationToolsError } from '@prisma-next/migration-tools/errors';\n\nexport {\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorDestructiveChanges,\n errorHashMismatch,\n errorMarkerMissing,\n errorMarkerRequired,\n errorRunnerFailed,\n errorRuntime,\n errorSchemaVerificationFailed,\n errorTargetMismatch,\n} from '@prisma-next/errors/execution';\nexport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n errorUnfilledPlaceholder,\n placeholder,\n} from '@prisma-next/errors/migration';\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\n\n/**\n * Maps a `MigrationToolsError` raised by the migration-tools loader/graph\n * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,\n * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.\n *\n * The full `error.details` payload is forwarded into `meta` so machine\n * consumers (`--json`) see structural fields like `dir`, `storedHash`,\n * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable\n * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.\n *\n * Callers are expected to gate on `MigrationToolsError.is(error)` first\n * (mirroring the original inline pattern); non-`MigrationToolsError`\n * values are caller-classified (rethrow, wrap with command-specific\n * `errorUnexpected`, etc.).\n */\nexport function mapMigrationToolsError(error: MigrationToolsError): CliStructuredError {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,uBAAuB,OAAgD;CACrF,OAAO,aAAa,MAAM,SAAS;EACjC,KAAK,MAAM;EACX,KAAK,MAAM;EACX,MAAM;GAAE,MAAM,MAAM;GAAM,GAAI,MAAM,WAAW,EAAE;GAAG;EACrD,CAAC"}
|