@prisma-next/cli 0.16.0-dev.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +13 -13
- package/dist/{client-KuBQftxz.mjs → client-DwOyZz0a.mjs} +13 -12
- package/dist/client-DwOyZz0a.mjs.map +1 -0
- package/dist/{command-helpers-Cpq44aVa.mjs → command-helpers-CNwURRf9.mjs} +3 -3
- package/dist/command-helpers-CNwURRf9.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 +6 -6
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.mjs +5 -5
- package/dist/commands/db-update.mjs.map +1 -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 -1
- package/dist/commands/migrate.mjs +5 -5
- package/dist/commands/migration-check.d.mts +1 -1
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +1 -1
- package/dist/commands/migration-graph.mjs +3 -3
- package/dist/commands/migration-list.d.mts +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.d.mts +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.mjs +3 -3
- package/dist/commands/migration-status.d.mts +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +2 -2
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-D9gEjYtg.mjs → contract-at-errors-BHbY04pl.mjs} +2 -2
- package/dist/{contract-at-errors-D9gEjYtg.mjs.map → contract-at-errors-BHbY04pl.mjs.map} +1 -1
- package/dist/{contract-emit-cJQBlvGb.mjs → contract-emit-BeidkyUC.mjs} +3 -3
- package/dist/{contract-emit-cJQBlvGb.mjs.map → contract-emit-BeidkyUC.mjs.map} +1 -1
- package/dist/{contract-emit-CgnXSANN.mjs → contract-emit-IQBYv351.mjs} +3 -3
- package/dist/{contract-emit-CgnXSANN.mjs.map → contract-emit-IQBYv351.mjs.map} +1 -1
- package/dist/{contract-infer-Cg8evbeg.mjs → contract-infer-B3Wq2cu1.mjs} +3 -3
- package/dist/{contract-infer-Cg8evbeg.mjs.map → contract-infer-B3Wq2cu1.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-D_3VeHVb.mjs → contract-space-aggregate-loader-BirzMmW1.mjs} +15 -14
- package/dist/contract-space-aggregate-loader-BirzMmW1.mjs.map +1 -0
- package/dist/{db-verify-BEclUzki.mjs → db-verify-DpRrecs7.mjs} +7 -6
- package/dist/db-verify-DpRrecs7.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 +2 -2
- package/dist/{format-DAUAZqPt.mjs → format-CaCF63ld.mjs} +2 -2
- package/dist/{format-DAUAZqPt.mjs.map → format-CaCF63ld.mjs.map} +1 -1
- package/dist/{framework-components-CnbUbiJw.mjs → framework-components-CnBcJDmF.mjs} +2 -2
- package/dist/{framework-components-CnbUbiJw.mjs.map → framework-components-CnBcJDmF.mjs.map} +1 -1
- package/dist/{init-C3JhkHg-.mjs → init-Boa0LzeJ.mjs} +46 -33
- package/dist/init-Boa0LzeJ.mjs.map +1 -0
- package/dist/{inspect-live-schema-CX7EA5C3.mjs → inspect-live-schema-CldSQjVI.mjs} +3 -3
- package/dist/{inspect-live-schema-CX7EA5C3.mjs.map → inspect-live-schema-CldSQjVI.mjs.map} +1 -1
- package/dist/{migration-check-VqN-iTcx.mjs → migration-check-CGtYnR9k.mjs} +24 -24
- package/dist/migration-check-CGtYnR9k.mjs.map +1 -0
- package/dist/migration-cli.mjs +3 -3
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-CRyYrHZ9.mjs → migration-command-scaffold-B3m-MMAx.mjs} +3 -3
- package/dist/{migration-command-scaffold-CRyYrHZ9.mjs.map → migration-command-scaffold-B3m-MMAx.mjs.map} +1 -1
- package/dist/{migration-list-BAKujUjh.mjs → migration-list-DBU6Pneg.mjs} +3 -3
- package/dist/{migration-list-BAKujUjh.mjs.map → migration-list-DBU6Pneg.mjs.map} +1 -1
- package/dist/{migration-log-C_xam2HZ.mjs → migration-log-BYngyvXa.mjs} +3 -3
- package/dist/{migration-log-C_xam2HZ.mjs.map → migration-log-BYngyvXa.mjs.map} +1 -1
- package/dist/{migration-path-target-DpPTsRCg.mjs → migration-path-target-DQa4Caoc.mjs} +2 -2
- package/dist/{migration-path-target-DpPTsRCg.mjs.map → migration-path-target-DQa4Caoc.mjs.map} +1 -1
- package/dist/{migration-plan-CreSVtWZ.mjs → migration-plan-D6bHpCzE.mjs} +6 -6
- package/dist/migration-plan-D6bHpCzE.mjs.map +1 -0
- package/dist/{migration-status-DYErXpyF.mjs → migration-status-CpQ5UhcU.mjs} +5 -5
- package/dist/{migration-status-DYErXpyF.mjs.map → migration-status-CpQ5UhcU.mjs.map} +1 -1
- package/dist/{telemetry-DVr6RFnq.mjs → telemetry-BQJ_XHa9.mjs} +2 -2
- package/dist/{telemetry-DVr6RFnq.mjs.map → telemetry-BQJ_XHa9.mjs.map} +1 -1
- package/dist/{types-D4r_HI9-.d.mts → types-DnpnkEgM.d.mts} +2 -2
- package/dist/{types-D4r_HI9-.d.mts.map → types-DnpnkEgM.d.mts.map} +1 -1
- package/dist/{verify-CgDVZjhc.mjs → verify-CInGyt4U.mjs} +2 -2
- package/dist/{verify-CgDVZjhc.mjs.map → verify-CInGyt4U.mjs.map} +1 -1
- package/package.json +21 -21
- package/src/commands/db-init.ts +3 -3
- package/src/commands/db-update.ts +1 -1
- package/src/commands/db-verify.ts +3 -2
- package/src/commands/init/errors.ts +58 -62
- package/src/commands/init/init.ts +26 -29
- 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 +9 -12
- package/src/control-api/types.ts +1 -4
- package/src/migration-cli.ts +5 -5
- package/src/utils/cli-errors.ts +1 -1
- package/src/utils/combine-verify-results.ts +1 -1
- package/src/utils/contract-space-aggregate-loader.ts +13 -12
- package/src/utils/integrity-violation-to-check-failure.ts +14 -14
- package/src/utils/result-handler.ts +2 -4
- package/dist/client-KuBQftxz.mjs.map +0 -1
- package/dist/command-helpers-Cpq44aVa.mjs.map +0 -1
- package/dist/contract-space-aggregate-loader-D_3VeHVb.mjs.map +0 -1
- package/dist/db-verify-BEclUzki.mjs.map +0 -1
- package/dist/init-C3JhkHg-.mjs.map +0 -1
- package/dist/migration-check-VqN-iTcx.mjs.map +0 -1
- package/dist/migration-plan-CreSVtWZ.mjs.map +0 -1
|
@@ -6,7 +6,8 @@ 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('
|
|
9
|
+
return new CliStructuredError('5002', 'Project is already initialized', {
|
|
10
|
+
domain: 'CLI',
|
|
10
11
|
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`.',
|
|
11
12
|
fix: 'Pass `--force` to overwrite the existing scaffold, or run `init` interactively to confirm.',
|
|
12
13
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -41,7 +42,8 @@ export function errorInitMissingFlags(options: {
|
|
|
41
42
|
}
|
|
42
43
|
})
|
|
43
44
|
.join(' ');
|
|
44
|
-
return new CliStructuredError('
|
|
45
|
+
return new CliStructuredError('5003', 'Missing required flags', {
|
|
46
|
+
domain: 'CLI',
|
|
45
47
|
why: `${options.why} Missing required flag(s): ${flagList}.`,
|
|
46
48
|
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.`,
|
|
47
49
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -58,16 +60,13 @@ export function errorInitInvalidFlagValue(options: {
|
|
|
58
60
|
readonly value: string;
|
|
59
61
|
readonly allowed: readonly string[];
|
|
60
62
|
}): CliStructuredError {
|
|
61
|
-
return new CliStructuredError(
|
|
62
|
-
'CLI
|
|
63
|
-
|
|
64
|
-
{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
meta: { flag: options.flag, value: options.value, allowed: options.allowed },
|
|
69
|
-
},
|
|
70
|
-
);
|
|
63
|
+
return new CliStructuredError('5004', `Invalid value for --${options.flag}`, {
|
|
64
|
+
domain: 'CLI',
|
|
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
|
+
});
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
/**
|
|
@@ -82,26 +81,23 @@ export function errorInitAuthoringSchemaPathMismatch(options: {
|
|
|
82
81
|
readonly expectedExtension: string;
|
|
83
82
|
}): CliStructuredError {
|
|
84
83
|
const expectedAuthoring = options.expectedExtension === '.ts' ? 'typescript' : 'psl';
|
|
85
|
-
return new CliStructuredError(
|
|
86
|
-
'CLI
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
actualExtension: options.actualExtension,
|
|
101
|
-
expectedExtension: options.expectedExtension,
|
|
102
|
-
},
|
|
84
|
+
return new CliStructuredError('5014', 'Authoring and schema path do not match', {
|
|
85
|
+
domain: 'CLI',
|
|
86
|
+
why:
|
|
87
|
+
`\`--authoring ${options.authoring}\` requires a schema file ending in ${options.expectedExtension}, ` +
|
|
88
|
+
`but \`--schema-path ${options.schemaPath}\` ends in ${options.actualExtension}.`,
|
|
89
|
+
fix:
|
|
90
|
+
`Use a matching pair, for example \`--authoring ${expectedAuthoring} --schema-path <path>${options.expectedExtension}\`, ` +
|
|
91
|
+
'or change `--authoring` to match the path you supplied. ' +
|
|
92
|
+
'You can also omit `--schema-path` to use the default for the chosen authoring.',
|
|
93
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
94
|
+
meta: {
|
|
95
|
+
authoring: options.authoring,
|
|
96
|
+
schemaPath: options.schemaPath,
|
|
97
|
+
actualExtension: options.actualExtension,
|
|
98
|
+
expectedExtension: options.expectedExtension,
|
|
103
99
|
},
|
|
104
|
-
);
|
|
100
|
+
});
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
/**
|
|
@@ -112,7 +108,8 @@ export function errorInitAuthoringSchemaPathMismatch(options: {
|
|
|
112
108
|
* 3 (USER_ABORTED).
|
|
113
109
|
*/
|
|
114
110
|
export function errorInitUserAborted(): CliStructuredError {
|
|
115
|
-
return new CliStructuredError('
|
|
111
|
+
return new CliStructuredError('5006', 'Init cancelled', {
|
|
112
|
+
domain: 'CLI',
|
|
116
113
|
why: 'The interactive prompt was cancelled before all required inputs were supplied. No files were modified.',
|
|
117
114
|
fix: 'Re-run `prisma-next init` and complete the prompts, or pass the required inputs as flags (see `--help`) for a non-interactive run.',
|
|
118
115
|
severity: 'info',
|
|
@@ -128,15 +125,12 @@ export function errorInitUserAborted(): CliStructuredError {
|
|
|
128
125
|
* mode is supposed to prevent.
|
|
129
126
|
*/
|
|
130
127
|
export function errorInitStrictProbeWithoutProbe(): CliStructuredError {
|
|
131
|
-
return new CliStructuredError(
|
|
132
|
-
'CLI
|
|
133
|
-
'`--strict-probe`
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
138
|
-
},
|
|
139
|
-
);
|
|
128
|
+
return new CliStructuredError('5005', '`--strict-probe` requires `--probe-db`', {
|
|
129
|
+
domain: 'CLI',
|
|
130
|
+
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.)',
|
|
131
|
+
fix: 'Add `--probe-db` to opt in to the probe, or drop `--strict-probe` if you do not need the version check.',
|
|
132
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
133
|
+
});
|
|
140
134
|
}
|
|
141
135
|
|
|
142
136
|
/**
|
|
@@ -158,7 +152,8 @@ export function errorInitInstallFailed(options: {
|
|
|
158
152
|
trimmed.length === 0
|
|
159
153
|
? 'The package manager exited with an error and no recoverable fallback applied.'
|
|
160
154
|
: `The package manager exited with: ${trimmed[0]}`;
|
|
161
|
-
return new CliStructuredError('
|
|
155
|
+
return new CliStructuredError('5007', 'Failed to install dependencies', {
|
|
156
|
+
domain: 'CLI',
|
|
162
157
|
why,
|
|
163
158
|
fix: `Install manually:\n ${options.addCommand}\n ${options.addDevCommand}\nThen run \`${options.emitCommand}\` to emit the contract.`,
|
|
164
159
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -184,7 +179,8 @@ export function errorInitInvalidManifest(options: {
|
|
|
184
179
|
readonly path: string;
|
|
185
180
|
readonly cause: string;
|
|
186
181
|
}): CliStructuredError {
|
|
187
|
-
return new CliStructuredError('
|
|
182
|
+
return new CliStructuredError('5010', `Failed to parse ${options.path}`, {
|
|
183
|
+
domain: 'CLI',
|
|
188
184
|
why: `\`${options.path}\` is not valid JSON: ${options.cause}`,
|
|
189
185
|
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\`.`,
|
|
190
186
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -210,7 +206,8 @@ export function errorInitInvalidTsconfig(options: {
|
|
|
210
206
|
readonly path: string;
|
|
211
207
|
readonly cause: string;
|
|
212
208
|
}): CliStructuredError {
|
|
213
|
-
return new CliStructuredError('
|
|
209
|
+
return new CliStructuredError('5011', `Failed to parse ${options.path}`, {
|
|
210
|
+
domain: 'CLI',
|
|
214
211
|
why: `\`${options.path}\` is not valid JSON or JSONC: ${options.cause}`,
|
|
215
212
|
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.`,
|
|
216
213
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -236,7 +233,8 @@ export function errorInitProbeFailed(options: {
|
|
|
236
233
|
readonly cause: string;
|
|
237
234
|
readonly filesWritten: readonly string[];
|
|
238
235
|
}): CliStructuredError {
|
|
239
|
-
return new CliStructuredError('
|
|
236
|
+
return new CliStructuredError('5012', 'Database probe failed', {
|
|
237
|
+
domain: 'CLI',
|
|
240
238
|
why: `\`--probe-db\` could not complete and \`--strict-probe\` was set: ${options.cause}`,
|
|
241
239
|
fix: 'Confirm `DATABASE_URL` points at a reachable server, or drop `--strict-probe` to treat probe failures as warnings.',
|
|
242
240
|
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
@@ -258,7 +256,8 @@ export function errorInitEmitFailed(options: {
|
|
|
258
256
|
readonly filesWritten: readonly string[];
|
|
259
257
|
readonly cause: string;
|
|
260
258
|
}): CliStructuredError {
|
|
261
|
-
return new CliStructuredError('
|
|
259
|
+
return new CliStructuredError('5008', 'Failed to emit contract', {
|
|
260
|
+
domain: 'CLI',
|
|
262
261
|
why: `\`prisma-next contract emit\` failed: ${options.cause}`,
|
|
263
262
|
fix: `Inspect your contract file, fix the underlying issue, then re-run \`${options.emitCommand}\`. Pass \`-v\` for the full error envelope.`,
|
|
264
263
|
docsUrl: 'https://prisma-next.dev/docs/cli/contract-emit',
|
|
@@ -285,21 +284,18 @@ export function errorInitSkillInstallFailed(options: {
|
|
|
285
284
|
readonly filesWritten: readonly string[];
|
|
286
285
|
readonly cause: string;
|
|
287
286
|
}): CliStructuredError {
|
|
288
|
-
return new CliStructuredError(
|
|
289
|
-
'CLI
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
skillInstallCommand: options.skillInstallCommand,
|
|
301
|
-
cause: options.cause,
|
|
302
|
-
},
|
|
287
|
+
return new CliStructuredError('5013', 'Failed to install Prisma Next skills', {
|
|
288
|
+
domain: 'CLI',
|
|
289
|
+
why: `\`${options.skillInstallCommand}\` exited with an error: ${options.cause}`,
|
|
290
|
+
fix:
|
|
291
|
+
'Either:\n' +
|
|
292
|
+
` - Re-run \`prisma-next init --no-skill${options.filesWritten.length > 0 ? ' --force' : ''}\` to skip the skill install for this run, or\n` +
|
|
293
|
+
` - Fix the underlying issue (network, npm registry, \`npx skills\` on PATH) and install manually:\n ${options.skillInstallCommand}`,
|
|
294
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init#skills',
|
|
295
|
+
meta: {
|
|
296
|
+
filesWritten: options.filesWritten,
|
|
297
|
+
skillInstallCommand: options.skillInstallCommand,
|
|
298
|
+
cause: options.cause,
|
|
303
299
|
},
|
|
304
|
-
);
|
|
300
|
+
});
|
|
305
301
|
}
|
|
@@ -534,21 +534,18 @@ 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
|
-
//
|
|
539
|
-
//
|
|
537
|
+
// 5009 regression would surface as an uncaught exception in
|
|
538
|
+
// commander instead of the documented `INTERNAL_ERROR` envelope on
|
|
539
|
+
// the right channel.
|
|
540
540
|
return emitError(
|
|
541
541
|
ui,
|
|
542
542
|
flags,
|
|
543
|
-
new CliStructuredError(
|
|
544
|
-
'CLI
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
550
|
-
},
|
|
551
|
-
),
|
|
543
|
+
new CliStructuredError('5009', 'Init produced an invalid output document', {
|
|
544
|
+
domain: 'CLI',
|
|
545
|
+
why: `The success document failed schema validation: ${String(validated)}`,
|
|
546
|
+
fix: 'This is a bug in prisma-next. Please report it with the full `-v` output.',
|
|
547
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
548
|
+
}),
|
|
552
549
|
);
|
|
553
550
|
}
|
|
554
551
|
|
|
@@ -585,10 +582,10 @@ function emitError(ui: TerminalUI, flags: GlobalFlags, error: CliStructuredError
|
|
|
585
582
|
* Maps a structured init error to its documented exit code. Centralised so
|
|
586
583
|
* the error → exit-code contract lives next to the codes themselves.
|
|
587
584
|
*
|
|
588
|
-
* `
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
585
|
+
* `5009` (and the unknown-code default branch) routes to
|
|
586
|
+
* `INIT_EXIT_INTERNAL_ERROR` because those represent prisma-next bugs the
|
|
587
|
+
* user did not cause — surfacing them as `PRECONDITION` would mislead
|
|
588
|
+
* automation into thinking the caller mis-invoked the CLI.
|
|
592
589
|
*
|
|
593
590
|
* See [exit-codes.ts](./exit-codes.ts) for the canonical list and
|
|
594
591
|
* [Style Guide § Exit Codes](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes)
|
|
@@ -599,24 +596,24 @@ function emitError(ui: TerminalUI, flags: GlobalFlags, error: CliStructuredError
|
|
|
599
596
|
*/
|
|
600
597
|
export function exitCodeForError(error: { readonly code: string }): number {
|
|
601
598
|
switch (error.code) {
|
|
602
|
-
case '
|
|
603
|
-
case '
|
|
604
|
-
case '
|
|
605
|
-
case '
|
|
606
|
-
case '
|
|
607
|
-
case '
|
|
608
|
-
case '
|
|
609
|
-
case '
|
|
599
|
+
case '5002': // re-init needs --force — precondition
|
|
600
|
+
case '5003': // missing flags — precondition
|
|
601
|
+
case '5004': // invalid flag value — precondition
|
|
602
|
+
case '5005': // --strict-probe without --probe-db — precondition
|
|
603
|
+
case '5010': // invalid manifest (malformed package.json) — precondition
|
|
604
|
+
case '5011': // invalid tsconfig (unparseable JSONC) — precondition
|
|
605
|
+
case '5012': // probe failed under --strict-probe — precondition
|
|
606
|
+
case '5014': // --authoring / --schema-path extension mismatch — precondition
|
|
610
607
|
return INIT_EXIT_PRECONDITION;
|
|
611
|
-
case '
|
|
608
|
+
case '5006': // user aborted interactive prompt
|
|
612
609
|
return INIT_EXIT_USER_ABORTED;
|
|
613
|
-
case '
|
|
610
|
+
case '5007': // install failed
|
|
614
611
|
return INIT_EXIT_INSTALL_FAILED;
|
|
615
|
-
case '
|
|
612
|
+
case '5008': // emit failed
|
|
616
613
|
return INIT_EXIT_EMIT_FAILED;
|
|
617
|
-
case '
|
|
614
|
+
case '5009': // invalid output document — internal bug in prisma-next
|
|
618
615
|
return INIT_EXIT_INTERNAL_ERROR;
|
|
619
|
-
case '
|
|
616
|
+
case '5013': // skill install failed
|
|
620
617
|
return INIT_EXIT_SKILL_INSTALL_FAILED;
|
|
621
618
|
default:
|
|
622
619
|
// 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: 'PN-MIG-CHECK-002',
|
|
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: 'PN-MIG-CHECK-005',
|
|
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: 'PN-MIG-CHECK-006',
|
|
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: 'PN-MIG-CHECK-003',
|
|
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: 'PN-MIG-CHECK-004',
|
|
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 (PN-RUN-3000) 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: 'PN-MIG-CHECK-001',
|
|
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.domain === 'MIG' && e.code === '2001') {
|
|
146
146
|
hasPlaceholders = true;
|
|
147
147
|
} else {
|
|
148
148
|
throw e;
|
|
@@ -286,9 +286,8 @@ 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
|
-
* `
|
|
291
|
-
* first orphan it finds, or `null`
|
|
289
|
+
* Returns a {@link CliStructuredError} envelope (code `5002`,
|
|
290
|
+
* `kind: 'orphanMarker'`) for the first orphan it finds, or `null`
|
|
292
291
|
* when every marker row maps to a declared contract space. Mirrors the M2
|
|
293
292
|
* `runContractSpaceVerifierMarkerCheck` envelope so downstream
|
|
294
293
|
* tooling (integration tests, JSON consumers) keeps asserting on the
|
|
@@ -314,7 +313,8 @@ function detectOrphanMarkers(
|
|
|
314
313
|
orphans.length === 1
|
|
315
314
|
? `Orphan contract-space marker detected for "${orphans[0]}"`
|
|
316
315
|
: `Orphan contract-space markers detected for ${orphans.length} spaces`;
|
|
317
|
-
return new CliStructuredError('
|
|
316
|
+
return new CliStructuredError('5002', summary, {
|
|
317
|
+
domain: 'MIG',
|
|
318
318
|
why: `The database has \`_prisma_marker\` rows for spaces (${orphans
|
|
319
319
|
.map((s) => `"${s}"`)
|
|
320
320
|
.join(
|
|
@@ -254,15 +254,12 @@ 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
|
-
|
|
263
|
-
docsUrl: 'https://pris.ly/contract-spaces',
|
|
264
|
-
},
|
|
265
|
-
),
|
|
257
|
+
new CliStructuredError('5002', 'Aggregate verifier introspection failed', {
|
|
258
|
+
domain: 'MIG',
|
|
259
|
+
why: verifyResult.failure.detail,
|
|
260
|
+
fix: 'Check database connectivity and the introspection tooling.',
|
|
261
|
+
docsUrl: 'https://pris.ly/contract-spaces',
|
|
262
|
+
}),
|
|
266
263
|
);
|
|
267
264
|
}
|
|
268
265
|
const markerError = skipMarker
|
|
@@ -303,8 +300,7 @@ function buildSkippedSchemaResult(space: AggregateContractSpace): VerifyDatabase
|
|
|
303
300
|
/**
|
|
304
301
|
* Translate per-space marker check failures and orphan markers into a
|
|
305
302
|
* single CLI structured error envelope. Preserves the legacy code
|
|
306
|
-
* `
|
|
307
|
-
* `runContractSpaceVerifierMarkerCheck`).
|
|
303
|
+
* `5002` (was emitted by `runContractSpaceVerifierMarkerCheck`).
|
|
308
304
|
*/
|
|
309
305
|
function mapMarkerCheckFailures(
|
|
310
306
|
appSpaceId: string,
|
|
@@ -358,7 +354,8 @@ function mapMarkerCheckFailures(
|
|
|
358
354
|
violations.length === 1
|
|
359
355
|
? 'Contract-space verifier found a violation'
|
|
360
356
|
: `Contract-space verifier found violations (${violations.length})`;
|
|
361
|
-
return new CliStructuredError('
|
|
357
|
+
return new CliStructuredError('5002', summary, {
|
|
358
|
+
domain: 'MIG',
|
|
362
359
|
why: `The on-disk \`migrations/\` directory, the \`extensionPacks\` declaration, and the live database marker rows are not in agreement.\n${lines.join('\n')}`,
|
|
363
360
|
fix: violations[0]?.remediation ?? 'Review and reconcile the violations listed above.',
|
|
364
361
|
docsUrl: 'https://pris.ly/contract-spaces',
|
package/src/control-api/types.ts
CHANGED
|
@@ -402,10 +402,7 @@ export interface DbInitSuccess {
|
|
|
402
402
|
/**
|
|
403
403
|
* Failure codes for dbInit operation.
|
|
404
404
|
*/
|
|
405
|
-
export type DbInitFailureCode =
|
|
406
|
-
| 'PLANNING_FAILED'
|
|
407
|
-
| 'MIGRATION.MARKER_ORIGIN_MISMATCH'
|
|
408
|
-
| 'RUNNER_FAILED';
|
|
405
|
+
export type DbInitFailureCode = 'PLANNING_FAILED' | 'MARKER_ORIGIN_MISMATCH' | 'RUNNER_FAILED';
|
|
409
406
|
|
|
410
407
|
/**
|
|
411
408
|
* 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
|
+
* (`PN-MIG-2006` 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` (`CLI
|
|
272
|
+
// `errorMigrationCliInvalidConfigArg` (`PN-CLI-4012`); 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
|
-
* `CLI
|
|
340
|
+
* `PN-CLI-4012` 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 CLI
|
|
428
|
+
* returned name is rendered into the user-visible PN-CLI-4013 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 `PN-MIG-2006` 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.
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -360,7 +360,7 @@ export function mapMigrationToolsError(error: MigrationToolsError): CliStructure
|
|
|
360
360
|
* Shared "needs a live database" precondition for read verbs that consult the
|
|
361
361
|
* marker/ledger (`migration log`, `migration status`). A command needs both a
|
|
362
362
|
* connection string and a control-plane driver; either missing yields the same
|
|
363
|
-
* `
|
|
363
|
+
* `PN-CLI-4005` envelope with `meta.missingFlags` (canonical long-form flags
|
|
364
364
|
* per CLI Style Guide §Errors) so callers can react programmatically. Returns
|
|
365
365
|
* `null` when both are present.
|
|
366
366
|
*/
|
|
@@ -78,7 +78,7 @@ export function combineVerifyResults(
|
|
|
78
78
|
return {
|
|
79
79
|
result: {
|
|
80
80
|
ok,
|
|
81
|
-
...(ok ? {} : { code: appResult.code ?? '
|
|
81
|
+
...(ok ? {} : { code: appResult.code ?? 'PN-RUN-3010' }),
|
|
82
82
|
summary,
|
|
83
83
|
contract: appResult.contract,
|
|
84
84
|
target: appResult.target,
|
|
@@ -20,7 +20,7 @@ import { toDeclaredExtensionsFromRaw } from './extension-pack-inputs';
|
|
|
20
20
|
|
|
21
21
|
const CONTRACT_SPACES_DOCS_URL = 'https://pris.ly/contract-spaces';
|
|
22
22
|
|
|
23
|
-
function
|
|
23
|
+
function contractSpaceError5002(
|
|
24
24
|
summary: string,
|
|
25
25
|
options: {
|
|
26
26
|
readonly why: string;
|
|
@@ -28,7 +28,8 @@ function contractSpaceViolationError(
|
|
|
28
28
|
readonly violations: readonly IntegrityViolation[];
|
|
29
29
|
},
|
|
30
30
|
): CliStructuredError {
|
|
31
|
-
return new CliStructuredError('
|
|
31
|
+
return new CliStructuredError('5002', summary, {
|
|
32
|
+
domain: 'MIG',
|
|
32
33
|
why: options.why,
|
|
33
34
|
fix: options.fix,
|
|
34
35
|
docsUrl: CONTRACT_SPACES_DOCS_URL,
|
|
@@ -37,7 +38,7 @@ function contractSpaceViolationError(
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
|
-
* Build the `
|
|
41
|
+
* Build the `5002` structured-error envelope for a contract-space
|
|
41
42
|
* target mismatch. Shared between the declared-extension precheck (the
|
|
42
43
|
* descriptor's configured target disagrees with the project target) and
|
|
43
44
|
* the on-disk-contract check surfaced by `checkIntegrity`.
|
|
@@ -47,7 +48,7 @@ function targetMismatchError(
|
|
|
47
48
|
expected: string,
|
|
48
49
|
actual: string,
|
|
49
50
|
): CliStructuredError {
|
|
50
|
-
return
|
|
51
|
+
return contractSpaceError5002(`Contract-space target mismatch for "${spaceId}"`, {
|
|
51
52
|
why: `Space "${spaceId}" targets "${actual}" but the project's adapter targets "${expected}".`,
|
|
52
53
|
fix: 'Update the extension descriptor to target the configured database, or change the project adapter.',
|
|
53
54
|
violations: [{ kind: 'targetMismatch', spaceId, expected, actual }],
|
|
@@ -88,10 +89,9 @@ function describeIntegrityViolation(violation: IntegrityViolation): string {
|
|
|
88
89
|
/**
|
|
89
90
|
* Map the integrity violations `checkIntegrity` reports into a single
|
|
90
91
|
* CLI structured-error envelope, preserving the error codes the prior
|
|
91
|
-
* throw-on-load loader emitted: `
|
|
92
|
-
* (
|
|
93
|
-
*
|
|
94
|
-
* `null` when there is nothing to refuse on.
|
|
92
|
+
* throw-on-load loader emitted: `5001` (layout drift, bundled) and
|
|
93
|
+
* `5002` (target / disjointness / contract-validation / structural
|
|
94
|
+
* integrity). Returns `null` when there is nothing to refuse on.
|
|
95
95
|
*
|
|
96
96
|
* Precedence reproduces the prior loader's first-failure ordering:
|
|
97
97
|
* layout drift first (every offence bundled into one envelope), then
|
|
@@ -113,7 +113,8 @@ export function mapIntegrityViolations(
|
|
|
113
113
|
layout.length === 1
|
|
114
114
|
? 'Contract-space layout violation detected'
|
|
115
115
|
: `Contract-space layout violations detected (${layout.length})`;
|
|
116
|
-
return new CliStructuredError('
|
|
116
|
+
return new CliStructuredError('5001', summary, {
|
|
117
|
+
domain: 'MIG',
|
|
117
118
|
why: `The on-disk \`migrations/\` directory and your \`extensionPacks\` declaration are not in agreement.\n${lines.join('\n')}`,
|
|
118
119
|
fix: 'Declare the extension in `extensionPacks` and re-emit its contract-space artefacts, or remove the orphan `migrations/<space>` directory.',
|
|
119
120
|
docsUrl: CONTRACT_SPACES_DOCS_URL,
|
|
@@ -132,7 +133,7 @@ export function mapIntegrityViolations(
|
|
|
132
133
|
|
|
133
134
|
const disjointness = violations.find((v) => v.kind === 'disjointness');
|
|
134
135
|
if (disjointness && disjointness.kind === 'disjointness') {
|
|
135
|
-
return
|
|
136
|
+
return contractSpaceError5002(
|
|
136
137
|
`Contract-space disjointness violation: storage element "${disjointness.element}" claimed by multiple spaces`,
|
|
137
138
|
{
|
|
138
139
|
why: `Spaces ${disjointness.claimedBy.map((s) => `"${s}"`).join(', ')} all claim the storage element "${disjointness.element}". Each storage element must be owned by exactly one contract space.`,
|
|
@@ -144,7 +145,7 @@ export function mapIntegrityViolations(
|
|
|
144
145
|
|
|
145
146
|
const contractUnreadable = violations.find((v) => v.kind === 'contractUnreadable');
|
|
146
147
|
if (contractUnreadable && contractUnreadable.kind === 'contractUnreadable') {
|
|
147
|
-
return
|
|
148
|
+
return contractSpaceError5002(
|
|
148
149
|
`Contract-space contract validation failed for "${contractUnreadable.spaceId}"`,
|
|
149
150
|
{
|
|
150
151
|
why: contractUnreadable.detail,
|
|
@@ -159,7 +160,7 @@ export function mapIntegrityViolations(
|
|
|
159
160
|
// is still computed; the gate just renders one envelope).
|
|
160
161
|
const structural = violations[0]!;
|
|
161
162
|
const spaceId = 'spaceId' in structural ? structural.spaceId : '*';
|
|
162
|
-
return
|
|
163
|
+
return contractSpaceError5002(`Contract-space integrity failure for "${spaceId}"`, {
|
|
163
164
|
why: describeIntegrityViolation(structural),
|
|
164
165
|
fix: 'Re-emit the affected migration package(s) or restore the on-disk `migrations/` directory from version control.',
|
|
165
166
|
violations: [structural],
|