@prisma-next/cli 0.10.0 → 0.11.0-dev.10
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 +1 -1
- package/dist/cli-errors-Bw2GlweY.mjs +175 -0
- package/dist/cli-errors-Bw2GlweY.mjs.map +1 -0
- package/dist/cli.mjs +400 -13
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-Brv4qlfB.mjs → client-UnIveZxZ.mjs} +6 -5
- package/dist/client-UnIveZxZ.mjs.map +1 -0
- package/dist/{command-helpers-D3vL5yi8.mjs → command-helpers-CRfjbZRz.mjs} +109 -12
- package/dist/command-helpers-CRfjbZRz.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +47 -21
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +6 -10
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.mjs +8 -12
- 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 +47 -19
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +5 -1
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +47 -15
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.mjs +5 -8
- package/dist/commands/migration-check.mjs.map +1 -1
- package/dist/commands/migration-graph.d.mts +1 -1
- package/dist/commands/migration-graph.mjs +6 -10
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.mjs +5 -9
- package/dist/commands/migration-list.mjs.map +1 -1
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +7 -10
- package/dist/commands/migration-log.mjs.map +1 -1
- package/dist/commands/migration-new.mjs +6 -10
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +2 -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 +1 -1
- package/dist/commands/migration-show.mjs +9 -13
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +1 -1
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +37 -15
- package/dist/commands/migration-status.mjs.map +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +41 -25
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/{contract-emit-iynA3BCA.mjs → contract-emit-C6rlsljO.mjs} +7 -6
- package/dist/contract-emit-C6rlsljO.mjs.map +1 -0
- package/dist/{contract-emit-C3STUIBg.mjs → contract-emit-mqXmapxB.mjs} +22 -20
- package/dist/contract-emit-mqXmapxB.mjs.map +1 -0
- package/dist/{contract-infer-Cnj8G1E2.mjs → contract-infer-C4jxc1aZ.mjs} +9 -14
- package/dist/contract-infer-C4jxc1aZ.mjs.map +1 -0
- package/dist/{contract-space-aggregate-loader-pAc8CDfY.mjs → contract-space-aggregate-loader-CGakRlKM.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-pAc8CDfY.mjs.map → contract-space-aggregate-loader-CGakRlKM.mjs.map} +1 -1
- package/dist/{db-verify-D7cyH_zz.mjs → db-verify-1d8tDoFN.mjs} +9 -13
- package/dist/db-verify-1d8tDoFN.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/exports/init-output.mjs +1 -1
- package/dist/{framework-components-xFLFpZUO.mjs → framework-components-Bexd0f4E.mjs} +2 -2
- package/dist/{framework-components-xFLFpZUO.mjs.map → framework-components-Bexd0f4E.mjs.map} +1 -1
- package/dist/{global-flags-DGmw6Kqg.d.mts → global-flags-CdE7M0d9.d.mts} +4 -1
- package/dist/global-flags-CdE7M0d9.d.mts.map +1 -0
- package/dist/{graph-render-eJDcLWny.mjs → graph-render-BE8vmJ_7.mjs} +1 -1
- package/dist/{graph-render-eJDcLWny.mjs.map → graph-render-BE8vmJ_7.mjs.map} +1 -1
- package/dist/{init-eh2z5Tl6.mjs → init-ByoeQphC.mjs} +528 -627
- package/dist/init-ByoeQphC.mjs.map +1 -0
- package/dist/{inspect-live-schema-CWLK_lgs.mjs → inspect-live-schema-B1Q49RF0.mjs} +4 -4
- package/dist/{inspect-live-schema-CWLK_lgs.mjs.map → inspect-live-schema-B1Q49RF0.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs → migration-command-scaffold-oY4P1Qto.mjs} +4 -4
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs.map → migration-command-scaffold-oY4P1Qto.mjs.map} +1 -1
- package/dist/{migration-plan-CHyUlBV0.mjs → migration-plan-jdAHg_gK.mjs} +349 -94
- package/dist/migration-plan-jdAHg_gK.mjs.map +1 -0
- package/dist/{migration-types-D2FW63pr.d.mts → migration-types-BXWvz12q.d.mts} +1 -1
- package/dist/{migration-types-D2FW63pr.d.mts.map → migration-types-BXWvz12q.d.mts.map} +1 -1
- package/dist/{migrations-DyUf5lTt.mjs → migrations-B7n518mT.mjs} +11 -2
- package/dist/migrations-B7n518mT.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-CUIdfYo5.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-CUIdfYo5.mjs.map} +1 -1
- package/dist/quick-reference-mongo.md +1 -1
- package/dist/quick-reference-postgres.md +1 -1
- package/dist/readme-mongo.md +35 -0
- package/dist/readme-postgres.md +34 -0
- package/dist/ref-advancement-DRh5Nquq.mjs +50 -0
- package/dist/ref-advancement-DRh5Nquq.mjs.map +1 -0
- package/dist/{terminal-ui-XtOQsqe9.mjs → terminal-ui-BiB_8KNo.mjs} +131 -24
- package/dist/terminal-ui-BiB_8KNo.mjs.map +1 -0
- package/dist/{types-0aS865QN.d.mts → types-UWB2-rrw.d.mts} +12 -4
- package/dist/types-UWB2-rrw.d.mts.map +1 -0
- package/dist/{verify-D7ypCCe6.mjs → verify-C5UvbrF1.mjs} +2 -2
- package/dist/{verify-D7ypCCe6.mjs.map → verify-C5UvbrF1.mjs.map} +1 -1
- package/package.json +20 -18
- package/src/cli.ts +42 -0
- package/src/commands/contract-emit.ts +23 -11
- package/src/commands/contract-infer.ts +7 -7
- package/src/commands/db-init.ts +61 -7
- package/src/commands/db-schema.ts +4 -4
- package/src/commands/db-sign.ts +4 -4
- package/src/commands/db-update.ts +58 -5
- package/src/commands/db-verify.ts +5 -5
- package/src/commands/init/detect-package-manager.ts +15 -0
- package/src/commands/init/errors.ts +33 -2
- package/src/commands/init/hygiene-gitattributes.ts +2 -2
- package/src/commands/init/index.ts +15 -6
- package/src/commands/init/init.ts +61 -32
- package/src/commands/init/inputs.ts +82 -5
- package/src/commands/init/output.ts +1 -1
- package/src/commands/init/{agent-skill-install.ts → skill-install.ts} +42 -31
- package/src/commands/init/templates/code-templates.ts +26 -24
- package/src/commands/init/templates/env.ts +8 -1
- package/src/commands/init/templates/quick-reference-mongo.md +1 -1
- package/src/commands/init/templates/quick-reference-postgres.md +1 -1
- package/src/commands/init/templates/readme-mongo.md +35 -0
- package/src/commands/init/templates/readme-postgres.md +34 -0
- package/src/commands/init/templates/readme.ts +62 -0
- package/src/commands/migrate.ts +77 -10
- package/src/commands/migration-check.ts +4 -4
- package/src/commands/migration-graph.ts +4 -4
- package/src/commands/migration-list.ts +4 -4
- package/src/commands/migration-log.ts +6 -5
- package/src/commands/migration-new.ts +4 -4
- package/src/commands/migration-plan.ts +369 -132
- package/src/commands/migration-show.ts +4 -4
- package/src/commands/migration-status.ts +49 -6
- package/src/commands/ref.ts +54 -14
- package/src/control-api/operations/apply-aggregate.ts +1 -0
- package/src/control-api/operations/contract-emit.ts +7 -4
- package/src/control-api/types.ts +7 -0
- package/src/utils/cli-errors.ts +177 -0
- package/src/utils/command-helpers.ts +14 -6
- package/src/utils/formatters/migrations.ts +25 -0
- package/src/utils/global-flags.ts +105 -16
- package/src/utils/is-ci.ts +18 -0
- package/src/utils/plan-resolution.ts +257 -0
- package/src/utils/ref-advancement.ts +68 -0
- package/src/utils/telemetry.ts +141 -0
- package/src/utils/terminal-ui.ts +44 -23
- package/dist/cli-errors-CF60g2cG.mjs +0 -71
- package/dist/cli-errors-CF60g2cG.mjs.map +0 -1
- package/dist/cli-errors-DdcjVLJV.d.mts +0 -3
- package/dist/client-Brv4qlfB.mjs.map +0 -1
- package/dist/command-helpers-D3vL5yi8.mjs.map +0 -1
- package/dist/contract-emit-C3STUIBg.mjs.map +0 -1
- package/dist/contract-emit-iynA3BCA.mjs.map +0 -1
- package/dist/contract-infer-Cnj8G1E2.mjs.map +0 -1
- package/dist/db-verify-D7cyH_zz.mjs.map +0 -1
- package/dist/errors-Cw6kyTyV.mjs +0 -56
- package/dist/errors-Cw6kyTyV.mjs.map +0 -1
- package/dist/global-flags-DGmw6Kqg.d.mts.map +0 -1
- package/dist/helpers-eqdN8tH6.mjs +0 -25
- package/dist/helpers-eqdN8tH6.mjs.map +0 -1
- package/dist/init-eh2z5Tl6.mjs.map +0 -1
- package/dist/migration-plan-CHyUlBV0.mjs.map +0 -1
- package/dist/migrations-DyUf5lTt.mjs.map +0 -1
- package/dist/result-handler-Bm_6dDYg.mjs +0 -25
- package/dist/result-handler-Bm_6dDYg.mjs.map +0 -1
- package/dist/terminal-ui-XtOQsqe9.mjs.map +0 -1
- package/dist/types-0aS865QN.d.mts.map +0 -1
package/src/cli.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { setCommandDescriptions } from './utils/command-helpers';
|
|
|
27
27
|
import { formatCommandHelp, formatRootHelp } from './utils/formatters/help';
|
|
28
28
|
import { parseGlobalFlags } from './utils/global-flags';
|
|
29
29
|
import { suggestCommands } from './utils/suggest-command';
|
|
30
|
+
import { fireTelemetryFromPreAction } from './utils/telemetry';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Lookup table mapping removed subcommands to their replacement verbs.
|
|
@@ -68,6 +69,21 @@ const program = new Command();
|
|
|
68
69
|
|
|
69
70
|
program.name('prisma-next').description('Prisma Next CLI').version(packageJson.version);
|
|
70
71
|
|
|
72
|
+
// Telemetry hook — fires at command start, before the action body
|
|
73
|
+
// runs. Synchronous by construction: `fireTelemetryFromPreAction`
|
|
74
|
+
// resolves gates (cheap), then `fork()`s the detached sender. The
|
|
75
|
+
// fork is enqueued before the action body runs at all, so the child
|
|
76
|
+
// survives even when the action throws synchronously. The try/catch
|
|
77
|
+
// is defence-in-depth — `runTelemetry` already swallows every failure
|
|
78
|
+
// mode internally and returns an outcome instead of throwing.
|
|
79
|
+
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
80
|
+
try {
|
|
81
|
+
fireTelemetryFromPreAction(actionCommand);
|
|
82
|
+
} catch {
|
|
83
|
+
// defence-in-depth — runTelemetry already swallows internally.
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
71
87
|
// Override version option description to match capitalization style
|
|
72
88
|
const versionOption = program.options.find((opt) => opt.flags.includes('--version'));
|
|
73
89
|
if (versionOption) {
|
|
@@ -302,6 +318,32 @@ program.addCommand(dbCommand);
|
|
|
302
318
|
program.addCommand(migrationCommand);
|
|
303
319
|
program.addCommand(refCommand);
|
|
304
320
|
|
|
321
|
+
// Test-only hidden command used by `cli-telemetry`'s `cli-e2e.test.ts`
|
|
322
|
+
// to verify that telemetry still lands when a CLI command crashes
|
|
323
|
+
// mid-execution. The preAction hook is synchronous and `fork()`s the
|
|
324
|
+
// detached sender before this action body runs; the small sleep
|
|
325
|
+
// gives the IPC `child.send()` a tick to flush before the throw
|
|
326
|
+
// triggers commander's `exitOverride` and `process.exit(1)`. Hidden
|
|
327
|
+
// from help; underscore prefix marks it as internal. Doesn't depend
|
|
328
|
+
// on any project state, so it runs in any tempdir.
|
|
329
|
+
//
|
|
330
|
+
// Gated behind `PRISMA_NEXT_ENABLE_TEST_COMMANDS=1` so the command is
|
|
331
|
+
// not even registered (and therefore not invocable) in shipped
|
|
332
|
+
// binaries. `hidden: true` only filters the help output; without this
|
|
333
|
+
// env gate the command would still be callable from production. The
|
|
334
|
+
// e2e suite sets the env var when it spawns the CLI.
|
|
335
|
+
const TELEMETRY_CRASH_TEST_SLEEP_MS = 200;
|
|
336
|
+
if (process.env['PRISMA_NEXT_ENABLE_TEST_COMMANDS'] === '1') {
|
|
337
|
+
const telemetryCrashTestCommand = new Command('__telemetry-crash-test')
|
|
338
|
+
.description('Internal: deliberately throw for the telemetry e2e suite.')
|
|
339
|
+
.action(async () => {
|
|
340
|
+
await new Promise((settle) => setTimeout(settle, TELEMETRY_CRASH_TEST_SLEEP_MS));
|
|
341
|
+
throw new Error('__telemetry-crash-test: intentional crash for e2e coverage');
|
|
342
|
+
});
|
|
343
|
+
telemetryCrashTestCommand.configureHelp({ visibleCommands: () => [] });
|
|
344
|
+
program.addCommand(telemetryCrashTestCommand, { hidden: true });
|
|
345
|
+
}
|
|
346
|
+
|
|
305
347
|
// Create help command
|
|
306
348
|
const helpCommand = new Command('help')
|
|
307
349
|
.description('Show usage instructions')
|
|
@@ -3,7 +3,7 @@ import { errorContractConfigMissing } from '@prisma-next/errors/control';
|
|
|
3
3
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
4
4
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
-
import { dirname, relative, resolve } from 'pathe';
|
|
6
|
+
import { dirname, join, relative, resolve } from 'pathe';
|
|
7
7
|
import { loadConfig } from '../config-loader';
|
|
8
8
|
import { executeContractEmit } from '../control-api/operations/contract-emit';
|
|
9
9
|
import type { ContractEmitResult } from '../control-api/types';
|
|
@@ -20,13 +20,14 @@ import {
|
|
|
20
20
|
} from '../utils/formatters/emit';
|
|
21
21
|
import { formatStyledHeader, formatSuccessMessage } from '../utils/formatters/styled';
|
|
22
22
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
23
|
-
import { type GlobalFlags,
|
|
23
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
24
24
|
import { createProgressAdapter } from '../utils/progress-adapter';
|
|
25
25
|
import { handleResult } from '../utils/result-handler';
|
|
26
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
26
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
27
27
|
|
|
28
28
|
interface ContractEmitOptions extends CommonCommandOptions {
|
|
29
29
|
readonly config?: string;
|
|
30
|
+
readonly outputPath?: string;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
interface HeaderPaths {
|
|
@@ -43,6 +44,7 @@ interface HeaderPaths {
|
|
|
43
44
|
*/
|
|
44
45
|
async function resolveHeaderPaths(
|
|
45
46
|
configOption: string | undefined,
|
|
47
|
+
outputPath: string | undefined,
|
|
46
48
|
): Promise<Result<HeaderPaths, CliStructuredError>> {
|
|
47
49
|
const displayConfigPath = configOption
|
|
48
50
|
? relative(process.cwd(), resolve(configOption))
|
|
@@ -62,7 +64,10 @@ async function resolveHeaderPaths(
|
|
|
62
64
|
);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
const effectiveJsonPath =
|
|
68
|
+
outputPath !== undefined ? join(outputPath, 'contract.json') : config.contract?.output;
|
|
69
|
+
|
|
70
|
+
if (!effectiveJsonPath) {
|
|
66
71
|
return notOk(
|
|
67
72
|
errorContractConfigMissing({
|
|
68
73
|
why: 'Config.contract.output is required for emit. Define it in your config: contract: { source: ..., output: ... }',
|
|
@@ -71,9 +76,8 @@ async function resolveHeaderPaths(
|
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
try {
|
|
74
|
-
const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } =
|
|
75
|
-
|
|
76
|
-
);
|
|
79
|
+
const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } =
|
|
80
|
+
getEmittedArtifactPaths(effectiveJsonPath);
|
|
77
81
|
return ok({ displayConfigPath, outputJsonPath, outputDtsPath });
|
|
78
82
|
} catch (error) {
|
|
79
83
|
return notOk(
|
|
@@ -90,7 +94,9 @@ async function executeContractEmitCommand(
|
|
|
90
94
|
ui: TerminalUI,
|
|
91
95
|
startTime: number,
|
|
92
96
|
): Promise<Result<EmitContractResult, CliStructuredError>> {
|
|
93
|
-
const
|
|
97
|
+
const outputPath = options.outputPath !== undefined ? resolve(options.outputPath) : undefined;
|
|
98
|
+
|
|
99
|
+
const headerPathsResult = await resolveHeaderPaths(options.config, outputPath);
|
|
94
100
|
if (!headerPathsResult.ok) {
|
|
95
101
|
return headerPathsResult;
|
|
96
102
|
}
|
|
@@ -117,7 +123,11 @@ async function executeContractEmitCommand(
|
|
|
117
123
|
|
|
118
124
|
let result: ContractEmitResult;
|
|
119
125
|
try {
|
|
120
|
-
result = await executeContractEmit({
|
|
126
|
+
result = await executeContractEmit({
|
|
127
|
+
configPath,
|
|
128
|
+
onProgress,
|
|
129
|
+
...ifDefined('outputPath', outputPath),
|
|
130
|
+
});
|
|
121
131
|
} catch (error) {
|
|
122
132
|
if (CliStructuredError.is(error)) {
|
|
123
133
|
return notOk(error);
|
|
@@ -155,12 +165,14 @@ export function createContractEmitCommand(): Command {
|
|
|
155
165
|
setCommandExamples(command, [
|
|
156
166
|
'prisma-next contract emit',
|
|
157
167
|
'prisma-next contract emit --config ./custom-config.ts',
|
|
168
|
+
'prisma-next contract emit --output-path ./generated',
|
|
158
169
|
]);
|
|
159
170
|
addGlobalOptions(command)
|
|
160
171
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
172
|
+
.option('--output-path <dir>', 'Directory to write contract.json and contract.d.ts into')
|
|
161
173
|
.action(async (options: ContractEmitOptions) => {
|
|
162
|
-
const flags =
|
|
163
|
-
const ui =
|
|
174
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
175
|
+
const ui = createTerminalUI(flags);
|
|
164
176
|
const startTime = Date.now();
|
|
165
177
|
|
|
166
178
|
const result = await executeContractEmitCommand(options, flags, ui, startTime);
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
setCommandDescriptions,
|
|
11
11
|
setCommandExamples,
|
|
12
12
|
} from '../utils/command-helpers';
|
|
13
|
-
import {
|
|
13
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
14
14
|
import { handleResult } from '../utils/result-handler';
|
|
15
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
15
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
16
16
|
import { resolveContractInferOutputPath } from './contract-infer-paths';
|
|
17
17
|
import {
|
|
18
18
|
type InspectLiveSchemaOptions,
|
|
@@ -39,10 +39,10 @@ interface ContractInferSuccessResult {
|
|
|
39
39
|
|
|
40
40
|
async function executeContractInferCommand(
|
|
41
41
|
options: ContractInferOptions,
|
|
42
|
+
flags: GlobalFlags,
|
|
42
43
|
ui: TerminalUI,
|
|
43
44
|
startTime: number,
|
|
44
45
|
): Promise<Result<ContractInferSuccessResult, CliStructuredError>> {
|
|
45
|
-
const flags = parseGlobalFlags(options);
|
|
46
46
|
const inspectResult = await inspectLiveSchema(options, flags, ui, startTime, {
|
|
47
47
|
commandName: 'contract infer',
|
|
48
48
|
description: 'Infer a PSL contract from the live database schema',
|
|
@@ -104,7 +104,7 @@ export function createContractInferCommand(): Command {
|
|
|
104
104
|
);
|
|
105
105
|
setCommandExamples(command, [
|
|
106
106
|
'prisma-next contract infer --db $DATABASE_URL',
|
|
107
|
-
'prisma-next contract infer --db $DATABASE_URL --output ./prisma/contract.prisma',
|
|
107
|
+
'prisma-next contract infer --db $DATABASE_URL --output ./src/prisma/contract.prisma',
|
|
108
108
|
'prisma-next contract infer --db $DATABASE_URL --json',
|
|
109
109
|
]);
|
|
110
110
|
addGlobalOptions(command)
|
|
@@ -112,11 +112,11 @@ export function createContractInferCommand(): Command {
|
|
|
112
112
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
113
113
|
.option('--output <path>', 'Write the inferred PSL contract to the specified path')
|
|
114
114
|
.action(async (options: ContractInferOptions) => {
|
|
115
|
-
const flags =
|
|
116
|
-
const ui =
|
|
115
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
116
|
+
const ui = createTerminalUI(flags);
|
|
117
117
|
const startTime = Date.now();
|
|
118
118
|
|
|
119
|
-
const result = await executeContractInferCommand(options, ui, startTime);
|
|
119
|
+
const result = await executeContractInferCommand(options, flags, ui, startTime);
|
|
120
120
|
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
121
121
|
if (flags.json) {
|
|
122
122
|
ui.output(JSON.stringify(value, null, 2));
|
package/src/commands/db-init.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
1
2
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
2
3
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
4
|
import { Command } from 'commander';
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
errorRunnerFailed,
|
|
11
12
|
errorRuntime,
|
|
12
13
|
errorUnexpected,
|
|
14
|
+
mapMigrationToolsError,
|
|
13
15
|
} from '../utils/cli-errors';
|
|
14
16
|
import type { MigrationCommandOptions } from '../utils/command-helpers';
|
|
15
17
|
import {
|
|
@@ -24,15 +26,23 @@ import {
|
|
|
24
26
|
formatMigrationPlanOutput,
|
|
25
27
|
type MigrationCommandResult,
|
|
26
28
|
} from '../utils/formatters/migrations';
|
|
27
|
-
import { type GlobalFlags,
|
|
29
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
28
30
|
import {
|
|
29
31
|
addMigrationCommandOptions,
|
|
30
32
|
prepareMigrationContext,
|
|
31
33
|
} from '../utils/migration-command-scaffold';
|
|
34
|
+
import {
|
|
35
|
+
buildRefAdvancementFields,
|
|
36
|
+
computeRefAdvancementName,
|
|
37
|
+
type RefAdvancementFields,
|
|
38
|
+
readContractIR,
|
|
39
|
+
} from '../utils/ref-advancement';
|
|
32
40
|
import { handleResult } from '../utils/result-handler';
|
|
33
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
41
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
interface DbInitOptions extends MigrationCommandOptions {
|
|
44
|
+
readonly advanceRef?: string;
|
|
45
|
+
}
|
|
36
46
|
|
|
37
47
|
/**
|
|
38
48
|
* Maps a DbInitFailure to a CliStructuredError for consistent error handling.
|
|
@@ -80,9 +90,17 @@ function mapDbInitFailure(failure: DbInitFailure): CliStructuredError {
|
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
if (failure.code === 'RUNNER_FAILED') {
|
|
93
|
+
const runnerCode =
|
|
94
|
+
typeof failure.meta?.['runnerErrorCode'] === 'string'
|
|
95
|
+
? failure.meta['runnerErrorCode']
|
|
96
|
+
: undefined;
|
|
97
|
+
const fix =
|
|
98
|
+
runnerCode === 'LEGACY_MARKER_SHAPE'
|
|
99
|
+
? 'Legacy marker-table shape detected. Drop `prisma_contract.marker` (Postgres) or `_prisma_marker` (SQLite) and re-run `prisma-next db init` to recreate it with the current per-space schema.'
|
|
100
|
+
: 'Fix the schema mismatch (db init is additive-only), or drop/reset the database and re-run `prisma-next db init`';
|
|
83
101
|
return errorRunnerFailed(failure.summary, {
|
|
84
102
|
why: failure.why ?? 'Migration runner failed',
|
|
85
|
-
fix
|
|
103
|
+
fix,
|
|
86
104
|
...(failure.meta
|
|
87
105
|
? { meta: { code: 'RUNNER_FAILED', ...failure.meta } }
|
|
88
106
|
: { meta: { code: 'RUNNER_FAILED' } }),
|
|
@@ -120,7 +138,7 @@ async function executeDbInitCommand(
|
|
|
120
138
|
// per-space precheck + marker-check helpers are no longer needed at
|
|
121
139
|
// this surface. Marker-vs-on-disk drift surfaces through the planner's
|
|
122
140
|
// graph-walk strategy.
|
|
123
|
-
const { migrationsDir } = resolveMigrationPaths(options.config, config);
|
|
141
|
+
const { migrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
|
|
124
142
|
|
|
125
143
|
try {
|
|
126
144
|
await client.connect(dbConnection);
|
|
@@ -137,6 +155,39 @@ async function executeDbInitCommand(
|
|
|
137
155
|
return notOk(mapDbInitFailure(result.failure));
|
|
138
156
|
}
|
|
139
157
|
|
|
158
|
+
const advancementHash =
|
|
159
|
+
result.value.mode === 'apply'
|
|
160
|
+
? (result.value.marker?.storageHash ?? result.value.destination.storageHash)
|
|
161
|
+
: result.value.destination.storageHash;
|
|
162
|
+
|
|
163
|
+
let refAdvancementFields: RefAdvancementFields = {
|
|
164
|
+
advancedRef: null,
|
|
165
|
+
plannedAdvanceRef: null,
|
|
166
|
+
};
|
|
167
|
+
if (
|
|
168
|
+
computeRefAdvancementName({
|
|
169
|
+
...ifDefined('advanceRef', options.advanceRef),
|
|
170
|
+
...ifDefined('db', options.db),
|
|
171
|
+
}) !== null
|
|
172
|
+
) {
|
|
173
|
+
try {
|
|
174
|
+
const contractIR = await readContractIR(contractJson, contractPathAbsolute);
|
|
175
|
+
refAdvancementFields = await buildRefAdvancementFields({
|
|
176
|
+
...ifDefined('advanceRef', options.advanceRef),
|
|
177
|
+
...ifDefined('db', options.db),
|
|
178
|
+
refsDir,
|
|
179
|
+
contractIR,
|
|
180
|
+
mode: result.value.mode,
|
|
181
|
+
hash: advancementHash,
|
|
182
|
+
});
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (MigrationToolsError.is(error)) {
|
|
185
|
+
return notOk(mapMigrationToolsError(error));
|
|
186
|
+
}
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
140
191
|
// Convert success result to CLI output format
|
|
141
192
|
const dbInitResult: MigrationCommandResult = {
|
|
142
193
|
ok: true,
|
|
@@ -171,6 +222,8 @@ async function executeDbInitCommand(
|
|
|
171
222
|
}
|
|
172
223
|
: {}),
|
|
173
224
|
...ifDefined('perSpace', result.value.perSpace),
|
|
225
|
+
advancedRef: refAdvancementFields.advancedRef,
|
|
226
|
+
plannedAdvanceRef: refAdvancementFields.plannedAdvanceRef,
|
|
174
227
|
summary: result.value.summary,
|
|
175
228
|
timings: { total: Date.now() - startTime },
|
|
176
229
|
};
|
|
@@ -221,11 +274,12 @@ export function createDbInitCommand(): Command {
|
|
|
221
274
|
'prisma-next db init --db $DATABASE_URL --dry-run',
|
|
222
275
|
]);
|
|
223
276
|
addMigrationCommandOptions(command);
|
|
277
|
+
command.option('--advance-ref <name>', 'Ref to advance to the post-command contract hash');
|
|
224
278
|
command.action(async (options: DbInitOptions) => {
|
|
225
|
-
const flags =
|
|
279
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
226
280
|
const startTime = Date.now();
|
|
227
281
|
|
|
228
|
-
const ui =
|
|
282
|
+
const ui = createTerminalUI(flags);
|
|
229
283
|
|
|
230
284
|
const result = await executeDbInitCommand(options, flags, ui, startTime);
|
|
231
285
|
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
setCommandExamples,
|
|
7
7
|
} from '../utils/command-helpers';
|
|
8
8
|
import { formatIntrospectJson, formatIntrospectOutput } from '../utils/formatters/verify';
|
|
9
|
-
import {
|
|
9
|
+
import { parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
10
10
|
import { handleResult } from '../utils/result-handler';
|
|
11
|
-
import {
|
|
11
|
+
import { createTerminalUI } from '../utils/terminal-ui';
|
|
12
12
|
import {
|
|
13
13
|
type InspectLiveSchemaOptions,
|
|
14
14
|
type InspectLiveSchemaResult,
|
|
@@ -46,8 +46,8 @@ export function createDbSchemaCommand(): Command {
|
|
|
46
46
|
.option('--db <url>', 'Database connection string')
|
|
47
47
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
48
48
|
.action(async (options: InspectLiveSchemaOptions) => {
|
|
49
|
-
const flags =
|
|
50
|
-
const ui =
|
|
49
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
50
|
+
const ui = createTerminalUI(flags);
|
|
51
51
|
const startTime = Date.now();
|
|
52
52
|
|
|
53
53
|
const result = await inspectLiveSchema(options, flags, ui, startTime, {
|
package/src/commands/db-sign.ts
CHANGED
|
@@ -40,10 +40,10 @@ import {
|
|
|
40
40
|
formatSignOutput,
|
|
41
41
|
} from '../utils/formatters/verify';
|
|
42
42
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
43
|
-
import { type GlobalFlags,
|
|
43
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
44
44
|
import { createProgressAdapter } from '../utils/progress-adapter';
|
|
45
45
|
import { handleResult } from '../utils/result-handler';
|
|
46
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
46
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
47
47
|
|
|
48
48
|
interface DbSignOptions extends CommonCommandOptions {
|
|
49
49
|
readonly db?: string;
|
|
@@ -270,7 +270,7 @@ export function createDbSignCommand(): Command {
|
|
|
270
270
|
'Contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
|
|
271
271
|
)
|
|
272
272
|
.action(async (positionalContract: string | undefined, options: DbSignOptions) => {
|
|
273
|
-
const flags =
|
|
273
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
274
274
|
|
|
275
275
|
if (positionalContract && options.contract) {
|
|
276
276
|
process.stderr.write(
|
|
@@ -280,7 +280,7 @@ export function createDbSignCommand(): Command {
|
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
const ui =
|
|
283
|
+
const ui = createTerminalUI(flags);
|
|
284
284
|
|
|
285
285
|
const result = await executeDbSignCommand(positionalContract, options, flags, ui);
|
|
286
286
|
|
|
@@ -33,16 +33,23 @@ import {
|
|
|
33
33
|
formatMigrationPlanOutput,
|
|
34
34
|
type MigrationCommandResult,
|
|
35
35
|
} from '../utils/formatters/migrations';
|
|
36
|
-
import { type GlobalFlags,
|
|
36
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
37
37
|
import {
|
|
38
38
|
addMigrationCommandOptions,
|
|
39
39
|
prepareMigrationContext,
|
|
40
40
|
} from '../utils/migration-command-scaffold';
|
|
41
|
+
import {
|
|
42
|
+
buildRefAdvancementFields,
|
|
43
|
+
computeRefAdvancementName,
|
|
44
|
+
type RefAdvancementFields,
|
|
45
|
+
readContractIR,
|
|
46
|
+
} from '../utils/ref-advancement';
|
|
41
47
|
import { handleResult } from '../utils/result-handler';
|
|
42
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
48
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
43
49
|
|
|
44
50
|
interface DbUpdateOptions extends MigrationCommandOptions {
|
|
45
51
|
readonly to?: string;
|
|
52
|
+
readonly advanceRef?: string;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
/**
|
|
@@ -54,9 +61,17 @@ function mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {
|
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
if (failure.code === 'RUNNER_FAILED') {
|
|
64
|
+
const runnerCode =
|
|
65
|
+
typeof failure.meta?.['runnerErrorCode'] === 'string'
|
|
66
|
+
? failure.meta['runnerErrorCode']
|
|
67
|
+
: undefined;
|
|
68
|
+
const fix =
|
|
69
|
+
runnerCode === 'LEGACY_MARKER_SHAPE'
|
|
70
|
+
? 'Legacy marker-table shape detected. Drop `prisma_contract.marker` (Postgres) or `_prisma_marker` (SQLite) and re-run `prisma-next db init` to recreate it with the current per-space schema.'
|
|
71
|
+
: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`';
|
|
57
72
|
return errorRunnerFailed(failure.summary, {
|
|
58
73
|
why: failure.why ?? 'Migration runner failed',
|
|
59
|
-
fix
|
|
74
|
+
fix,
|
|
60
75
|
...ifDefined('meta', failure.meta),
|
|
61
76
|
});
|
|
62
77
|
}
|
|
@@ -93,6 +108,7 @@ async function executeDbUpdateCommand(
|
|
|
93
108
|
}
|
|
94
109
|
const { client, config, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;
|
|
95
110
|
let { contractJson } = ctxResult.value;
|
|
111
|
+
let contractJsonPathForSnapshot = contractPathAbsolute;
|
|
96
112
|
const { migrationsDir, appMigrationsDir, refsDir } = resolveMigrationPaths(
|
|
97
113
|
options.config,
|
|
98
114
|
config,
|
|
@@ -122,6 +138,7 @@ async function executeDbUpdateCommand(
|
|
|
122
138
|
const endContractPath = join(matchingBundle.dirPath, 'end-contract.json');
|
|
123
139
|
const raw = await readFile(endContractPath, 'utf-8');
|
|
124
140
|
contractJson = JSON.parse(raw) as Record<string, unknown>;
|
|
141
|
+
contractJsonPathForSnapshot = endContractPath;
|
|
125
142
|
} catch (error) {
|
|
126
143
|
if (MigrationToolsError.is(error)) {
|
|
127
144
|
return notOk(mapMigrationToolsError(error));
|
|
@@ -149,6 +166,39 @@ async function executeDbUpdateCommand(
|
|
|
149
166
|
return notOk(mapDbUpdateFailure(result.failure));
|
|
150
167
|
}
|
|
151
168
|
|
|
169
|
+
const advancementHash =
|
|
170
|
+
result.value.mode === 'apply'
|
|
171
|
+
? (result.value.marker?.storageHash ?? result.value.destination.storageHash)
|
|
172
|
+
: result.value.destination.storageHash;
|
|
173
|
+
|
|
174
|
+
let refAdvancementFields: RefAdvancementFields = {
|
|
175
|
+
advancedRef: null,
|
|
176
|
+
plannedAdvanceRef: null,
|
|
177
|
+
};
|
|
178
|
+
if (
|
|
179
|
+
computeRefAdvancementName({
|
|
180
|
+
...ifDefined('advanceRef', options.advanceRef),
|
|
181
|
+
...ifDefined('db', options.db),
|
|
182
|
+
}) !== null
|
|
183
|
+
) {
|
|
184
|
+
try {
|
|
185
|
+
const contractIR = await readContractIR(contractJson, contractJsonPathForSnapshot);
|
|
186
|
+
refAdvancementFields = await buildRefAdvancementFields({
|
|
187
|
+
...ifDefined('advanceRef', options.advanceRef),
|
|
188
|
+
...ifDefined('db', options.db),
|
|
189
|
+
refsDir,
|
|
190
|
+
contractIR,
|
|
191
|
+
mode: result.value.mode,
|
|
192
|
+
hash: advancementHash,
|
|
193
|
+
});
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (MigrationToolsError.is(error)) {
|
|
196
|
+
return notOk(mapMigrationToolsError(error));
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
152
202
|
// Convert success result to CLI output format
|
|
153
203
|
const dbUpdateResult: MigrationCommandResult = {
|
|
154
204
|
ok: true,
|
|
@@ -185,6 +235,8 @@ async function executeDbUpdateCommand(
|
|
|
185
235
|
: undefined,
|
|
186
236
|
),
|
|
187
237
|
...ifDefined('perSpace', result.value.perSpace),
|
|
238
|
+
advancedRef: refAdvancementFields.advancedRef,
|
|
239
|
+
plannedAdvanceRef: refAdvancementFields.plannedAdvanceRef,
|
|
188
240
|
summary: result.value.summary,
|
|
189
241
|
timings: { total: Date.now() - startTime },
|
|
190
242
|
};
|
|
@@ -237,11 +289,12 @@ export function createDbUpdateCommand(): Command {
|
|
|
237
289
|
'--to <contract>',
|
|
238
290
|
'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
|
|
239
291
|
);
|
|
292
|
+
command.option('--advance-ref <name>', 'Ref to advance to the post-command contract hash');
|
|
240
293
|
command.action(async (options: DbUpdateOptions) => {
|
|
241
|
-
const flags =
|
|
294
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
242
295
|
const startTime = Date.now();
|
|
243
296
|
|
|
244
|
-
const ui =
|
|
297
|
+
const ui = createTerminalUI(flags);
|
|
245
298
|
|
|
246
299
|
let result = await executeDbUpdateCommand(options, flags, ui, startTime);
|
|
247
300
|
|
|
@@ -47,10 +47,10 @@ import {
|
|
|
47
47
|
formatVerifyOutput,
|
|
48
48
|
} from '../utils/formatters/verify';
|
|
49
49
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
50
|
-
import { type GlobalFlags,
|
|
50
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
51
51
|
import { createProgressAdapter } from '../utils/progress-adapter';
|
|
52
52
|
import { handleResult } from '../utils/result-handler';
|
|
53
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
53
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
54
54
|
|
|
55
55
|
interface DbVerifyOptions extends CommonCommandOptions {
|
|
56
56
|
readonly db?: string;
|
|
@@ -331,7 +331,7 @@ function wrapVerifyError(
|
|
|
331
331
|
contractPathAbsolute: string,
|
|
332
332
|
modeLabel: string,
|
|
333
333
|
): Result<never, CliStructuredError> {
|
|
334
|
-
if (error
|
|
334
|
+
if (CliStructuredError.is(error)) {
|
|
335
335
|
return notOk(error);
|
|
336
336
|
}
|
|
337
337
|
if (error instanceof ContractValidationError) {
|
|
@@ -529,8 +529,8 @@ export function createDbVerifyCommand(): Command {
|
|
|
529
529
|
false,
|
|
530
530
|
)
|
|
531
531
|
.action(async (options: DbVerifyOptions) => {
|
|
532
|
-
const flags =
|
|
533
|
-
const ui =
|
|
532
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
533
|
+
const ui = createTerminalUI(flags);
|
|
534
534
|
|
|
535
535
|
const modeResult = resolveDbVerifyMode(options);
|
|
536
536
|
if (!modeResult.ok) {
|
|
@@ -56,6 +56,21 @@ export function formatRunCommand(pm: PackageManager, bin: string, args: string):
|
|
|
56
56
|
return `${pm} ${bin} ${args}`;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export function formatRunScriptCommand(pm: PackageManager, scriptName: string): string {
|
|
60
|
+
switch (pm) {
|
|
61
|
+
case 'deno':
|
|
62
|
+
return `deno task ${scriptName}`;
|
|
63
|
+
case 'bun':
|
|
64
|
+
return `bun run ${scriptName}`;
|
|
65
|
+
case 'pnpm':
|
|
66
|
+
return `pnpm run ${scriptName}`;
|
|
67
|
+
case 'yarn':
|
|
68
|
+
return `yarn run ${scriptName}`;
|
|
69
|
+
default:
|
|
70
|
+
return `npm run ${scriptName}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
export function formatAddArgs(pm: PackageManager, packages: string[]): string[] {
|
|
60
75
|
if (pm === 'deno') {
|
|
61
76
|
return ['add', ...packages.map((p) => `npm:${p}`)];
|
|
@@ -69,6 +69,37 @@ export function errorInitInvalidFlagValue(options: {
|
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* `--authoring` and `--schema-path` disagree on file extension (e.g. PSL
|
|
74
|
+
* authoring with a `.ts` path). Surfaces before any scaffold files are
|
|
75
|
+
* written so the project tree stays untouched.
|
|
76
|
+
*/
|
|
77
|
+
export function errorInitAuthoringSchemaPathMismatch(options: {
|
|
78
|
+
readonly authoring: 'psl' | 'typescript';
|
|
79
|
+
readonly schemaPath: string;
|
|
80
|
+
readonly actualExtension: string;
|
|
81
|
+
readonly expectedExtension: string;
|
|
82
|
+
}): CliStructuredError {
|
|
83
|
+
const expectedAuthoring = options.expectedExtension === '.ts' ? 'typescript' : 'psl';
|
|
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,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
72
103
|
/**
|
|
73
104
|
* The user cancelled an interactive prompt (Ctrl-C, escape, declined a
|
|
74
105
|
* selection). Distinct from `errorInitReinitNeedsForce` because that path
|
|
@@ -238,7 +269,7 @@ export function errorInitEmitFailed(options: {
|
|
|
238
269
|
}
|
|
239
270
|
|
|
240
271
|
/**
|
|
241
|
-
* The project-level
|
|
272
|
+
* The project-level skills install (`npx skills add
|
|
242
273
|
* prisma/prisma-next#v<version>`) failed after a successful dependency
|
|
243
274
|
* install + emit. The project's scaffold remains on disk; the user
|
|
244
275
|
* can either fix the underlying issue (network, registry, PATH) and
|
|
@@ -260,7 +291,7 @@ export function errorInitSkillInstallFailed(options: {
|
|
|
260
291
|
'Either:\n' +
|
|
261
292
|
` - Re-run \`prisma-next init --no-skill${options.filesWritten.length > 0 ? ' --force' : ''}\` to skip the skill install for this run, or\n` +
|
|
262
293
|
` - Fix the underlying issue (network, npm registry, \`npx skills\` on PATH) and install manually:\n ${options.skillInstallCommand}`,
|
|
263
|
-
docsUrl: 'https://prisma-next.dev/docs/cli/init#
|
|
294
|
+
docsUrl: 'https://prisma-next.dev/docs/cli/init#skills',
|
|
264
295
|
meta: {
|
|
265
296
|
filesWritten: options.filesWritten,
|
|
266
297
|
skillInstallCommand: options.skillInstallCommand,
|
|
@@ -20,7 +20,7 @@ import type { TargetId } from './templates/code-templates';
|
|
|
20
20
|
* `db/contract.json linguist-generated` — not the workspace-glob form
|
|
21
21
|
* `<glob>/contract.json` (which would over-match any unrelated
|
|
22
22
|
* `contract.json` the user has elsewhere) and not the absolute
|
|
23
|
-
* `
|
|
23
|
+
* `DEFAULT_CONTRACT_SOURCE_DIR/contract.json` (which would silently break for a non-default
|
|
24
24
|
* schema path).
|
|
25
25
|
*/
|
|
26
26
|
const ARTEFACT_FILENAMES: readonly string[] = [
|
|
@@ -59,7 +59,7 @@ export function requiredGitattributesLines(
|
|
|
59
59
|
*
|
|
60
60
|
* Equivalence is exact-line: a user-customised line like
|
|
61
61
|
* `prisma/*.json linguist-generated` is *not* recognised as covering
|
|
62
|
-
* `
|
|
62
|
+
* `DEFAULT_CONTRACT_SOURCE_DIR/contract.json linguist-generated`. We accept that
|
|
63
63
|
* over-specification — preserving the user's broad pattern *and*
|
|
64
64
|
* appending the narrow one — because the narrow lines are what the
|
|
65
65
|
* acceptance criteria pin (FR3.4 AC).
|