@prisma-next/cli 0.10.0 → 0.11.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/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 +151 -12
- 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-BSb0tRC8.mjs} +104 -10
- package/dist/command-helpers-BSb0tRC8.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-r4y8Zhf1.mjs} +7 -12
- package/dist/contract-emit-r4y8Zhf1.mjs.map +1 -0
- package/dist/{contract-infer-Cnj8G1E2.mjs → contract-infer-BmySmqVT.mjs} +8 -13
- package/dist/contract-infer-BmySmqVT.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-BClPs3ph.mjs} +9 -13
- package/dist/db-verify-BClPs3ph.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-BCJZPWE1.mjs} +547 -399
- package/dist/init-BCJZPWE1.mjs.map +1 -0
- package/dist/{inspect-live-schema-CWLK_lgs.mjs → inspect-live-schema-DSRbFoOL.mjs} +4 -4
- package/dist/{inspect-live-schema-CWLK_lgs.mjs.map → inspect-live-schema-DSRbFoOL.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs → migration-command-scaffold-Bzd9La5c.mjs} +4 -4
- package/dist/{migration-command-scaffold-CmXXC1UZ.mjs.map → migration-command-scaffold-Bzd9La5c.mjs.map} +1 -1
- package/dist/{migration-plan-CHyUlBV0.mjs → migration-plan-CFwqw3Gk.mjs} +8 -12
- package/dist/migration-plan-CFwqw3Gk.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 +6 -6
- 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/index.ts +13 -5
- 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 +22 -22
- 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 +6 -2
- 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,9 +20,9 @@ import {
|
|
|
20
20
|
} from '../utils/command-helpers';
|
|
21
21
|
import { formatStyledHeader } 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 { handleResult } from '../utils/result-handler';
|
|
25
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
25
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
26
26
|
|
|
27
27
|
interface MigrationListOptions extends CommonCommandOptions {
|
|
28
28
|
readonly config?: string;
|
|
@@ -130,8 +130,8 @@ export function createMigrationListCommand(): Command {
|
|
|
130
130
|
addGlobalOptions(command)
|
|
131
131
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
132
132
|
.action(async (options: MigrationListOptions) => {
|
|
133
|
-
const flags =
|
|
134
|
-
const ui =
|
|
133
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
134
|
+
const ui = createTerminalUI(flags);
|
|
135
135
|
const result = await executeMigrationListCommand(options, flags, ui);
|
|
136
136
|
const exitCode = handleResult(result, flags, ui, (listResult) => {
|
|
137
137
|
if (flags.json) {
|
|
@@ -8,7 +8,7 @@ import { Command } from 'commander';
|
|
|
8
8
|
import { loadConfig } from '../config-loader';
|
|
9
9
|
import { createControlClient } from '../control-api/client';
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
CliStructuredError,
|
|
12
12
|
errorDatabaseConnectionRequired,
|
|
13
13
|
errorDriverRequired,
|
|
14
14
|
errorUnexpected,
|
|
@@ -26,9 +26,9 @@ import {
|
|
|
26
26
|
} from '../utils/command-helpers';
|
|
27
27
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
28
28
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
29
|
-
import { type GlobalFlags,
|
|
29
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
30
30
|
import { handleResult } from '../utils/result-handler';
|
|
31
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
31
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
32
32
|
|
|
33
33
|
interface MigrationLogOptions extends CommonCommandOptions {
|
|
34
34
|
readonly db?: string;
|
|
@@ -159,6 +159,7 @@ async function executeMigrationLogCommand(
|
|
|
159
159
|
summary: `${entries.length} migration(s) applied`,
|
|
160
160
|
});
|
|
161
161
|
} catch (error) {
|
|
162
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
162
163
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
163
164
|
return notOk(
|
|
164
165
|
errorUnexpected(error instanceof Error ? error.message : String(error), {
|
|
@@ -192,8 +193,8 @@ export function createMigrationLogCommand(): Command {
|
|
|
192
193
|
.option('--db <url>', 'Database connection string')
|
|
193
194
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
194
195
|
.action(async (options: MigrationLogOptions) => {
|
|
195
|
-
const flags =
|
|
196
|
-
const ui =
|
|
196
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
197
|
+
const ui = createTerminalUI(flags);
|
|
197
198
|
const result = await executeMigrationLogCommand(options, flags, ui);
|
|
198
199
|
const exitCode = handleResult(result, flags, ui, (logResult) => {
|
|
199
200
|
if (flags.json) {
|
|
@@ -49,9 +49,9 @@ import {
|
|
|
49
49
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
50
50
|
import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
|
|
51
51
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
52
|
-
import {
|
|
52
|
+
import { parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
53
53
|
import { handleResult } from '../utils/result-handler';
|
|
54
|
-
import {
|
|
54
|
+
import { createTerminalUI } from '../utils/terminal-ui';
|
|
55
55
|
|
|
56
56
|
interface MigrationNewOptions extends CommonCommandOptions {
|
|
57
57
|
readonly name?: string;
|
|
@@ -287,8 +287,8 @@ export function createMigrationNewCommand(): Command {
|
|
|
287
287
|
.option('--from <hash>', 'Starting contract hash (default: latest migration target)')
|
|
288
288
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
289
289
|
.action(async (options: MigrationNewOptions) => {
|
|
290
|
-
const flags =
|
|
291
|
-
const ui =
|
|
290
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
291
|
+
const ui = createTerminalUI(flags);
|
|
292
292
|
|
|
293
293
|
if (!flags.json && !flags.quiet) {
|
|
294
294
|
const header = formatStyledHeader({
|
|
@@ -51,9 +51,9 @@ import { toExtensionInputs } from '../utils/extension-pack-inputs';
|
|
|
51
51
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
52
52
|
import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
|
|
53
53
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
54
|
-
import { type GlobalFlags,
|
|
54
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
55
55
|
import { handleResult } from '../utils/result-handler';
|
|
56
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
56
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
57
57
|
|
|
58
58
|
interface MigrationPlanOptions extends CommonCommandOptions {
|
|
59
59
|
readonly config?: string;
|
|
@@ -551,10 +551,10 @@ export function createMigrationPlanCommand(): Command {
|
|
|
551
551
|
'Starting contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
|
|
552
552
|
)
|
|
553
553
|
.action(async (options: MigrationPlanOptions) => {
|
|
554
|
-
const flags =
|
|
554
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
555
555
|
const startTime = Date.now();
|
|
556
556
|
|
|
557
|
-
const ui =
|
|
557
|
+
const ui = createTerminalUI(flags);
|
|
558
558
|
const result = await executeMigrationPlanCommand(options, flags, ui, startTime);
|
|
559
559
|
|
|
560
560
|
const exitCode = handleResult(result, flags, ui, (planResult) => {
|
|
@@ -43,9 +43,9 @@ import { buildContractSpaceAggregate } from '../utils/contract-space-aggregate-l
|
|
|
43
43
|
import { formatMigrationShowOutput } from '../utils/formatters/migrations';
|
|
44
44
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
45
45
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
46
|
-
import { type GlobalFlags,
|
|
46
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
47
47
|
import { handleResult } from '../utils/result-handler';
|
|
48
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
48
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
49
49
|
|
|
50
50
|
interface MigrationShowOptions extends CommonCommandOptions {
|
|
51
51
|
readonly config?: string;
|
|
@@ -495,9 +495,9 @@ export function createMigrationShowCommand(): Command {
|
|
|
495
495
|
)
|
|
496
496
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
497
497
|
.action(async (target: string | undefined, options: MigrationShowOptions) => {
|
|
498
|
-
const flags =
|
|
498
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
499
499
|
|
|
500
|
-
const ui =
|
|
500
|
+
const ui = createTerminalUI(flags);
|
|
501
501
|
|
|
502
502
|
const result = await executeMigrationShowCommand(target, options, flags, ui);
|
|
503
503
|
|
|
@@ -30,7 +30,7 @@ import { Command } from 'commander';
|
|
|
30
30
|
import { loadConfig } from '../config-loader';
|
|
31
31
|
import { createControlClient } from '../control-api/client';
|
|
32
32
|
import {
|
|
33
|
-
|
|
33
|
+
CliStructuredError,
|
|
34
34
|
errorRuntime,
|
|
35
35
|
errorUnexpected,
|
|
36
36
|
mapMigrationToolsError,
|
|
@@ -65,10 +65,10 @@ import {
|
|
|
65
65
|
} from '../utils/formatters/graph-render';
|
|
66
66
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
67
67
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
68
|
-
import { type GlobalFlags,
|
|
68
|
+
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
69
69
|
import type { StatusDiagnostic, StatusRef } from '../utils/migration-types';
|
|
70
70
|
import { handleResult } from '../utils/result-handler';
|
|
71
|
-
import { TerminalUI } from '../utils/terminal-ui';
|
|
71
|
+
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
72
72
|
|
|
73
73
|
interface MigrationStatusOptions extends CommonCommandOptions {
|
|
74
74
|
readonly db?: string;
|
|
@@ -540,6 +540,40 @@ async function loadContractRawSafely(config: {
|
|
|
540
540
|
}
|
|
541
541
|
}
|
|
542
542
|
|
|
543
|
+
async function validateOnlineMarkerRead(
|
|
544
|
+
config: Awaited<ReturnType<typeof loadConfig>>,
|
|
545
|
+
dbConnection: unknown,
|
|
546
|
+
): Promise<Result<void, CliStructuredError>> {
|
|
547
|
+
const driver = config.driver;
|
|
548
|
+
if (!driver) {
|
|
549
|
+
return ok(undefined);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const client = createControlClient({
|
|
553
|
+
family: config.family,
|
|
554
|
+
target: config.target,
|
|
555
|
+
adapter: config.adapter,
|
|
556
|
+
driver,
|
|
557
|
+
extensionPacks: config.extensionPacks ?? [],
|
|
558
|
+
});
|
|
559
|
+
try {
|
|
560
|
+
await client.connect(dbConnection);
|
|
561
|
+
await client.readMarker();
|
|
562
|
+
return ok(undefined);
|
|
563
|
+
} catch (error) {
|
|
564
|
+
if (CliStructuredError.is(error)) {
|
|
565
|
+
return notOk(error);
|
|
566
|
+
}
|
|
567
|
+
return notOk(
|
|
568
|
+
errorUnexpected(error instanceof Error ? error.message : String(error), {
|
|
569
|
+
why: `Failed to read database marker: ${error instanceof Error ? error.message : String(error)}`,
|
|
570
|
+
}),
|
|
571
|
+
);
|
|
572
|
+
} finally {
|
|
573
|
+
await client.close();
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
543
577
|
async function executeMigrationStatusCommand(
|
|
544
578
|
options: MigrationStatusOptions,
|
|
545
579
|
flags: GlobalFlags,
|
|
@@ -666,6 +700,12 @@ async function executeMigrationStatusCommand(
|
|
|
666
700
|
}
|
|
667
701
|
|
|
668
702
|
if (bundles.length === 0) {
|
|
703
|
+
if (dbConnection && hasDriver) {
|
|
704
|
+
const markerProbe = await validateOnlineMarkerRead(config, dbConnection);
|
|
705
|
+
if (!markerProbe.ok) {
|
|
706
|
+
return markerProbe;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
669
709
|
if (contractHash !== EMPTY_CONTRACT_HASH) {
|
|
670
710
|
diagnostics.push({
|
|
671
711
|
code: 'CONTRACT.AHEAD',
|
|
@@ -750,7 +790,10 @@ async function executeMigrationStatusCommand(
|
|
|
750
790
|
// space has no marker", which is a different condition).
|
|
751
791
|
allMarkers = null;
|
|
752
792
|
}
|
|
753
|
-
} catch {
|
|
793
|
+
} catch (error) {
|
|
794
|
+
if (CliStructuredError.is(error)) {
|
|
795
|
+
return notOk(error);
|
|
796
|
+
}
|
|
754
797
|
if (!flags.json && !flags.quiet) {
|
|
755
798
|
ui.warn('Could not connect to database — showing offline status');
|
|
756
799
|
}
|
|
@@ -1097,8 +1140,8 @@ export function createMigrationStatusCommand(): Command {
|
|
|
1097
1140
|
'Origin contract reference; same grammar as --to. Supplying --from switches to offline path computation.',
|
|
1098
1141
|
)
|
|
1099
1142
|
.action(async (options: MigrationStatusOptions) => {
|
|
1100
|
-
const flags =
|
|
1101
|
-
const ui =
|
|
1143
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
1144
|
+
const ui = createTerminalUI(flags);
|
|
1102
1145
|
|
|
1103
1146
|
const result = await executeMigrationStatusCommand(options, flags, ui);
|
|
1104
1147
|
|
package/src/commands/ref.ts
CHANGED
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
setCommandDescriptions,
|
|
26
26
|
} from '../utils/command-helpers';
|
|
27
27
|
import { formatCommandHelp } from '../utils/formatters/help';
|
|
28
|
-
import { parseGlobalFlags } from '../utils/global-flags';
|
|
28
|
+
import { parseGlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
29
29
|
import { handleResult } from '../utils/result-handler';
|
|
30
|
-
import {
|
|
30
|
+
import { createTerminalUI } from '../utils/terminal-ui';
|
|
31
31
|
|
|
32
32
|
interface RefSetResult {
|
|
33
33
|
readonly ok: true;
|
|
@@ -145,8 +145,8 @@ function createRefSetCommand(): Command {
|
|
|
145
145
|
hash: string,
|
|
146
146
|
options: { config?: string; json?: string | boolean; quiet?: boolean },
|
|
147
147
|
) => {
|
|
148
|
-
const flags =
|
|
149
|
-
const ui =
|
|
148
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
149
|
+
const ui = createTerminalUI(flags);
|
|
150
150
|
const result = await executeRefSetCommand(name, hash, options);
|
|
151
151
|
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
152
152
|
if (flags.json) {
|
|
@@ -172,8 +172,8 @@ function createRefDeleteCommand(): Command {
|
|
|
172
172
|
name: string,
|
|
173
173
|
options: { config?: string; json?: string | boolean; quiet?: boolean },
|
|
174
174
|
) => {
|
|
175
|
-
const flags =
|
|
176
|
-
const ui =
|
|
175
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
176
|
+
const ui = createTerminalUI(flags);
|
|
177
177
|
const result = await executeRefDeleteCommand(name, options);
|
|
178
178
|
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
179
179
|
if (flags.json) {
|
|
@@ -194,8 +194,8 @@ function createRefListCommand(): Command {
|
|
|
194
194
|
addGlobalOptions(command)
|
|
195
195
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
196
196
|
.action(async (options: { config?: string; json?: string | boolean; quiet?: boolean }) => {
|
|
197
|
-
const flags =
|
|
198
|
-
const ui =
|
|
197
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
198
|
+
const ui = createTerminalUI(flags);
|
|
199
199
|
const result = await executeRefListCommand(options);
|
|
200
200
|
const exitCode = handleResult(result, flags, ui, (value) => {
|
|
201
201
|
if (flags.json) {
|
|
@@ -178,6 +178,7 @@ export async function applyAggregate<TFamilyId extends string, TTargetId extends
|
|
|
178
178
|
meta: {
|
|
179
179
|
...(runnerResult.failure.meta ?? {}),
|
|
180
180
|
failingSpace: runnerResult.failure.failingSpace,
|
|
181
|
+
runnerErrorCode: runnerResult.failure.code,
|
|
181
182
|
},
|
|
182
183
|
});
|
|
183
184
|
}
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -16,9 +16,11 @@ import {
|
|
|
16
16
|
errorDriverRequired,
|
|
17
17
|
errorFamilyReadMarkerSqlRequired,
|
|
18
18
|
errorFileNotFound,
|
|
19
|
+
errorInvalidOutputFormat,
|
|
19
20
|
errorMigrationCliInvalidConfigArg,
|
|
20
21
|
errorMigrationCliUnknownFlag,
|
|
21
22
|
errorMigrationPlanningFailed,
|
|
23
|
+
errorOutputFormatMutex,
|
|
22
24
|
errorQueryRunnerFactoryRequired,
|
|
23
25
|
errorTargetMigrationNotSupported,
|
|
24
26
|
errorUnexpected,
|
|
@@ -56,9 +58,11 @@ export {
|
|
|
56
58
|
errorDriverRequired,
|
|
57
59
|
errorFamilyReadMarkerSqlRequired,
|
|
58
60
|
errorFileNotFound,
|
|
61
|
+
errorInvalidOutputFormat,
|
|
59
62
|
errorMigrationCliInvalidConfigArg,
|
|
60
63
|
errorMigrationCliUnknownFlag,
|
|
61
64
|
errorMigrationPlanningFailed,
|
|
65
|
+
errorOutputFormatMutex,
|
|
62
66
|
errorQueryRunnerFactoryRequired,
|
|
63
67
|
errorTargetMigrationNotSupported,
|
|
64
68
|
errorUnexpected,
|
|
@@ -365,7 +365,7 @@ export function sanitizeErrorMessage(message: string, connectionUrl?: string): s
|
|
|
365
365
|
|
|
366
366
|
/**
|
|
367
367
|
* Registers the global CLI options shared by every command:
|
|
368
|
-
* --json, -q/--quiet, -v/--verbose, --trace, --color, --no-color,
|
|
368
|
+
* --format, --json, -q/--quiet, -v/--verbose, --trace, --color, --no-color,
|
|
369
369
|
* --interactive, --no-interactive, -y/--yes.
|
|
370
370
|
*
|
|
371
371
|
* Also sets up the styled help formatter.
|
|
@@ -378,7 +378,11 @@ export function addGlobalOptions(command: Command): Command {
|
|
|
378
378
|
return formatCommandHelp({ command: cmd, flags });
|
|
379
379
|
},
|
|
380
380
|
})
|
|
381
|
-
.option(
|
|
381
|
+
.option(
|
|
382
|
+
'--format <pretty|json>',
|
|
383
|
+
'Output format (default: pretty, or json when stdout is not a TTY)',
|
|
384
|
+
)
|
|
385
|
+
.option('--json', 'Output as JSON (alias for --format json)')
|
|
382
386
|
.option('-q, --quiet', 'Quiet mode: errors only')
|
|
383
387
|
.option('-v, --verbose', 'Verbose output: debug info, timings')
|
|
384
388
|
.option('--trace', 'Trace output: deep internals, stack traces')
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { notOk } from '@prisma-next/utils/result';
|
|
2
|
+
import { CliStructuredError, errorInvalidOutputFormat, errorOutputFormatMutex } from './cli-errors';
|
|
3
|
+
import { isCI } from './is-ci';
|
|
4
|
+
import { handleResult } from './result-handler';
|
|
5
|
+
import { createTerminalUI } from './terminal-ui';
|
|
6
|
+
|
|
7
|
+
export type OutputFormat = 'pretty' | 'json';
|
|
8
|
+
|
|
1
9
|
export interface GlobalFlags {
|
|
10
|
+
readonly format: OutputFormat;
|
|
11
|
+
readonly explicitFormat: boolean;
|
|
2
12
|
readonly json?: boolean;
|
|
3
13
|
readonly quiet?: boolean;
|
|
4
|
-
readonly verbose?: number;
|
|
14
|
+
readonly verbose?: number;
|
|
5
15
|
readonly color?: boolean;
|
|
6
16
|
readonly interactive?: boolean;
|
|
7
17
|
readonly yes?: boolean;
|
|
@@ -12,6 +22,7 @@ export interface GlobalFlags {
|
|
|
12
22
|
* Extend this for command-specific options instead of duplicating these fields.
|
|
13
23
|
*/
|
|
14
24
|
export interface CommonCommandOptions {
|
|
25
|
+
readonly format?: string;
|
|
15
26
|
readonly json?: string | boolean;
|
|
16
27
|
readonly quiet?: boolean;
|
|
17
28
|
readonly q?: boolean;
|
|
@@ -26,33 +37,117 @@ export interface CommonCommandOptions {
|
|
|
26
37
|
readonly y?: boolean;
|
|
27
38
|
}
|
|
28
39
|
|
|
40
|
+
function isJsonFlagSet(json: string | boolean | undefined): boolean {
|
|
41
|
+
return json === true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ResolvedOutputFormat {
|
|
45
|
+
readonly format: OutputFormat;
|
|
46
|
+
readonly explicitFormat: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function resolveOutputFormat(options: CommonCommandOptions): ResolvedOutputFormat {
|
|
50
|
+
const formatOption = options.format;
|
|
51
|
+
const jsonFlag = isJsonFlagSet(options.json);
|
|
52
|
+
|
|
53
|
+
if (formatOption !== undefined) {
|
|
54
|
+
if (formatOption !== 'pretty' && formatOption !== 'json') {
|
|
55
|
+
throw errorInvalidOutputFormat(formatOption);
|
|
56
|
+
}
|
|
57
|
+
if (jsonFlag && formatOption === 'pretty') {
|
|
58
|
+
throw errorOutputFormatMutex();
|
|
59
|
+
}
|
|
60
|
+
return { format: formatOption, explicitFormat: true };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (jsonFlag) {
|
|
64
|
+
return { format: 'json', explicitFormat: false };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!process.stdout.isTTY) {
|
|
68
|
+
return { format: 'json', explicitFormat: false };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { format: 'pretty', explicitFormat: false };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function inferJsonModeForParseError(options: CommonCommandOptions): boolean {
|
|
75
|
+
if (options.format === 'json') {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (isJsonFlagSet(options.json) && options.format !== 'pretty') {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
if (options.format !== undefined) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return !process.stdout.isTTY;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function emitGlobalFlagParseError(error: CliStructuredError, options: CommonCommandOptions): never {
|
|
88
|
+
const jsonMode = inferJsonModeForParseError(options);
|
|
89
|
+
const flags: GlobalFlags = {
|
|
90
|
+
format: jsonMode ? 'json' : 'pretty',
|
|
91
|
+
explicitFormat: false,
|
|
92
|
+
...(jsonMode ? { json: true } : {}),
|
|
93
|
+
color: false,
|
|
94
|
+
verbose: 0,
|
|
95
|
+
interactive: false,
|
|
96
|
+
};
|
|
97
|
+
const ui = createTerminalUI(flags);
|
|
98
|
+
const exitCode = handleResult(notOk(error), flags, ui);
|
|
99
|
+
process.exit(exitCode);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Parses global flags from CLI options.
|
|
104
|
+
* Handles verbosity flags (-v, --trace), output format (--format, --json),
|
|
105
|
+
* quiet mode, color, interactivity (--interactive/--no-interactive), and
|
|
106
|
+
* auto-accept (-y/--yes).
|
|
107
|
+
*
|
|
108
|
+
* On invalid or conflicting format flags, prints a structured CLI error
|
|
109
|
+
* envelope and exits with code 2.
|
|
110
|
+
*/
|
|
111
|
+
export function parseGlobalFlagsOrExit(options: CommonCommandOptions): GlobalFlags {
|
|
112
|
+
try {
|
|
113
|
+
return parseGlobalFlags(options);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (CliStructuredError.is(error)) {
|
|
116
|
+
emitGlobalFlagParseError(error, options);
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
29
122
|
/**
|
|
30
123
|
* Parses global flags from CLI options.
|
|
31
|
-
* Handles verbosity flags (-v, --trace),
|
|
32
|
-
* interactivity (--interactive/--no-interactive), and
|
|
124
|
+
* Handles verbosity flags (-v, --trace), output format (--format, --json),
|
|
125
|
+
* quiet mode, color, interactivity (--interactive/--no-interactive), and
|
|
126
|
+
* auto-accept (-y/--yes).
|
|
127
|
+
*
|
|
128
|
+
* Throws {@link CliStructuredError} for invalid or conflicting format flags.
|
|
33
129
|
*/
|
|
34
130
|
export function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {
|
|
131
|
+
const { format, explicitFormat } = resolveOutputFormat(options);
|
|
35
132
|
const flags: {
|
|
133
|
+
format: OutputFormat;
|
|
134
|
+
explicitFormat: boolean;
|
|
36
135
|
json?: boolean;
|
|
37
136
|
quiet?: boolean;
|
|
38
137
|
verbose?: number;
|
|
39
138
|
color?: boolean;
|
|
40
139
|
interactive?: boolean;
|
|
41
140
|
yes?: boolean;
|
|
42
|
-
} = {};
|
|
141
|
+
} = { format, explicitFormat };
|
|
43
142
|
|
|
44
|
-
|
|
45
|
-
if (options.json || !process.stdout.isTTY) {
|
|
143
|
+
if (format === 'json') {
|
|
46
144
|
flags.json = true;
|
|
47
145
|
}
|
|
48
146
|
|
|
49
|
-
// Quiet mode
|
|
50
147
|
if (options.quiet || options.q) {
|
|
51
148
|
flags.quiet = true;
|
|
52
149
|
}
|
|
53
150
|
|
|
54
|
-
// Verbosity: -v = 1, --trace = 2
|
|
55
|
-
// Env toggles: PRISMA_NEXT_TRACE=1 ≅ --trace, PRISMA_NEXT_DEBUG=1 ≅ -v
|
|
56
151
|
if (options.trace || process.env['PRISMA_NEXT_TRACE'] === '1') {
|
|
57
152
|
flags.verbose = 2;
|
|
58
153
|
} else if (options.verbose || options.v || process.env['PRISMA_NEXT_DEBUG'] === '1') {
|
|
@@ -61,8 +156,6 @@ export function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {
|
|
|
61
156
|
flags.verbose = 0;
|
|
62
157
|
}
|
|
63
158
|
|
|
64
|
-
// Color: respect NO_COLOR env var, --color/--no-color flags
|
|
65
|
-
// When JSON output is enabled, disable color to ensure clean JSON output
|
|
66
159
|
if (process.env['NO_COLOR'] || flags.json) {
|
|
67
160
|
flags.color = false;
|
|
68
161
|
} else if (options['no-color']) {
|
|
@@ -70,12 +163,9 @@ export function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {
|
|
|
70
163
|
} else if (options.color !== undefined) {
|
|
71
164
|
flags.color = options.color;
|
|
72
165
|
} else {
|
|
73
|
-
|
|
74
|
-
flags.color = process.stdout.isTTY && !process.env['CI'];
|
|
166
|
+
flags.color = process.stdout.isTTY && !isCI();
|
|
75
167
|
}
|
|
76
168
|
|
|
77
|
-
// Interactivity: --interactive/--no-interactive
|
|
78
|
-
// Default: interactive when stdout is a TTY
|
|
79
169
|
if (options['no-interactive']) {
|
|
80
170
|
flags.interactive = false;
|
|
81
171
|
} else if (options.interactive !== undefined) {
|
|
@@ -84,7 +174,6 @@ export function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {
|
|
|
84
174
|
flags.interactive = !!process.stdout.isTTY;
|
|
85
175
|
}
|
|
86
176
|
|
|
87
|
-
// Auto-accept prompts: -y/--yes
|
|
88
177
|
if (options.yes || options.y) {
|
|
89
178
|
flags.yes = true;
|
|
90
179
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isCI as ciInfoIsCI } from 'ci-info';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns true when the process is running in any CI environment recognised
|
|
5
|
+
* by the `ci-info` package. The single source of truth for CI detection
|
|
6
|
+
* across this CLI — colour-output suppression and telemetry-skip both call
|
|
7
|
+
* this helper, so neither path drifts from the other when a new CI provider
|
|
8
|
+
* is added upstream.
|
|
9
|
+
*
|
|
10
|
+
* `ci-info` checks the standard `CI=true` marker plus dozens of
|
|
11
|
+
* provider-specific environment variables (Buildkite, Jenkins, Drone,
|
|
12
|
+
* Bitbucket Pipelines, Azure Pipelines, AWS CodeBuild, …) that the raw
|
|
13
|
+
* `process.env.CI` read misses.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export function isCI(): boolean {
|
|
17
|
+
return ciInfoIsCI;
|
|
18
|
+
}
|