@prisma-next/cli 0.10.0 → 0.11.0-dev.1
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-CF60g2cG.mjs → cli-errors-Djtz98Vm.mjs} +3 -3
- package/dist/cli-errors-Djtz98Vm.mjs.map +1 -0
- package/dist/cli.mjs +400 -13
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-Brv4qlfB.mjs → client-oXO2WCPD.mjs} +6 -5
- package/dist/client-oXO2WCPD.mjs.map +1 -0
- package/dist/{command-helpers-D3vL5yi8.mjs → command-helpers-DtavI0wJ.mjs} +109 -12
- package/dist/command-helpers-DtavI0wJ.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.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +19 -20
- 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 +7 -11
- 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 +16 -17
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -1
- package/dist/commands/migrate.mjs +7 -11
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.mjs +4 -7
- 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 +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 +8 -12
- 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 +36 -14
- package/dist/commands/migration-status.mjs.map +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +9 -19
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/{contract-emit-iynA3BCA.mjs → contract-emit-bcrpT-wD.mjs} +3 -3
- package/dist/{contract-emit-iynA3BCA.mjs.map → contract-emit-bcrpT-wD.mjs.map} +1 -1
- package/dist/{contract-emit-C3STUIBg.mjs → contract-emit-uwT-Mj8-.mjs} +7 -12
- package/dist/contract-emit-uwT-Mj8-.mjs.map +1 -0
- package/dist/{contract-infer-Cnj8G1E2.mjs → contract-infer-pKkiCt7C.mjs} +9 -14
- package/dist/contract-infer-pKkiCt7C.mjs.map +1 -0
- package/dist/{contract-space-aggregate-loader-pAc8CDfY.mjs → contract-space-aggregate-loader-BmNQwlws.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-pAc8CDfY.mjs.map → contract-space-aggregate-loader-BmNQwlws.mjs.map} +1 -1
- package/dist/{db-verify-D7cyH_zz.mjs → db-verify-AoIUriL4.mjs} +9 -13
- package/dist/db-verify-AoIUriL4.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-65gOHkHB.mjs} +2 -2
- package/dist/{framework-components-xFLFpZUO.mjs.map → framework-components-65gOHkHB.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-DJVv0_uf.mjs} +1 -1
- package/dist/{graph-render-eJDcLWny.mjs.map → graph-render-DJVv0_uf.mjs.map} +1 -1
- package/dist/{init-eh2z5Tl6.mjs → init-YX6lCJpG.mjs} +528 -627
- package/dist/init-YX6lCJpG.mjs.map +1 -0
- package/dist/{inspect-live-schema-CWLK_lgs.mjs → inspect-live-schema-LeWvkZVz.mjs} +4 -4
- package/dist/{inspect-live-schema-CWLK_lgs.mjs.map → inspect-live-schema-LeWvkZVz.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs → migration-command-scaffold-BtkunvFQ.mjs} +4 -4
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs.map → migration-command-scaffold-BtkunvFQ.mjs.map} +1 -1
- package/dist/{migration-plan-CHyUlBV0.mjs → migration-plan-C2jeH1J5.mjs} +8 -12
- package/dist/migration-plan-C2jeH1J5.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-CwZMa1Ck.mjs} +2 -2
- package/dist/{migrations-DyUf5lTt.mjs.map → migrations-CwZMa1Ck.mjs.map} +1 -1
- package/dist/{output-B60Gw5fu.mjs → output-BlsrGMEF.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-BlsrGMEF.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/{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--CqjMdk0.d.mts} +2 -2
- package/dist/{types-0aS865QN.d.mts.map → types--CqjMdk0.d.mts.map} +1 -1
- package/dist/{verify-D7ypCCe6.mjs → verify-Bom75OYI.mjs} +2 -2
- package/dist/{verify-D7ypCCe6.mjs.map → verify-Bom75OYI.mjs.map} +1 -1
- package/package.json +19 -17
- package/src/cli.ts +42 -0
- package/src/commands/contract-emit.ts +4 -4
- package/src/commands/contract-infer.ts +7 -7
- package/src/commands/db-init.ts +13 -5
- package/src/commands/db-schema.ts +4 -4
- package/src/commands/db-sign.ts +4 -4
- package/src/commands/db-update.ts +13 -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 +4 -7
- 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 +4 -4
- package/src/commands/migration-show.ts +4 -4
- package/src/commands/migration-status.ts +49 -6
- package/src/commands/ref.ts +8 -8
- package/src/control-api/operations/apply-aggregate.ts +1 -0
- package/src/utils/cli-errors.ts +4 -0
- package/src/utils/command-helpers.ts +14 -6
- package/src/utils/global-flags.ts +105 -16
- package/src/utils/is-ci.ts +18 -0
- package/src/utils/telemetry.ts +141 -0
- package/src/utils/terminal-ui.ts +44 -23
- package/dist/cli-errors-CF60g2cG.mjs.map +0 -1
- 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-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/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/{cli-errors-DdcjVLJV.d.mts → cli-errors-Czmx92Zy.d.mts} +0 -0
|
@@ -20,10 +20,10 @@ 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;
|
|
@@ -159,8 +159,8 @@ export function createContractEmitCommand(): Command {
|
|
|
159
159
|
addGlobalOptions(command)
|
|
160
160
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
161
161
|
.action(async (options: ContractEmitOptions) => {
|
|
162
|
-
const flags =
|
|
163
|
-
const ui =
|
|
162
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
163
|
+
const ui = createTerminalUI(flags);
|
|
164
164
|
const startTime = Date.now();
|
|
165
165
|
|
|
166
166
|
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
|
@@ -24,13 +24,13 @@ import {
|
|
|
24
24
|
formatMigrationPlanOutput,
|
|
25
25
|
type MigrationCommandResult,
|
|
26
26
|
} from '../utils/formatters/migrations';
|
|
27
|
-
import { type GlobalFlags,
|
|
27
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
28
28
|
import {
|
|
29
29
|
addMigrationCommandOptions,
|
|
30
30
|
prepareMigrationContext,
|
|
31
31
|
} from '../utils/migration-command-scaffold';
|
|
32
32
|
import { handleResult } from '../utils/result-handler';
|
|
33
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
33
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
34
34
|
|
|
35
35
|
type DbInitOptions = MigrationCommandOptions;
|
|
36
36
|
|
|
@@ -80,9 +80,17 @@ function mapDbInitFailure(failure: DbInitFailure): CliStructuredError {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
if (failure.code === 'RUNNER_FAILED') {
|
|
83
|
+
const runnerCode =
|
|
84
|
+
typeof failure.meta?.['runnerErrorCode'] === 'string'
|
|
85
|
+
? failure.meta['runnerErrorCode']
|
|
86
|
+
: undefined;
|
|
87
|
+
const fix =
|
|
88
|
+
runnerCode === 'LEGACY_MARKER_SHAPE'
|
|
89
|
+
? '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.'
|
|
90
|
+
: 'Fix the schema mismatch (db init is additive-only), or drop/reset the database and re-run `prisma-next db init`';
|
|
83
91
|
return errorRunnerFailed(failure.summary, {
|
|
84
92
|
why: failure.why ?? 'Migration runner failed',
|
|
85
|
-
fix
|
|
93
|
+
fix,
|
|
86
94
|
...(failure.meta
|
|
87
95
|
? { meta: { code: 'RUNNER_FAILED', ...failure.meta } }
|
|
88
96
|
: { meta: { code: 'RUNNER_FAILED' } }),
|
|
@@ -222,10 +230,10 @@ export function createDbInitCommand(): Command {
|
|
|
222
230
|
]);
|
|
223
231
|
addMigrationCommandOptions(command);
|
|
224
232
|
command.action(async (options: DbInitOptions) => {
|
|
225
|
-
const flags =
|
|
233
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
226
234
|
const startTime = Date.now();
|
|
227
235
|
|
|
228
|
-
const ui =
|
|
236
|
+
const ui = createTerminalUI(flags);
|
|
229
237
|
|
|
230
238
|
const result = await executeDbInitCommand(options, flags, ui, startTime);
|
|
231
239
|
|
|
@@ -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,13 +33,13 @@ 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
41
|
import { handleResult } from '../utils/result-handler';
|
|
42
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
42
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
43
43
|
|
|
44
44
|
interface DbUpdateOptions extends MigrationCommandOptions {
|
|
45
45
|
readonly to?: string;
|
|
@@ -54,9 +54,17 @@ function mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
if (failure.code === 'RUNNER_FAILED') {
|
|
57
|
+
const runnerCode =
|
|
58
|
+
typeof failure.meta?.['runnerErrorCode'] === 'string'
|
|
59
|
+
? failure.meta['runnerErrorCode']
|
|
60
|
+
: undefined;
|
|
61
|
+
const fix =
|
|
62
|
+
runnerCode === 'LEGACY_MARKER_SHAPE'
|
|
63
|
+
? '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.'
|
|
64
|
+
: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`';
|
|
57
65
|
return errorRunnerFailed(failure.summary, {
|
|
58
66
|
why: failure.why ?? 'Migration runner failed',
|
|
59
|
-
fix
|
|
67
|
+
fix,
|
|
60
68
|
...ifDefined('meta', failure.meta),
|
|
61
69
|
});
|
|
62
70
|
}
|
|
@@ -238,10 +246,10 @@ export function createDbUpdateCommand(): Command {
|
|
|
238
246
|
'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
|
|
239
247
|
);
|
|
240
248
|
command.action(async (options: DbUpdateOptions) => {
|
|
241
|
-
const flags =
|
|
249
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
242
250
|
const startTime = Date.now();
|
|
243
251
|
|
|
244
|
-
const ui =
|
|
252
|
+
const ui = createTerminalUI(flags);
|
|
245
253
|
|
|
246
254
|
let result = await executeDbUpdateCommand(options, flags, ui, startTime);
|
|
247
255
|
|
|
@@ -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).
|
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
setCommandDescriptions,
|
|
5
5
|
setCommandExamples,
|
|
6
6
|
} from '../../utils/command-helpers';
|
|
7
|
-
import { type CommonCommandOptions,
|
|
7
|
+
import { type CommonCommandOptions, parseGlobalFlagsOrExit } from '../../utils/global-flags';
|
|
8
|
+
import { fireTelemetryAfterInitConsent } from '../../utils/telemetry';
|
|
8
9
|
import {
|
|
9
10
|
INIT_EXIT_EMIT_FAILED,
|
|
10
11
|
INIT_EXIT_INSTALL_FAILED,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
INIT_EXIT_SKILL_INSTALL_FAILED,
|
|
15
16
|
INIT_EXIT_USER_ABORTED,
|
|
16
17
|
} from './exit-codes';
|
|
18
|
+
import { defaultSchemaPath } from './templates/code-templates';
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* Commander.js parsed options for `init`. The init-specific options live
|
|
@@ -63,7 +65,7 @@ export function createInitCommand(): Command {
|
|
|
63
65
|
'prisma-next init --yes --target mongodb --authoring typescript --json',
|
|
64
66
|
'prisma-next init --yes --force --target postgres --authoring psl # overwrite an existing scaffold',
|
|
65
67
|
'prisma-next init --no-install # skip pnpm/npm install + emit',
|
|
66
|
-
'prisma-next init --no-skill # skip the
|
|
68
|
+
'prisma-next init --no-skill # skip the skills install (air-gapped / restricted env)',
|
|
67
69
|
]);
|
|
68
70
|
|
|
69
71
|
return addGlobalOptions(command)
|
|
@@ -71,7 +73,7 @@ export function createInitCommand(): Command {
|
|
|
71
73
|
.option('--authoring <style>', 'Schema authoring style: psl or typescript')
|
|
72
74
|
.option(
|
|
73
75
|
'--schema-path <path>',
|
|
74
|
-
|
|
76
|
+
`Where to write the starter schema (default: ${defaultSchemaPath('psl')})`,
|
|
75
77
|
)
|
|
76
78
|
.option('--force', 'Overwrite an existing scaffold without prompting')
|
|
77
79
|
.option(
|
|
@@ -91,15 +93,22 @@ export function createInitCommand(): Command {
|
|
|
91
93
|
'--no-skill',
|
|
92
94
|
'Skip Prisma Next skills install (air-gapped CI, restricted registries, etc.)',
|
|
93
95
|
)
|
|
94
|
-
.action(async (options: InitCommandOptions) => {
|
|
96
|
+
.action(async (options: InitCommandOptions, actionCommand: Command) => {
|
|
95
97
|
const { runInit } = await import('./init');
|
|
96
|
-
const flags =
|
|
98
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
97
99
|
const canPrompt = deriveCanPrompt({
|
|
98
100
|
flagsInteractive: flags.interactive,
|
|
99
101
|
optionInteractive: options.interactive,
|
|
100
102
|
stdinIsTTY: Boolean(process.stdin.isTTY),
|
|
101
103
|
});
|
|
102
|
-
const exitCode = await runInit(process.cwd(), {
|
|
104
|
+
const exitCode = await runInit(process.cwd(), {
|
|
105
|
+
options,
|
|
106
|
+
flags,
|
|
107
|
+
canPrompt,
|
|
108
|
+
afterFirstTelemetryConsent: (inputs) => {
|
|
109
|
+
fireTelemetryAfterInitConsent(actionCommand, { databaseTarget: inputs.target });
|
|
110
|
+
},
|
|
111
|
+
});
|
|
103
112
|
process.exit(exitCode);
|
|
104
113
|
});
|
|
105
114
|
}
|
|
@@ -6,14 +6,7 @@ import { basename, dirname, isAbsolute, join } from 'pathe';
|
|
|
6
6
|
import { CliStructuredError } from '../../utils/cli-errors';
|
|
7
7
|
import { formatErrorJson, formatErrorOutput } from '../../utils/formatters/errors';
|
|
8
8
|
import type { GlobalFlags } from '../../utils/global-flags';
|
|
9
|
-
import { TerminalUI } from '../../utils/terminal-ui';
|
|
10
|
-
import {
|
|
11
|
-
DEFAULT_AGENT_SKILL_SOURCES,
|
|
12
|
-
formatClaudeSkillInstallCommand,
|
|
13
|
-
formatSkillInstallCommand,
|
|
14
|
-
LEGACY_SKILL_FILE,
|
|
15
|
-
runProjectLevelSkillInstall,
|
|
16
|
-
} from './agent-skill-install';
|
|
9
|
+
import { createTerminalUI, type TerminalUI } from '../../utils/terminal-ui';
|
|
17
10
|
import {
|
|
18
11
|
detectPackageManager,
|
|
19
12
|
formatAddArgs,
|
|
@@ -56,9 +49,16 @@ import {
|
|
|
56
49
|
} from './output';
|
|
57
50
|
import { type ProbeOutcome, type ProbeOverrides, probeServerVersion } from './probe-db';
|
|
58
51
|
import { findStaleArtefacts, removeDependency } from './reinit-cleanup';
|
|
52
|
+
import {
|
|
53
|
+
DEFAULT_SKILL_SOURCES,
|
|
54
|
+
formatSkillInstallCommand,
|
|
55
|
+
LEGACY_SKILL_FILE,
|
|
56
|
+
runProjectLevelSkillInstall,
|
|
57
|
+
} from './skill-install';
|
|
59
58
|
import { configFile, dbFile, starterSchema, targetPackageName } from './templates/code-templates';
|
|
60
59
|
import { envExampleContent, envFileContent, MIN_SERVER_VERSION } from './templates/env';
|
|
61
60
|
import { quickReferenceMd } from './templates/quick-reference';
|
|
61
|
+
import { minimalProjectReadmeMd } from './templates/readme';
|
|
62
62
|
import { defaultTsConfig, mergeTsConfig, TsConfigParseError } from './templates/tsconfig';
|
|
63
63
|
|
|
64
64
|
interface FileEntry {
|
|
@@ -81,11 +81,11 @@ interface InstallReport {
|
|
|
81
81
|
readonly warnings: readonly string[];
|
|
82
82
|
/**
|
|
83
83
|
* The package manager that actually ran. Equal to the detected `pm`
|
|
84
|
-
* on the common path; differs when the
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
84
|
+
* on the common path; differs when the pnpm → npm fallback fired, in
|
|
85
|
+
* which case it's `'npm'`. Threaded into the skills install so the
|
|
86
|
+
* runner stays consistent with the install we just ran — re-trying
|
|
87
|
+
* through `pnpm dlx` when `pnpm install` just failed for
|
|
88
|
+
* workspace/catalog reasons would fail again for the same reason.
|
|
89
89
|
*/
|
|
90
90
|
readonly effectivePm: PackageManager;
|
|
91
91
|
}
|
|
@@ -95,7 +95,7 @@ interface InstallReport {
|
|
|
95
95
|
* structured CLI errors raised at every phase (input resolution, install,
|
|
96
96
|
* emit) and renders them via the same UI surface as success output
|
|
97
97
|
* (`--json` to stdout, human to stderr). Exit codes follow the documented
|
|
98
|
-
* stable set in `./exit-codes.ts`
|
|
98
|
+
* stable set in `./exit-codes.ts` and the
|
|
99
99
|
* [Style Guide § Exit Codes](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes).
|
|
100
100
|
*
|
|
101
101
|
* Layered for testability: the action handler in `./index.ts` is
|
|
@@ -113,6 +113,11 @@ export async function runInit(
|
|
|
113
113
|
* mode) — see [Style Guide § Interactivity](../../../../../../../docs/CLI%20Style%20Guide.md#interactivity).
|
|
114
114
|
*/
|
|
115
115
|
readonly canPrompt: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Called once after the first affirmative telemetry consent is persisted.
|
|
118
|
+
* Failures are swallowed by the caller; init success must not depend on telemetry.
|
|
119
|
+
*/
|
|
120
|
+
readonly afterFirstTelemetryConsent?: (inputs: ResolvedInitInputs) => void | Promise<void>;
|
|
116
121
|
/**
|
|
117
122
|
* FR8.3 — test-only seam for the optional database version probe.
|
|
118
123
|
* Production callers omit this; tests inject stub `probePostgres` /
|
|
@@ -124,8 +129,8 @@ export async function runInit(
|
|
|
124
129
|
readonly probeOverrides?: ProbeOverrides;
|
|
125
130
|
},
|
|
126
131
|
): Promise<number> {
|
|
127
|
-
const { options, flags, canPrompt, probeOverrides } = runOptions;
|
|
128
|
-
const ui =
|
|
132
|
+
const { options, flags, canPrompt, probeOverrides, afterFirstTelemetryConsent } = runOptions;
|
|
133
|
+
const ui = createTerminalUI(flags);
|
|
129
134
|
const warnings: string[] = [];
|
|
130
135
|
const filesWritten: string[] = [];
|
|
131
136
|
const filesDeleted: string[] = [];
|
|
@@ -144,6 +149,14 @@ export async function runInit(
|
|
|
144
149
|
throw error;
|
|
145
150
|
}
|
|
146
151
|
|
|
152
|
+
if (inputs.enableTelemetry === true && afterFirstTelemetryConsent !== undefined) {
|
|
153
|
+
try {
|
|
154
|
+
await afterFirstTelemetryConsent(inputs);
|
|
155
|
+
} catch {
|
|
156
|
+
// telemetry is best-effort and must never affect init
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
147
160
|
const pm = await detectPackageManager(baseDir);
|
|
148
161
|
const pkgRun = formatRunCommand(pm, 'prisma-next', '').trimEnd();
|
|
149
162
|
|
|
@@ -336,6 +349,26 @@ export async function runInit(
|
|
|
336
349
|
}
|
|
337
350
|
}
|
|
338
351
|
|
|
352
|
+
if (existsSync(join(baseDir, 'src/index.ts'))) {
|
|
353
|
+
if (!existsSync(join(baseDir, 'README.md'))) {
|
|
354
|
+
const rawName =
|
|
355
|
+
parsedPackageJson !== null && typeof parsedPackageJson['name'] === 'string'
|
|
356
|
+
? parsedPackageJson['name']
|
|
357
|
+
: basename(baseDir);
|
|
358
|
+
filesToWrite.push({
|
|
359
|
+
path: 'README.md',
|
|
360
|
+
content: minimalProjectReadmeMd(
|
|
361
|
+
inputs.target,
|
|
362
|
+
inputs.schemaPath,
|
|
363
|
+
sanitisePackageName(rawName),
|
|
364
|
+
pm,
|
|
365
|
+
),
|
|
366
|
+
});
|
|
367
|
+
} else {
|
|
368
|
+
warnings.push('README.md already exists; leaving it untouched.');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
339
372
|
// -----------------------------------------------------------------
|
|
340
373
|
// Write phase — every input has been parsed and every merged file is
|
|
341
374
|
// staged. From here on, failures are only possible at the
|
|
@@ -445,25 +478,20 @@ export async function runInit(
|
|
|
445
478
|
// framework relies on. A project-level failure is fatal
|
|
446
479
|
// (`INIT_EXIT_SKILL_INSTALL_FAILED`).
|
|
447
480
|
//
|
|
448
|
-
// Runs after install + emit
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
// `--no-
|
|
453
|
-
//
|
|
454
|
-
const manualProjectSkillCommands =
|
|
455
|
-
formatSkillInstallCommand(install.effectivePm, source),
|
|
456
|
-
|
|
457
|
-
]);
|
|
481
|
+
// Runs after the install + emit phase when those steps are enabled,
|
|
482
|
+
// but is not coupled to them: the skills are pulled directly from
|
|
483
|
+
// the Prisma Next GitHub repo and do not require `node_modules`.
|
|
484
|
+
// `--no-install` therefore skips only dependency installation and
|
|
485
|
+
// contract emission; `--no-skill` is the explicit escape hatch for
|
|
486
|
+
// skipping skills.
|
|
487
|
+
const manualProjectSkillCommands = DEFAULT_SKILL_SOURCES.map((source) =>
|
|
488
|
+
formatSkillInstallCommand({ pm: install.effectivePm, source }),
|
|
489
|
+
);
|
|
458
490
|
const manualProjectSkillSummary = manualProjectSkillCommands.map((c) => `\`${c}\``).join(' && ');
|
|
459
491
|
let skillRegistered = false;
|
|
460
492
|
if (!inputs.installProjectSkill) {
|
|
461
493
|
warnings.push(
|
|
462
|
-
`Skipped Prisma Next
|
|
463
|
-
);
|
|
464
|
-
} else if (install.skipped) {
|
|
465
|
-
warnings.push(
|
|
466
|
-
`Skipped Prisma Next agent-skill install because --no-install was passed. After you run install manually, install the skills with: ${manualProjectSkillSummary}`,
|
|
494
|
+
`Skipped Prisma Next skills install (--no-skill). To install the skills later, run: ${manualProjectSkillSummary}`,
|
|
467
495
|
);
|
|
468
496
|
} else {
|
|
469
497
|
const spinner = ui.spinner();
|
|
@@ -588,6 +616,7 @@ export function exitCodeForError(error: { readonly code: string }): number {
|
|
|
588
616
|
case '5010': // invalid manifest (malformed package.json) — precondition
|
|
589
617
|
case '5011': // invalid tsconfig (unparseable JSONC) — precondition
|
|
590
618
|
case '5012': // probe failed under --strict-probe — precondition
|
|
619
|
+
case '5014': // --authoring / --schema-path extension mismatch — precondition
|
|
591
620
|
return INIT_EXIT_PRECONDITION;
|
|
592
621
|
case '5006': // user aborted interactive prompt
|
|
593
622
|
return INIT_EXIT_USER_ABORTED;
|
|
@@ -597,7 +626,7 @@ export function exitCodeForError(error: { readonly code: string }): number {
|
|
|
597
626
|
return INIT_EXIT_EMIT_FAILED;
|
|
598
627
|
case '5009': // invalid output document — internal bug in prisma-next
|
|
599
628
|
return INIT_EXIT_INTERNAL_ERROR;
|
|
600
|
-
case '5013': //
|
|
629
|
+
case '5013': // skill install failed
|
|
601
630
|
return INIT_EXIT_SKILL_INSTALL_FAILED;
|
|
602
631
|
default:
|
|
603
632
|
// Any unexpected code is treated as an internal bug rather than
|