@prisma-next/cli 0.15.0 → 0.16.0-dev.2
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/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/{client-DigVI8zX.mjs → client-KuBQftxz.mjs} +67 -36
- package/dist/client-KuBQftxz.mjs.map +1 -0
- package/dist/{command-helpers-CUoKYTlG.mjs → command-helpers-Cpq44aVa.mjs} +21 -5
- package/dist/command-helpers-Cpq44aVa.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts +0 -1
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts +0 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts +0 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +6 -6
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts +0 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.d.mts +0 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.d.mts +0 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +5 -5
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts +0 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +5 -5
- package/dist/commands/migration-check.d.mts +1 -2
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +2 -3
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +3 -3
- package/dist/commands/migration-list.d.mts +2 -3
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.d.mts +2 -3
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.d.mts +0 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.d.mts +0 -1
- 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 +0 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +3 -3
- package/dist/commands/migration-status.d.mts +2 -3
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/commands/ref.d.mts +1 -2
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +2 -2
- package/dist/commands/telemetry/index.d.mts +0 -1
- package/dist/commands/telemetry/index.d.mts.map +1 -1
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-D8CNDD7g.mjs → contract-at-errors-D9gEjYtg.mjs} +2 -2
- package/dist/{contract-at-errors-D8CNDD7g.mjs.map → contract-at-errors-D9gEjYtg.mjs.map} +1 -1
- package/dist/{contract-emit-wgqrOXUI.mjs → contract-emit-CgnXSANN.mjs} +3 -3
- package/dist/{contract-emit-wgqrOXUI.mjs.map → contract-emit-CgnXSANN.mjs.map} +1 -1
- package/dist/{contract-emit-sYrqzsdN.mjs → contract-emit-cJQBlvGb.mjs} +3 -3
- package/dist/{contract-emit-sYrqzsdN.mjs.map → contract-emit-cJQBlvGb.mjs.map} +1 -1
- package/dist/{contract-infer-6SQnnVj7.mjs → contract-infer-Cg8evbeg.mjs} +3 -3
- package/dist/{contract-infer-6SQnnVj7.mjs.map → contract-infer-Cg8evbeg.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-DpB4x97a.mjs → contract-space-aggregate-loader-D_3VeHVb.mjs} +14 -15
- package/dist/contract-space-aggregate-loader-D_3VeHVb.mjs.map +1 -0
- package/dist/{db-verify-CEsG5Gek.mjs → db-verify-BEclUzki.mjs} +6 -7
- package/dist/db-verify-BEclUzki.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -2
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.d.mts +0 -1
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +2 -2
- package/dist/exports/init-output.d.mts +1 -0
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/{format-CjongNb1.mjs → format-DAUAZqPt.mjs} +2 -2
- package/dist/{format-CjongNb1.mjs.map → format-DAUAZqPt.mjs.map} +1 -1
- package/dist/{framework-components-BbnM1RYm.mjs → framework-components-CnbUbiJw.mjs} +2 -2
- package/dist/{framework-components-BbnM1RYm.mjs.map → framework-components-CnbUbiJw.mjs.map} +1 -1
- package/dist/global-flags-BpoOYtNZ.d.mts.map +1 -1
- package/dist/{init-D8YFfaD6.mjs → init-C3JhkHg-.mjs} +33 -46
- package/dist/init-C3JhkHg-.mjs.map +1 -0
- package/dist/{inspect-live-schema-CEt_ztBJ.mjs → inspect-live-schema-CX7EA5C3.mjs} +3 -3
- package/dist/{inspect-live-schema-CEt_ztBJ.mjs.map → inspect-live-schema-CX7EA5C3.mjs.map} +1 -1
- package/dist/{migration-check-ByeQHOhK.mjs → migration-check-VqN-iTcx.mjs} +25 -24
- package/dist/migration-check-VqN-iTcx.mjs.map +1 -0
- package/dist/migration-cli.d.mts +0 -1
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +3 -3
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-CJO3tjiR.mjs → migration-command-scaffold-CRyYrHZ9.mjs} +3 -3
- package/dist/{migration-command-scaffold-CJO3tjiR.mjs.map → migration-command-scaffold-CRyYrHZ9.mjs.map} +1 -1
- package/dist/{migration-list-DTYM8xvm.mjs → migration-list-BAKujUjh.mjs} +3 -3
- package/dist/{migration-list-DTYM8xvm.mjs.map → migration-list-BAKujUjh.mjs.map} +1 -1
- package/dist/{migration-log-qZ8LpQIl.mjs → migration-log-C_xam2HZ.mjs} +3 -3
- package/dist/{migration-log-qZ8LpQIl.mjs.map → migration-log-C_xam2HZ.mjs.map} +1 -1
- package/dist/{migration-path-target-DmNwsDgs.mjs → migration-path-target-DpPTsRCg.mjs} +2 -2
- package/dist/{migration-path-target-DmNwsDgs.mjs.map → migration-path-target-DpPTsRCg.mjs.map} +1 -1
- package/dist/{migration-plan-CfPrB80t.mjs → migration-plan-CreSVtWZ.mjs} +6 -6
- package/dist/migration-plan-CreSVtWZ.mjs.map +1 -0
- package/dist/{migration-status-DRuS-rP5.mjs → migration-status-DYErXpyF.mjs} +6 -5
- package/dist/{migration-status-DRuS-rP5.mjs.map → migration-status-DYErXpyF.mjs.map} +1 -1
- package/dist/schemas-CeGMYFYX.d.mts.map +1 -1
- package/dist/{telemetry-DHBBq5wT.mjs → telemetry-DVr6RFnq.mjs} +2 -2
- package/dist/{telemetry-DHBBq5wT.mjs.map → telemetry-DVr6RFnq.mjs.map} +1 -1
- package/dist/{terminal-ui-DGRNFWna.d.mts → terminal-ui-BN4QOsm5.d.mts} +1 -2
- package/dist/terminal-ui-BN4QOsm5.d.mts.map +1 -0
- package/dist/{types-DFoqNIcQ.d.mts → types-D4r_HI9-.d.mts} +8 -4
- package/dist/types-D4r_HI9-.d.mts.map +1 -0
- package/dist/{verify-DDCb0R2r.mjs → verify-CgDVZjhc.mjs} +9 -8
- package/dist/verify-CgDVZjhc.mjs.map +1 -0
- package/package.json +25 -25
- package/src/commands/db-init.ts +3 -3
- package/src/commands/db-update.ts +1 -1
- package/src/commands/db-verify.ts +2 -3
- package/src/commands/init/errors.ts +62 -58
- package/src/commands/init/init.ts +29 -26
- package/src/commands/migration-check.ts +7 -7
- package/src/commands/migration-plan.ts +1 -1
- package/src/control-api/operations/db-run.ts +4 -4
- package/src/control-api/operations/db-verify.ts +12 -9
- package/src/control-api/operations/migrate.ts +70 -26
- package/src/control-api/types.ts +4 -1
- package/src/migration-cli.ts +5 -5
- package/src/utils/cli-errors.ts +15 -2
- package/src/utils/combine-verify-results.ts +1 -1
- package/src/utils/contract-space-aggregate-loader.ts +12 -13
- package/src/utils/formatters/errors.ts +24 -3
- package/src/utils/formatters/verify.ts +7 -6
- package/src/utils/integrity-violation-to-check-failure.ts +14 -14
- package/src/utils/result-handler.ts +4 -2
- package/dist/client-DigVI8zX.mjs.map +0 -1
- package/dist/command-helpers-CUoKYTlG.mjs.map +0 -1
- package/dist/contract-space-aggregate-loader-DpB4x97a.mjs.map +0 -1
- package/dist/db-verify-CEsG5Gek.mjs.map +0 -1
- package/dist/init-D8YFfaD6.mjs.map +0 -1
- package/dist/migration-check-ByeQHOhK.mjs.map +0 -1
- package/dist/migration-plan-CfPrB80t.mjs.map +0 -1
- package/dist/terminal-ui-DGRNFWna.d.mts.map +0 -1
- package/dist/types-DFoqNIcQ.d.mts.map +0 -1
- package/dist/verify-DDCb0R2r.mjs.map +0 -1
|
@@ -6,8 +6,7 @@ import { CliStructuredError } from '../../utils/cli-errors';
|
|
|
6
6
|
* the user was never given the choice — `--force` is the contract.
|
|
7
7
|
*/
|
|
8
8
|
export function errorInitReinitNeedsForce(): CliStructuredError {
|
|
9
|
-
return new CliStructuredError('
|
|
10
|
-
domain: 'CLI',
|
|
9
|
+
return new CliStructuredError('CLI.INIT_REINIT_NEEDS_FORCE', 'Project is already initialized', {
|
|
11
10
|
why: 'A `prisma-next.config.ts` already exists in this directory. Re-running `init` would overwrite the scaffolded files; in non-interactive mode `init` will not do that without `--force`.',
|
|
12
11
|
fix: 'Pass `--force` to overwrite the existing scaffold, or run `init` interactively to confirm.',
|
|
13
12
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -42,8 +41,7 @@ export function errorInitMissingFlags(options: {
|
|
|
42
41
|
}
|
|
43
42
|
})
|
|
44
43
|
.join(' ');
|
|
45
|
-
return new CliStructuredError('
|
|
46
|
-
domain: 'CLI',
|
|
44
|
+
return new CliStructuredError('CLI.INIT_MISSING_FLAGS', 'Missing required flags', {
|
|
47
45
|
why: `${options.why} Missing required flag(s): ${flagList}.`,
|
|
48
46
|
fix: `Re-run with the missing flag(s) supplied, e.g. \`prisma-next init --yes ${fixList}\`. Use \`prisma-next init --help\` to see every flag.`,
|
|
49
47
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -60,13 +58,16 @@ export function errorInitInvalidFlagValue(options: {
|
|
|
60
58
|
readonly value: string;
|
|
61
59
|
readonly allowed: readonly string[];
|
|
62
60
|
}): CliStructuredError {
|
|
63
|
-
return new CliStructuredError(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
return new CliStructuredError(
|
|
62
|
+
'CLI.INIT_INVALID_FLAG_VALUE',
|
|
63
|
+
`Invalid value for --${options.flag}`,
|
|
64
|
+
{
|
|
65
|
+
why: `\`--${options.flag} ${options.value}\` is not one of: ${options.allowed.join(', ')}.`,
|
|
66
|
+
fix: `Use one of: ${options.allowed.map((v) => `--${options.flag} ${v}`).join(', ')}.`,
|
|
67
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
68
|
+
meta: { flag: options.flag, value: options.value, allowed: options.allowed },
|
|
69
|
+
},
|
|
70
|
+
);
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
/**
|
|
@@ -81,23 +82,26 @@ export function errorInitAuthoringSchemaPathMismatch(options: {
|
|
|
81
82
|
readonly expectedExtension: string;
|
|
82
83
|
}): CliStructuredError {
|
|
83
84
|
const expectedAuthoring = options.expectedExtension === '.ts' ? 'typescript' : 'psl';
|
|
84
|
-
return new CliStructuredError(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
return new CliStructuredError(
|
|
86
|
+
'CLI.INIT_AUTHORING_SCHEMA_PATH_MISMATCH',
|
|
87
|
+
'Authoring and schema path do not match',
|
|
88
|
+
{
|
|
89
|
+
why:
|
|
90
|
+
`\`--authoring ${options.authoring}\` requires a schema file ending in ${options.expectedExtension}, ` +
|
|
91
|
+
`but \`--schema-path ${options.schemaPath}\` ends in ${options.actualExtension}.`,
|
|
92
|
+
fix:
|
|
93
|
+
`Use a matching pair, for example \`--authoring ${expectedAuthoring} --schema-path <path>${options.expectedExtension}\`, ` +
|
|
94
|
+
'or change `--authoring` to match the path you supplied. ' +
|
|
95
|
+
'You can also omit `--schema-path` to use the default for the chosen authoring.',
|
|
96
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
97
|
+
meta: {
|
|
98
|
+
authoring: options.authoring,
|
|
99
|
+
schemaPath: options.schemaPath,
|
|
100
|
+
actualExtension: options.actualExtension,
|
|
101
|
+
expectedExtension: options.expectedExtension,
|
|
102
|
+
},
|
|
99
103
|
},
|
|
100
|
-
|
|
104
|
+
);
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
/**
|
|
@@ -108,8 +112,7 @@ export function errorInitAuthoringSchemaPathMismatch(options: {
|
|
|
108
112
|
* 3 (USER_ABORTED).
|
|
109
113
|
*/
|
|
110
114
|
export function errorInitUserAborted(): CliStructuredError {
|
|
111
|
-
return new CliStructuredError('
|
|
112
|
-
domain: 'CLI',
|
|
115
|
+
return new CliStructuredError('CLI.INIT_USER_ABORTED', 'Init cancelled', {
|
|
113
116
|
why: 'The interactive prompt was cancelled before all required inputs were supplied. No files were modified.',
|
|
114
117
|
fix: 'Re-run `prisma-next init` and complete the prompts, or pass the required inputs as flags (see `--help`) for a non-interactive run.',
|
|
115
118
|
severity: 'info',
|
|
@@ -125,12 +128,15 @@ export function errorInitUserAborted(): CliStructuredError {
|
|
|
125
128
|
* mode is supposed to prevent.
|
|
126
129
|
*/
|
|
127
130
|
export function errorInitStrictProbeWithoutProbe(): CliStructuredError {
|
|
128
|
-
return new CliStructuredError(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
return new CliStructuredError(
|
|
132
|
+
'CLI.INIT_STRICT_PROBE_WITHOUT_PROBE',
|
|
133
|
+
'`--strict-probe` requires `--probe-db`',
|
|
134
|
+
{
|
|
135
|
+
why: '`--strict-probe` only changes how a *failed* probe is reported; without `--probe-db` no probe is attempted in the first place. (`init` is offline-by-default — it never opens a connection to your database without explicit consent.)',
|
|
136
|
+
fix: 'Add `--probe-db` to opt in to the probe, or drop `--strict-probe` if you do not need the version check.',
|
|
137
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
138
|
+
},
|
|
139
|
+
);
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
/**
|
|
@@ -152,8 +158,7 @@ export function errorInitInstallFailed(options: {
|
|
|
152
158
|
trimmed.length === 0
|
|
153
159
|
? 'The package manager exited with an error and no recoverable fallback applied.'
|
|
154
160
|
: `The package manager exited with: ${trimmed[0]}`;
|
|
155
|
-
return new CliStructuredError('
|
|
156
|
-
domain: 'CLI',
|
|
161
|
+
return new CliStructuredError('CLI.INIT_INSTALL_FAILED', 'Failed to install dependencies', {
|
|
157
162
|
why,
|
|
158
163
|
fix: `Install manually:\n ${options.addCommand}\n ${options.addDevCommand}\nThen run \`${options.emitCommand}\` to emit the contract.`,
|
|
159
164
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -179,8 +184,7 @@ export function errorInitInvalidManifest(options: {
|
|
|
179
184
|
readonly path: string;
|
|
180
185
|
readonly cause: string;
|
|
181
186
|
}): CliStructuredError {
|
|
182
|
-
return new CliStructuredError('
|
|
183
|
-
domain: 'CLI',
|
|
187
|
+
return new CliStructuredError('CLI.INIT_INVALID_MANIFEST', `Failed to parse ${options.path}`, {
|
|
184
188
|
why: `\`${options.path}\` is not valid JSON: ${options.cause}`,
|
|
185
189
|
fix: `Fix the JSON syntax in \`${options.path}\` (a missing comma or unbalanced brace is the most common cause), then re-run \`prisma-next init\`.`,
|
|
186
190
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -206,8 +210,7 @@ export function errorInitInvalidTsconfig(options: {
|
|
|
206
210
|
readonly path: string;
|
|
207
211
|
readonly cause: string;
|
|
208
212
|
}): CliStructuredError {
|
|
209
|
-
return new CliStructuredError('
|
|
210
|
-
domain: 'CLI',
|
|
213
|
+
return new CliStructuredError('CLI.INIT_INVALID_TSCONFIG', `Failed to parse ${options.path}`, {
|
|
211
214
|
why: `\`${options.path}\` is not valid JSON or JSONC: ${options.cause}`,
|
|
212
215
|
fix: `Fix the syntax in \`${options.path}\` and re-run \`prisma-next init\`. \`init\` accepts JSONC (comments and trailing commas) but cannot recover from unbalanced braces or missing commas.`,
|
|
213
216
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -233,8 +236,7 @@ export function errorInitProbeFailed(options: {
|
|
|
233
236
|
readonly cause: string;
|
|
234
237
|
readonly filesWritten: readonly string[];
|
|
235
238
|
}): CliStructuredError {
|
|
236
|
-
return new CliStructuredError('
|
|
237
|
-
domain: 'CLI',
|
|
239
|
+
return new CliStructuredError('CLI.INIT_PROBE_FAILED', 'Database probe failed', {
|
|
238
240
|
why: `\`--probe-db\` could not complete and \`--strict-probe\` was set: ${options.cause}`,
|
|
239
241
|
fix: 'Confirm `DATABASE_URL` points at a reachable server, or drop `--strict-probe` to treat probe failures as warnings.',
|
|
240
242
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -256,8 +258,7 @@ export function errorInitEmitFailed(options: {
|
|
|
256
258
|
readonly filesWritten: readonly string[];
|
|
257
259
|
readonly cause: string;
|
|
258
260
|
}): CliStructuredError {
|
|
259
|
-
return new CliStructuredError('
|
|
260
|
-
domain: 'CLI',
|
|
261
|
+
return new CliStructuredError('CLI.INIT_EMIT_FAILED', 'Failed to emit contract', {
|
|
261
262
|
why: `\`prisma-next contract emit\` failed: ${options.cause}`,
|
|
262
263
|
fix: `Inspect your contract file, fix the underlying issue, then re-run \`${options.emitCommand}\`. Pass \`-v\` for the full error envelope.`,
|
|
263
264
|
docsUrl: 'https://prisma-next.dev/docs/cli/contract-emit',
|
|
@@ -284,18 +285,21 @@ export function errorInitSkillInstallFailed(options: {
|
|
|
284
285
|
readonly filesWritten: readonly string[];
|
|
285
286
|
readonly cause: string;
|
|
286
287
|
}): CliStructuredError {
|
|
287
|
-
return new CliStructuredError(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
288
|
+
return new CliStructuredError(
|
|
289
|
+
'CLI.INIT_SKILL_INSTALL_FAILED',
|
|
290
|
+
'Failed to install Prisma Next skills',
|
|
291
|
+
{
|
|
292
|
+
why: `\`${options.skillInstallCommand}\` exited with an error: ${options.cause}`,
|
|
293
|
+
fix:
|
|
294
|
+
'Either:\n' +
|
|
295
|
+
` - Re-run \`prisma-next init --no-skill${options.filesWritten.length > 0 ? ' --force' : ''}\` to skip the skill install for this run, or\n` +
|
|
296
|
+
` - Fix the underlying issue (network, npm registry, \`npx skills\` on PATH) and install manually:\n ${options.skillInstallCommand}`,
|
|
297
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init#skills',
|
|
298
|
+
meta: {
|
|
299
|
+
filesWritten: options.filesWritten,
|
|
300
|
+
skillInstallCommand: options.skillInstallCommand,
|
|
301
|
+
cause: options.cause,
|
|
302
|
+
},
|
|
299
303
|
},
|
|
300
|
-
|
|
304
|
+
);
|
|
301
305
|
}
|
|
@@ -534,18 +534,21 @@ export async function runInit(
|
|
|
534
534
|
if (validated instanceof Error || (validated as { problems?: unknown }).problems !== undefined) {
|
|
535
535
|
// Route through `emitError` rather than throwing: the bare throw
|
|
536
536
|
// bypassed `--json` envelope formatting and `exitCodeForError`, so a
|
|
537
|
-
//
|
|
538
|
-
// commander instead of the documented
|
|
539
|
-
// the right channel.
|
|
537
|
+
// CLI.INIT_INVALID_OUTPUT_DOCUMENT regression would surface as an
|
|
538
|
+
// uncaught exception in commander instead of the documented
|
|
539
|
+
// `INTERNAL_ERROR` envelope on the right channel.
|
|
540
540
|
return emitError(
|
|
541
541
|
ui,
|
|
542
542
|
flags,
|
|
543
|
-
new CliStructuredError(
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
543
|
+
new CliStructuredError(
|
|
544
|
+
'CLI.INIT_INVALID_OUTPUT_DOCUMENT',
|
|
545
|
+
'Init produced an invalid output document',
|
|
546
|
+
{
|
|
547
|
+
why: `The success document failed schema validation: ${String(validated)}`,
|
|
548
|
+
fix: 'This is a bug in prisma-next. Please report it with the full `-v` output.',
|
|
549
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
550
|
+
},
|
|
551
|
+
),
|
|
549
552
|
);
|
|
550
553
|
}
|
|
551
554
|
|
|
@@ -582,10 +585,10 @@ function emitError(ui: TerminalUI, flags: GlobalFlags, error: CliStructuredError
|
|
|
582
585
|
* Maps a structured init error to its documented exit code. Centralised so
|
|
583
586
|
* the error → exit-code contract lives next to the codes themselves.
|
|
584
587
|
*
|
|
585
|
-
* `
|
|
586
|
-
* `INIT_EXIT_INTERNAL_ERROR` because those represent prisma-next
|
|
587
|
-
* user did not cause — surfacing them as `PRECONDITION` would
|
|
588
|
-
* automation into thinking the caller mis-invoked the CLI.
|
|
588
|
+
* `CLI.INIT_INVALID_OUTPUT_DOCUMENT` (and the unknown-code default branch)
|
|
589
|
+
* routes to `INIT_EXIT_INTERNAL_ERROR` because those represent prisma-next
|
|
590
|
+
* bugs the user did not cause — surfacing them as `PRECONDITION` would
|
|
591
|
+
* mislead automation into thinking the caller mis-invoked the CLI.
|
|
589
592
|
*
|
|
590
593
|
* See [exit-codes.ts](./exit-codes.ts) for the canonical list and
|
|
591
594
|
* [Style Guide § Exit Codes](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes)
|
|
@@ -596,24 +599,24 @@ function emitError(ui: TerminalUI, flags: GlobalFlags, error: CliStructuredError
|
|
|
596
599
|
*/
|
|
597
600
|
export function exitCodeForError(error: { readonly code: string }): number {
|
|
598
601
|
switch (error.code) {
|
|
599
|
-
case '
|
|
600
|
-
case '
|
|
601
|
-
case '
|
|
602
|
-
case '
|
|
603
|
-
case '
|
|
604
|
-
case '
|
|
605
|
-
case '
|
|
606
|
-
case '
|
|
602
|
+
case 'CLI.INIT_REINIT_NEEDS_FORCE': // re-init needs --force — precondition
|
|
603
|
+
case 'CLI.INIT_MISSING_FLAGS': // missing flags — precondition
|
|
604
|
+
case 'CLI.INIT_INVALID_FLAG_VALUE': // invalid flag value — precondition
|
|
605
|
+
case 'CLI.INIT_STRICT_PROBE_WITHOUT_PROBE': // --strict-probe without --probe-db — precondition
|
|
606
|
+
case 'CLI.INIT_INVALID_MANIFEST': // invalid manifest (malformed package.json) — precondition
|
|
607
|
+
case 'CLI.INIT_INVALID_TSCONFIG': // invalid tsconfig (unparseable JSONC) — precondition
|
|
608
|
+
case 'CLI.INIT_PROBE_FAILED': // probe failed under --strict-probe — precondition
|
|
609
|
+
case 'CLI.INIT_AUTHORING_SCHEMA_PATH_MISMATCH': // --authoring / --schema-path extension mismatch — precondition
|
|
607
610
|
return INIT_EXIT_PRECONDITION;
|
|
608
|
-
case '
|
|
611
|
+
case 'CLI.INIT_USER_ABORTED': // user aborted interactive prompt
|
|
609
612
|
return INIT_EXIT_USER_ABORTED;
|
|
610
|
-
case '
|
|
613
|
+
case 'CLI.INIT_INSTALL_FAILED': // install failed
|
|
611
614
|
return INIT_EXIT_INSTALL_FAILED;
|
|
612
|
-
case '
|
|
615
|
+
case 'CLI.INIT_EMIT_FAILED': // emit failed
|
|
613
616
|
return INIT_EXIT_EMIT_FAILED;
|
|
614
|
-
case '
|
|
617
|
+
case 'CLI.INIT_INVALID_OUTPUT_DOCUMENT': // invalid output document — internal bug in prisma-next
|
|
615
618
|
return INIT_EXIT_INTERNAL_ERROR;
|
|
616
|
-
case '
|
|
619
|
+
case 'CLI.INIT_SKILL_INSTALL_FAILED': // skill install failed
|
|
617
620
|
return INIT_EXIT_SKILL_INSTALL_FAILED;
|
|
618
621
|
default:
|
|
619
622
|
// Any unexpected code is treated as an internal bug rather than
|
|
@@ -83,7 +83,7 @@ function checkFileExists(
|
|
|
83
83
|
if (!existsSync(join(dirPath, fileName))) {
|
|
84
84
|
return {
|
|
85
85
|
space: spaceId,
|
|
86
|
-
code: '
|
|
86
|
+
code: 'MIGRATION.CHECK_FILE_MISSING',
|
|
87
87
|
where: migrationFileRelative(dirPath, fileName),
|
|
88
88
|
why: `${fileName} is missing from ${dirName}`,
|
|
89
89
|
fix: 'Re-emit the migration package or restore from version control.',
|
|
@@ -105,7 +105,7 @@ function checkSnapshotConsistency(
|
|
|
105
105
|
if (typeof snapshotHash === 'string' && snapshotHash !== pkg.metadata.to) {
|
|
106
106
|
return {
|
|
107
107
|
space: spaceId,
|
|
108
|
-
code: '
|
|
108
|
+
code: 'MIGRATION.CHECK_SNAPSHOT_HASH_MISMATCH',
|
|
109
109
|
where: migrationPathRelative(pkg.dirPath),
|
|
110
110
|
why: `Migration "${pkg.dirName}" declares to=${pkg.metadata.to} but end-contract.json has storageHash=${snapshotHash}`,
|
|
111
111
|
fix: 'Re-emit the migration package so migration.json and end-contract.json agree.',
|
|
@@ -114,7 +114,7 @@ function checkSnapshotConsistency(
|
|
|
114
114
|
} catch {
|
|
115
115
|
return {
|
|
116
116
|
space: spaceId,
|
|
117
|
-
code: '
|
|
117
|
+
code: 'MIGRATION.CHECK_SNAPSHOT_UNPARSEABLE',
|
|
118
118
|
where: migrationPathRelative(pkg.dirPath),
|
|
119
119
|
why: `Migration "${pkg.dirName}" has an unparseable end-contract.json.`,
|
|
120
120
|
fix: 'Re-emit the migration package to repair the snapshot file.',
|
|
@@ -212,7 +212,7 @@ function checkReachability(space: CheckSpace): readonly CheckFailure[] {
|
|
|
212
212
|
if (!isReachable) {
|
|
213
213
|
failures.push({
|
|
214
214
|
space: space.spaceId,
|
|
215
|
-
code: '
|
|
215
|
+
code: 'MIGRATION.CHECK_UNREACHABLE_MIGRATION',
|
|
216
216
|
where: migrationPathRelative(pkg.dirPath),
|
|
217
217
|
why: `Migration "${pkg.dirName}" starts from ${pkg.metadata.from} which no other migration produces`,
|
|
218
218
|
fix: 'This migration is unreachable in the graph. Delete it or re-emit a connecting migration.',
|
|
@@ -228,7 +228,7 @@ function checkDanglingRefs(space: CheckSpace): readonly CheckFailure[] {
|
|
|
228
228
|
if (!space.graph.nodes.has(entry.hash)) {
|
|
229
229
|
failures.push({
|
|
230
230
|
space: space.spaceId,
|
|
231
|
-
code: '
|
|
231
|
+
code: 'MIGRATION.CHECK_DANGLING_REF',
|
|
232
232
|
where: relative(process.cwd(), join(space.refsDir, `${name}.json`)),
|
|
233
233
|
why: `Ref "${name}" points at ${entry.hash} which does not exist in the migration graph`,
|
|
234
234
|
fix: `Update the ref with \`prisma-next ref set ${name} <valid-hash>\` or delete it.`,
|
|
@@ -522,7 +522,7 @@ async function checkSingleTarget(
|
|
|
522
522
|
matchedPkg = hits[0]!.pkg;
|
|
523
523
|
} else if (bestParseFailure !== undefined) {
|
|
524
524
|
// The ref didn't resolve in any in-scope space — surface the most informative
|
|
525
|
-
// parse failure through the shared ref-resolution envelope (
|
|
525
|
+
// parse failure through the shared ref-resolution envelope (CONTRACT.VERIFY_FAILED) the
|
|
526
526
|
// earlier work established, rather than a bespoke string. (Ref-resolved-but-
|
|
527
527
|
// no-package falls through to the "not found on disk" result below.)
|
|
528
528
|
return { error: mapRefResolutionError(bestParseFailure), exitCode: PRECONDITION };
|
|
@@ -551,7 +551,7 @@ async function checkSingleTarget(
|
|
|
551
551
|
if (!verification.ok) {
|
|
552
552
|
failures.push({
|
|
553
553
|
space: matchedSpace.spaceId,
|
|
554
|
-
code: '
|
|
554
|
+
code: 'MIGRATION.CHECK_HASH_MISMATCH',
|
|
555
555
|
where: migrationFileRelative(matchedPkg.dirPath, 'migration.json'),
|
|
556
556
|
why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,
|
|
557
557
|
fix: 'Re-emit the migration package or restore from version control.',
|
|
@@ -142,7 +142,7 @@ async function runPlannerLeg(
|
|
|
142
142
|
);
|
|
143
143
|
}
|
|
144
144
|
} catch (e) {
|
|
145
|
-
if (CliStructuredError.is(e) && e.
|
|
145
|
+
if (CliStructuredError.is(e) && e.code === 'MIGRATION.UNFILLED_PLACEHOLDER') {
|
|
146
146
|
hasPlaceholders = true;
|
|
147
147
|
} else {
|
|
148
148
|
throw e;
|
|
@@ -286,8 +286,9 @@ function aggregatePlannerWarnings(
|
|
|
286
286
|
* an extension that was removed from `extensionPacks` without first
|
|
287
287
|
* cleaning up its on-disk migrations / database tables.
|
|
288
288
|
*
|
|
289
|
-
* Returns a {@link CliStructuredError} envelope (code
|
|
290
|
-
* `kind: 'orphanMarker'`) for the
|
|
289
|
+
* Returns a {@link CliStructuredError} envelope (code
|
|
290
|
+
* `MIGRATION.CONTRACT_SPACE_VIOLATION`, `kind: 'orphanMarker'`) for the
|
|
291
|
+
* first orphan it finds, or `null`
|
|
291
292
|
* when every marker row maps to a declared contract space. Mirrors the M2
|
|
292
293
|
* `runContractSpaceVerifierMarkerCheck` envelope so downstream
|
|
293
294
|
* tooling (integration tests, JSON consumers) keeps asserting on the
|
|
@@ -313,8 +314,7 @@ function detectOrphanMarkers(
|
|
|
313
314
|
orphans.length === 1
|
|
314
315
|
? `Orphan contract-space marker detected for "${orphans[0]}"`
|
|
315
316
|
: `Orphan contract-space markers detected for ${orphans.length} spaces`;
|
|
316
|
-
return new CliStructuredError('
|
|
317
|
-
domain: 'MIG',
|
|
317
|
+
return new CliStructuredError('MIGRATION.CONTRACT_SPACE_VIOLATION', summary, {
|
|
318
318
|
why: `The database has \`_prisma_marker\` rows for spaces (${orphans
|
|
319
319
|
.map((s) => `"${s}"`)
|
|
320
320
|
.join(
|
|
@@ -254,12 +254,15 @@ function finaliseVerifyResult(args: {
|
|
|
254
254
|
if (!verifyResult.ok) {
|
|
255
255
|
emitVerifySpan(onProgress, 'spanEndError');
|
|
256
256
|
return notOk(
|
|
257
|
-
new CliStructuredError(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
257
|
+
new CliStructuredError(
|
|
258
|
+
'MIGRATION.CONTRACT_SPACE_VIOLATION',
|
|
259
|
+
'Aggregate verifier introspection failed',
|
|
260
|
+
{
|
|
261
|
+
why: verifyResult.failure.detail,
|
|
262
|
+
fix: 'Check database connectivity and the introspection tooling.',
|
|
263
|
+
docsUrl: 'https://pris.ly/contract-spaces',
|
|
264
|
+
},
|
|
265
|
+
),
|
|
263
266
|
);
|
|
264
267
|
}
|
|
265
268
|
const markerError = skipMarker
|
|
@@ -300,7 +303,8 @@ function buildSkippedSchemaResult(space: AggregateContractSpace): VerifyDatabase
|
|
|
300
303
|
/**
|
|
301
304
|
* Translate per-space marker check failures and orphan markers into a
|
|
302
305
|
* single CLI structured error envelope. Preserves the legacy code
|
|
303
|
-
* `
|
|
306
|
+
* `MIGRATION.CONTRACT_SPACE_VIOLATION` (was emitted by
|
|
307
|
+
* `runContractSpaceVerifierMarkerCheck`).
|
|
304
308
|
*/
|
|
305
309
|
function mapMarkerCheckFailures(
|
|
306
310
|
appSpaceId: string,
|
|
@@ -354,8 +358,7 @@ function mapMarkerCheckFailures(
|
|
|
354
358
|
violations.length === 1
|
|
355
359
|
? 'Contract-space verifier found a violation'
|
|
356
360
|
: `Contract-space verifier found violations (${violations.length})`;
|
|
357
|
-
return new CliStructuredError('
|
|
358
|
-
domain: 'MIG',
|
|
361
|
+
return new CliStructuredError('MIGRATION.CONTRACT_SPACE_VIOLATION', summary, {
|
|
359
362
|
why: `The on-disk \`migrations/\` directory, the \`extensionPacks\` declaration, and the live database marker rows are not in agreement.\n${lines.join('\n')}`,
|
|
360
363
|
fix: violations[0]?.remediation ?? 'Review and reconcile the violations listed above.',
|
|
361
364
|
docsUrl: 'https://pris.ly/contract-spaces',
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
} from '@prisma-next/framework-components/control';
|
|
13
13
|
import {
|
|
14
14
|
type AggregateContractSpace,
|
|
15
|
+
allStorageElementsExternal,
|
|
15
16
|
buildFabricatedMigrationEdge,
|
|
16
17
|
type ContractMarkerRecordLike,
|
|
17
18
|
type ContractSpaceAggregate,
|
|
@@ -98,13 +99,17 @@ export interface ExecuteMigrateOptions<TFamilyId extends string, TTargetId exten
|
|
|
98
99
|
* 2. Read live marker rows per space (`familyInstance.readAllMarkers`).
|
|
99
100
|
* 3. Per space: `resolveRecordedPath` plots the path from the live
|
|
100
101
|
* marker to `space.headRef.hash` (or `refHash` for the app
|
|
101
|
-
* space when provided).
|
|
102
|
-
*
|
|
102
|
+
* space when provided). An empty-graph space whose elements are ALL
|
|
103
|
+
* externally managed resolves declaratively (marker to head, zero
|
|
104
|
+
* ops), mirroring the db-init aggregate planner: such a space ships
|
|
105
|
+
* no DDL and has nothing to author. Every other empty-graph space
|
|
106
|
+
* fails loudly — "never planned" is a user-error condition for
|
|
107
|
+
* replay.
|
|
103
108
|
* 4. Hand off to {@link runMigration} (the runner-driving tail
|
|
104
109
|
* shared with `db init` / `db update`). Marker advancement is
|
|
105
110
|
* inside the per-space transaction.
|
|
106
111
|
*
|
|
107
|
-
* Encodes the replay-only contract:
|
|
112
|
+
* Encodes the replay-only contract: the app contract space must have an
|
|
108
113
|
* authored migration graph on disk before this operation can advance it.
|
|
109
114
|
*/
|
|
110
115
|
export async function executeMigrate<TFamilyId extends string, TTargetId extends string>(
|
|
@@ -230,8 +235,13 @@ export async function executeMigrate<TFamilyId extends string, TTargetId extends
|
|
|
230
235
|
// plans). Surfaces every loaded space — including at-head empty-
|
|
231
236
|
// graph extensions — in `perSpace[]` so the result reflects the
|
|
232
237
|
// full aggregate, not just the spaces the runner would have touched.
|
|
233
|
-
|
|
234
|
-
|
|
238
|
+
// A zero-op plan still counts as pending when it advances a marker
|
|
239
|
+
// (declared-state resolution for an all-external extension space).
|
|
240
|
+
const hasPendingWork = applyOrder.some((spaceId) => {
|
|
241
|
+
const entry = perSpacePlans.get(spaceId);
|
|
242
|
+
return entry !== undefined && planRequiresExecution(entry);
|
|
243
|
+
});
|
|
244
|
+
if (!hasPendingWork) {
|
|
235
245
|
const ordered = canonicalOrder
|
|
236
246
|
.filter((spaceId) => perSpacePlans.has(spaceId) || atHeadResolutions.has(spaceId))
|
|
237
247
|
.map((spaceId) => {
|
|
@@ -397,6 +407,39 @@ export function planSpacePath({
|
|
|
397
407
|
}),
|
|
398
408
|
};
|
|
399
409
|
}
|
|
410
|
+
// Empty-graph extension space not yet at head: the space ships no
|
|
411
|
+
// migration packages at all. Advancing the marker without migrations
|
|
412
|
+
// (the db-init aggregate planner's declared-state strategy, mirrored
|
|
413
|
+
// here) is valid exclusively when every element the space declares is
|
|
414
|
+
// externally managed — nothing Prisma Next owns exists in such a space
|
|
415
|
+
// (e.g. Supabase's auth/storage), so its declared state needs no
|
|
416
|
+
// migration to be true, and there is no command that could author an
|
|
417
|
+
// edge for it. A space that declares a managed element but ships no
|
|
418
|
+
// migration graph is an authoring bug: it falls through to the
|
|
419
|
+
// never-planned failure, like an app space with no authored graph.
|
|
420
|
+
if (!isAppSpace && allStorageElementsExternal(space.contract())) {
|
|
421
|
+
if (headRef.invariants.length > 0) {
|
|
422
|
+
return {
|
|
423
|
+
kind: 'unsatisfiable',
|
|
424
|
+
spaceId: space.spaceId,
|
|
425
|
+
isAppSpace,
|
|
426
|
+
missing: [...headRef.invariants].sort(),
|
|
427
|
+
targetInvariants: headRef.invariants,
|
|
428
|
+
targetSpace: space,
|
|
429
|
+
liveHash: liveHash ?? EMPTY_CONTRACT_HASH,
|
|
430
|
+
refName: undefined,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
kind: 'ok',
|
|
435
|
+
plan: buildAtHeadResolution({
|
|
436
|
+
aggregateTargetId: aggregate.targetId,
|
|
437
|
+
space,
|
|
438
|
+
targetHash,
|
|
439
|
+
liveMarker,
|
|
440
|
+
}),
|
|
441
|
+
};
|
|
442
|
+
}
|
|
400
443
|
return { kind: 'never-planned', spaceId: space.spaceId, targetHash };
|
|
401
444
|
}
|
|
402
445
|
|
|
@@ -434,11 +477,13 @@ export function planSpacePath({
|
|
|
434
477
|
}
|
|
435
478
|
|
|
436
479
|
/**
|
|
437
|
-
* Build a zero-op {@link PerSpacePlan} for an empty-graph
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
480
|
+
* Build a zero-op {@link PerSpacePlan} for an empty-graph space —
|
|
481
|
+
* either one whose live marker already matches the target (at-head), or
|
|
482
|
+
* an all-external extension space whose marker must advance to the head
|
|
483
|
+
* ref with no DDL (declared-state). Lets the apply pipeline thread the
|
|
484
|
+
* space through `perSpacePlans` -> `applyOrder` -> the success
|
|
485
|
+
* envelope's `perSpace[]` block so the result reflects every loaded
|
|
486
|
+
* space, even when there is nothing to execute.
|
|
442
487
|
*/
|
|
443
488
|
function buildAtHeadResolution(args: {
|
|
444
489
|
readonly aggregateTargetId: string;
|
|
@@ -469,17 +514,14 @@ function buildAtHeadResolution(args: {
|
|
|
469
514
|
};
|
|
470
515
|
}
|
|
471
516
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
total += entry.plan.operations.length;
|
|
481
|
-
}
|
|
482
|
-
return total;
|
|
517
|
+
/**
|
|
518
|
+
* A plan needs the runner when it executes operations or advances the
|
|
519
|
+
* space's marker (a declared-state resolution has zero operations but a
|
|
520
|
+
* destination hash the live marker doesn't carry yet).
|
|
521
|
+
*/
|
|
522
|
+
function planRequiresExecution(entry: PerSpacePlan): boolean {
|
|
523
|
+
if (entry.plan.operations.length > 0) return true;
|
|
524
|
+
return entry.plan.origin?.storageHash !== entry.plan.destination.storageHash;
|
|
483
525
|
}
|
|
484
526
|
|
|
485
527
|
interface BuildSuccessArgs {
|
|
@@ -552,10 +594,12 @@ function buildSuccess(args: BuildSuccessArgs): MigrateSuccess {
|
|
|
552
594
|
}
|
|
553
595
|
|
|
554
596
|
/**
|
|
555
|
-
* Build the `neverPlanned` failure raised when a contract space
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
597
|
+
* Build the `neverPlanned` failure raised when a contract space that
|
|
598
|
+
* declares managed storage elements has no on-disk migration graph but
|
|
599
|
+
* migrate was asked to reach a target hash. All-external spaces never reach
|
|
600
|
+
* this: they resolve declaratively (marker advances to the head ref with
|
|
601
|
+
* zero operations). The `why` states only the condition; the recovery
|
|
602
|
+
* sequence is composed by `errorPathUnreachable`'s `fix`.
|
|
559
603
|
*
|
|
560
604
|
* @internal Exported for testing only.
|
|
561
605
|
*/
|
|
@@ -563,7 +607,7 @@ export function buildNeverPlannedFailure(spaceId: string, targetHash: string): M
|
|
|
563
607
|
return {
|
|
564
608
|
code: 'MIGRATION_PATH_NOT_FOUND',
|
|
565
609
|
summary: `No on-disk migrations for contract space "${spaceId}"`,
|
|
566
|
-
why: `migrate is replay-only:
|
|
610
|
+
why: `migrate is replay-only: a contract space that declares managed storage elements must have an authored migration graph on disk. Space "${spaceId}" has no migrations under \`migrations/${spaceId}/\` but its head ref targets "${targetHash}".`,
|
|
567
611
|
meta: { spaceId, target: targetHash, kind: 'neverPlanned' },
|
|
568
612
|
};
|
|
569
613
|
}
|
package/src/control-api/types.ts
CHANGED
|
@@ -402,7 +402,10 @@ export interface DbInitSuccess {
|
|
|
402
402
|
/**
|
|
403
403
|
* Failure codes for dbInit operation.
|
|
404
404
|
*/
|
|
405
|
-
export type DbInitFailureCode =
|
|
405
|
+
export type DbInitFailureCode =
|
|
406
|
+
| 'PLANNING_FAILED'
|
|
407
|
+
| 'MIGRATION.MARKER_ORIGIN_MISMATCH'
|
|
408
|
+
| 'RUNNER_FAILED';
|
|
406
409
|
|
|
407
410
|
/**
|
|
408
411
|
* Failure details for dbInit operation.
|
package/src/migration-cli.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* the CLI commands use, walking up from the migration file's directory.
|
|
22
22
|
* 4. Probe-instantiates the migration class without a stack so it can read
|
|
23
23
|
* `targetId` and verify it matches `config.target.targetId`
|
|
24
|
-
* (`
|
|
24
|
+
* (`MIGRATION.TARGET_MISMATCH` on mismatch) before any stack-driven adapter
|
|
25
25
|
* construction runs.
|
|
26
26
|
* 5. Assembles a `ControlStack` from the loaded config descriptors and
|
|
27
27
|
* constructs the migration with that stack.
|
|
@@ -269,7 +269,7 @@ async function orchestrate(
|
|
|
269
269
|
|
|
270
270
|
// Pre-scan for malformed `--config` (no value, or value-shaped-as-flag)
|
|
271
271
|
// before delegating to clipanion. The legacy parser surfaced both as
|
|
272
|
-
// `errorMigrationCliInvalidConfigArg` (`
|
|
272
|
+
// `errorMigrationCliInvalidConfigArg` (`CLI.CONFIG_ARG_MISSING_PATH`); pre-scanning
|
|
273
273
|
// here keeps that contract independent of how clipanion classifies
|
|
274
274
|
// the error internally (it variably throws `UnknownSyntaxError` or
|
|
275
275
|
// accepts the flag-shaped token as the value depending on what other
|
|
@@ -337,7 +337,7 @@ async function orchestrate(
|
|
|
337
337
|
* - `--config <empty>` where the value is the empty string. Shells
|
|
338
338
|
* expand `--config ""` (or `--config "$UNSET_VAR"`) into a real
|
|
339
339
|
* empty argv token; treating that as a usage error here surfaces
|
|
340
|
-
* `
|
|
340
|
+
* `CLI.CONFIG_ARG_MISSING_PATH` instead of a less actionable loader error on an
|
|
341
341
|
* empty path.
|
|
342
342
|
* - `--config=` (the equals form with an empty value). Same shape as
|
|
343
343
|
* the empty-string case above; the user expressed intent to override
|
|
@@ -425,7 +425,7 @@ function isUnknownSyntaxError(err: unknown): err is Error {
|
|
|
425
425
|
/**
|
|
426
426
|
* Best-effort: pull the first input token that doesn't match a known
|
|
427
427
|
* flag. Falls back to the first token when we can't pinpoint it. The
|
|
428
|
-
* returned name is rendered into the user-visible
|
|
428
|
+
* returned name is rendered into the user-visible CLI.UNKNOWN_FLAG envelope
|
|
429
429
|
* (`Unknown flag \`<name>\``) and round-tripped via `meta.flag` so
|
|
430
430
|
* agent consumers can render their own "did you mean" suggestions.
|
|
431
431
|
*/
|
|
@@ -556,7 +556,7 @@ async function runMigration(
|
|
|
556
556
|
// subclasses are required to accept the no-arg form; the abstract
|
|
557
557
|
// `Migration` constructor declares `stack?` and target subclasses
|
|
558
558
|
// (Postgres, Mongo) propagate that optionality. This makes the
|
|
559
|
-
// target-mismatch guard fail fast with `
|
|
559
|
+
// target-mismatch guard fail fast with `MIGRATION.TARGET_MISMATCH` before any
|
|
560
560
|
// stack-driven adapter construction begins, even if the wrong-target
|
|
561
561
|
// adapter's `create` would otherwise succeed and silently misshapen
|
|
562
562
|
// the stored adapter cast.
|