@prisma-next/cli 0.3.0-pr.99.6 → 0.3.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/LICENSE +201 -0
- package/README.md +381 -128
- package/dist/agent-skill-mongo.md +106 -0
- package/dist/agent-skill-postgres.md +106 -0
- package/dist/cli-errors-BDCYR5ap.mjs +4 -0
- package/dist/cli-errors-DStABy9d.d.mts +3 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.js +1 -2910
- package/dist/cli.mjs +261 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/client-DiUkJAeN.mjs +987 -0
- package/dist/client-DiUkJAeN.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts +7 -0
- package/dist/commands/contract-emit.d.mts.map +1 -0
- package/dist/commands/contract-emit.mjs +9 -0
- package/dist/commands/contract-infer.d.mts +7 -0
- package/dist/commands/contract-infer.d.mts.map +1 -0
- package/dist/commands/contract-infer.mjs +10 -0
- package/dist/commands/db-init.d.mts +7 -0
- package/dist/commands/db-init.d.mts.map +1 -0
- package/dist/commands/db-init.mjs +126 -0
- package/dist/commands/db-init.mjs.map +1 -0
- package/dist/commands/db-schema.d.mts +7 -0
- package/dist/commands/db-schema.d.mts.map +1 -0
- package/dist/commands/db-schema.mjs +56 -0
- package/dist/commands/db-schema.mjs.map +1 -0
- package/dist/commands/db-sign.d.mts +7 -0
- package/dist/commands/db-sign.d.mts.map +1 -0
- package/dist/commands/db-sign.mjs +137 -0
- package/dist/commands/db-sign.mjs.map +1 -0
- package/dist/commands/db-update.d.mts +7 -0
- package/dist/commands/db-update.d.mts.map +1 -0
- package/dist/commands/db-update.mjs +123 -0
- package/dist/commands/db-update.mjs.map +1 -0
- package/dist/commands/db-verify.d.mts +7 -0
- package/dist/commands/db-verify.d.mts.map +1 -0
- package/dist/commands/db-verify.mjs +323 -0
- package/dist/commands/db-verify.mjs.map +1 -0
- package/dist/commands/migration-apply.d.mts +36 -0
- package/dist/commands/migration-apply.d.mts.map +1 -0
- package/dist/commands/migration-apply.mjs +245 -0
- package/dist/commands/migration-apply.mjs.map +1 -0
- package/dist/commands/migration-new.d.mts +8 -0
- package/dist/commands/migration-new.d.mts.map +1 -0
- package/dist/commands/migration-new.mjs +152 -0
- package/dist/commands/migration-new.mjs.map +1 -0
- package/dist/commands/migration-plan.d.mts +47 -0
- package/dist/commands/migration-plan.d.mts.map +1 -0
- package/dist/commands/migration-plan.mjs +313 -0
- package/dist/commands/migration-plan.mjs.map +1 -0
- package/dist/commands/migration-ref.d.mts +43 -0
- package/dist/commands/migration-ref.d.mts.map +1 -0
- package/dist/commands/migration-ref.mjs +195 -0
- package/dist/commands/migration-ref.mjs.map +1 -0
- package/dist/commands/migration-show.d.mts +28 -0
- package/dist/commands/migration-show.d.mts.map +1 -0
- package/dist/commands/migration-show.mjs +140 -0
- package/dist/commands/migration-show.mjs.map +1 -0
- package/dist/commands/migration-status.d.mts +86 -0
- package/dist/commands/migration-status.d.mts.map +1 -0
- package/dist/commands/migration-status.mjs +9 -0
- package/dist/commands/migration-verify.d.mts +16 -0
- package/dist/commands/migration-verify.d.mts.map +1 -0
- package/dist/commands/migration-verify.mjs +110 -0
- package/dist/commands/migration-verify.mjs.map +1 -0
- package/dist/config-loader-C4VXKl8f.mjs +43 -0
- package/dist/config-loader-C4VXKl8f.mjs.map +1 -0
- package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
- package/dist/config-loader.d.mts.map +1 -0
- package/dist/config-loader.mjs +3 -0
- package/dist/contract-emit-D2wDXfyo.mjs +191 -0
- package/dist/contract-emit-D2wDXfyo.mjs.map +1 -0
- package/dist/contract-emit-Zm_sd1wQ.mjs +112 -0
- package/dist/contract-emit-Zm_sd1wQ.mjs.map +1 -0
- package/dist/contract-emit-kN-IkKTE.mjs +6 -0
- package/dist/contract-enrichment-CGW6mm-E.mjs +79 -0
- package/dist/contract-enrichment-CGW6mm-E.mjs.map +1 -0
- package/dist/contract-infer-DozZT511.mjs +90 -0
- package/dist/contract-infer-DozZT511.mjs.map +1 -0
- package/dist/exports/config-types.d.mts +2 -0
- package/dist/exports/config-types.mjs +3 -0
- package/dist/exports/control-api.d.mts +624 -0
- package/dist/exports/control-api.d.mts.map +1 -0
- package/dist/exports/control-api.mjs +8 -0
- package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +12 -7
- package/dist/exports/index.d.mts.map +1 -0
- package/dist/exports/index.mjs +142 -0
- package/dist/exports/index.mjs.map +1 -0
- package/dist/extract-operation-statements-DZUJNmL3.mjs +13 -0
- package/dist/extract-operation-statements-DZUJNmL3.mjs.map +1 -0
- package/dist/extract-sql-ddl-DDMX-9mz.mjs +26 -0
- package/dist/extract-sql-ddl-DDMX-9mz.mjs.map +1 -0
- package/dist/framework-components-BAsliT4V.mjs +59 -0
- package/dist/framework-components-BAsliT4V.mjs.map +1 -0
- package/dist/init-6Pvm_esG.mjs +430 -0
- package/dist/init-6Pvm_esG.mjs.map +1 -0
- package/dist/inspect-live-schema-BYnhztxZ.mjs +91 -0
- package/dist/inspect-live-schema-BYnhztxZ.mjs.map +1 -0
- package/dist/migration-command-scaffold-CntCcntR.mjs +105 -0
- package/dist/migration-command-scaffold-CntCcntR.mjs.map +1 -0
- package/dist/migration-status-CJANY4yr.mjs +1583 -0
- package/dist/migration-status-CJANY4yr.mjs.map +1 -0
- package/dist/migrations-DTZBYXm1.mjs +173 -0
- package/dist/migrations-DTZBYXm1.mjs.map +1 -0
- package/dist/progress-adapter-B-YvmcDu.mjs +43 -0
- package/dist/progress-adapter-B-YvmcDu.mjs.map +1 -0
- package/dist/quick-reference-mongo.md +93 -0
- package/dist/quick-reference-postgres.md +91 -0
- package/dist/result-handler-oK_vA-Fn.mjs +697 -0
- package/dist/result-handler-oK_vA-Fn.mjs.map +1 -0
- package/dist/terminal-ui-C5k88MmW.mjs +274 -0
- package/dist/terminal-ui-C5k88MmW.mjs.map +1 -0
- package/dist/validate-contract-deps-esa-VQ0h.mjs +37 -0
- package/dist/validate-contract-deps-esa-VQ0h.mjs.map +1 -0
- package/dist/verify-DlFQ2FOw.mjs +385 -0
- package/dist/verify-DlFQ2FOw.mjs.map +1 -0
- package/package.json +87 -40
- package/src/cli.ts +118 -58
- package/src/commands/contract-emit.ts +101 -78
- package/src/commands/contract-infer-paths.ts +32 -0
- package/src/commands/contract-infer.ts +143 -0
- package/src/commands/db-init.ts +97 -219
- package/src/commands/db-schema.ts +77 -0
- package/src/commands/db-sign.ts +46 -73
- package/src/commands/db-update.ts +236 -0
- package/src/commands/db-verify.ts +409 -119
- package/src/commands/init/detect-package-manager.ts +47 -0
- package/src/commands/init/index.ts +21 -0
- package/src/commands/init/init.ts +203 -0
- package/src/commands/init/templates/agent-skill-mongo.md +106 -0
- package/src/commands/init/templates/agent-skill-postgres.md +106 -0
- package/src/commands/init/templates/agent-skill.ts +19 -0
- package/src/commands/init/templates/code-templates.ts +168 -0
- package/src/commands/init/templates/quick-reference-mongo.md +93 -0
- package/src/commands/init/templates/quick-reference-postgres.md +91 -0
- package/src/commands/init/templates/quick-reference.ts +19 -0
- package/src/commands/init/templates/render.ts +20 -0
- package/src/commands/init/templates/tsconfig.ts +35 -0
- package/src/commands/inspect-live-schema.ts +170 -0
- package/src/commands/migration-apply.ts +427 -0
- package/src/commands/migration-new.ts +260 -0
- package/src/commands/migration-plan.ts +519 -0
- package/src/commands/migration-ref.ts +305 -0
- package/src/commands/migration-show.ts +246 -0
- package/src/commands/migration-status.ts +864 -0
- package/src/commands/migration-verify.ts +180 -0
- package/src/config-loader.ts +13 -3
- package/src/control-api/client.ts +205 -183
- package/src/control-api/contract-enrichment.ts +119 -0
- package/src/control-api/errors.ts +9 -0
- package/src/control-api/operations/contract-emit.ts +181 -0
- package/src/control-api/operations/db-init.ts +53 -49
- package/src/control-api/operations/db-update.ts +220 -0
- package/src/control-api/operations/extract-operation-statements.ts +14 -0
- package/src/control-api/operations/extract-sql-ddl.ts +47 -0
- package/src/control-api/operations/migration-apply.ts +191 -0
- package/src/control-api/operations/migration-helpers.ts +49 -0
- package/src/control-api/types.ts +274 -52
- package/src/exports/config-types.ts +4 -3
- package/src/exports/control-api.ts +15 -5
- package/src/load-ts-contract.ts +30 -19
- package/src/utils/cli-errors.ts +14 -8
- package/src/utils/command-helpers.ts +302 -3
- package/src/utils/formatters/emit.ts +67 -0
- package/src/utils/formatters/errors.ts +82 -0
- package/src/utils/formatters/graph-migration-mapper.ts +240 -0
- package/src/utils/formatters/graph-render.ts +1323 -0
- package/src/utils/formatters/graph-types.ts +120 -0
- package/src/utils/formatters/help.ts +380 -0
- package/src/utils/formatters/helpers.ts +28 -0
- package/src/utils/formatters/migrations.ts +346 -0
- package/src/utils/formatters/styled.ts +212 -0
- package/src/utils/formatters/verify.ts +621 -0
- package/src/utils/framework-components.ts +13 -10
- package/src/utils/global-flags.ts +41 -23
- package/src/utils/migration-command-scaffold.ts +184 -0
- package/src/utils/migration-types.ts +12 -0
- package/src/utils/progress-adapter.ts +18 -29
- package/src/utils/result-handler.ts +12 -13
- package/src/utils/shutdown.ts +92 -0
- package/src/utils/suggest-command.ts +31 -0
- package/src/utils/terminal-ui.ts +276 -0
- package/src/utils/validate-contract-deps.ts +49 -0
- package/dist/chunk-AGOTG4L3.js +0 -965
- package/dist/chunk-AGOTG4L3.js.map +0 -1
- package/dist/chunk-HLLI4YL7.js +0 -180
- package/dist/chunk-HLLI4YL7.js.map +0 -1
- package/dist/chunk-HWYQOCAJ.js +0 -47
- package/dist/chunk-HWYQOCAJ.js.map +0 -1
- package/dist/chunk-VG2R7DGF.js +0 -735
- package/dist/chunk-VG2R7DGF.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/contract-emit.d.ts +0 -3
- package/dist/commands/contract-emit.d.ts.map +0 -1
- package/dist/commands/contract-emit.js +0 -10
- package/dist/commands/contract-emit.js.map +0 -1
- package/dist/commands/db-init.d.ts +0 -3
- package/dist/commands/db-init.d.ts.map +0 -1
- package/dist/commands/db-init.js +0 -257
- package/dist/commands/db-init.js.map +0 -1
- package/dist/commands/db-introspect.d.ts +0 -3
- package/dist/commands/db-introspect.d.ts.map +0 -1
- package/dist/commands/db-introspect.js +0 -155
- package/dist/commands/db-introspect.js.map +0 -1
- package/dist/commands/db-schema-verify.d.ts +0 -3
- package/dist/commands/db-schema-verify.d.ts.map +0 -1
- package/dist/commands/db-schema-verify.js +0 -171
- package/dist/commands/db-schema-verify.js.map +0 -1
- package/dist/commands/db-sign.d.ts +0 -3
- package/dist/commands/db-sign.d.ts.map +0 -1
- package/dist/commands/db-sign.js +0 -195
- package/dist/commands/db-sign.js.map +0 -1
- package/dist/commands/db-verify.d.ts +0 -3
- package/dist/commands/db-verify.d.ts.map +0 -1
- package/dist/commands/db-verify.js +0 -193
- package/dist/commands/db-verify.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js +0 -7
- package/dist/config-loader.js.map +0 -1
- package/dist/control-api/client.d.ts +0 -13
- package/dist/control-api/client.d.ts.map +0 -1
- package/dist/control-api/operations/db-init.d.ts +0 -29
- package/dist/control-api/operations/db-init.d.ts.map +0 -1
- package/dist/control-api/types.d.ts +0 -387
- package/dist/control-api/types.d.ts.map +0 -1
- package/dist/exports/config-types.d.ts +0 -3
- package/dist/exports/config-types.d.ts.map +0 -1
- package/dist/exports/config-types.js +0 -6
- package/dist/exports/config-types.js.map +0 -1
- package/dist/exports/control-api.d.ts +0 -13
- package/dist/exports/control-api.d.ts.map +0 -1
- package/dist/exports/control-api.js +0 -7
- package/dist/exports/control-api.js.map +0 -1
- package/dist/exports/index.d.ts +0 -4
- package/dist/exports/index.d.ts.map +0 -1
- package/dist/exports/index.js +0 -176
- package/dist/exports/index.js.map +0 -1
- package/dist/load-ts-contract.d.ts.map +0 -1
- package/dist/utils/cli-errors.d.ts +0 -7
- package/dist/utils/cli-errors.d.ts.map +0 -1
- package/dist/utils/command-helpers.d.ts +0 -12
- package/dist/utils/command-helpers.d.ts.map +0 -1
- package/dist/utils/framework-components.d.ts +0 -70
- package/dist/utils/framework-components.d.ts.map +0 -1
- package/dist/utils/global-flags.d.ts +0 -25
- package/dist/utils/global-flags.d.ts.map +0 -1
- package/dist/utils/output.d.ts +0 -142
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/progress-adapter.d.ts +0 -26
- package/dist/utils/progress-adapter.d.ts.map +0 -1
- package/dist/utils/result-handler.d.ts +0 -15
- package/dist/utils/result-handler.d.ts.map +0 -1
- package/src/commands/db-introspect.ts +0 -227
- package/src/commands/db-schema-verify.ts +0 -238
- package/src/utils/output.ts +0 -1471
package/src/commands/db-sign.ts
CHANGED
|
@@ -1,48 +1,45 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { relative, resolve } from 'node:path';
|
|
3
2
|
import type {
|
|
4
3
|
SignDatabaseResult,
|
|
5
4
|
VerifyDatabaseSchemaResult,
|
|
6
|
-
} from '@prisma-next/
|
|
5
|
+
} from '@prisma-next/framework-components/control';
|
|
7
6
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
8
7
|
import { Command } from 'commander';
|
|
8
|
+
import { relative, resolve } from 'pathe';
|
|
9
9
|
import { loadConfig } from '../config-loader';
|
|
10
10
|
import { createControlClient } from '../control-api/client';
|
|
11
|
+
import { ContractValidationError } from '../control-api/errors';
|
|
11
12
|
import {
|
|
12
13
|
CliStructuredError,
|
|
13
14
|
errorContractValidationFailed,
|
|
14
15
|
errorDatabaseConnectionRequired,
|
|
15
16
|
errorDriverRequired,
|
|
16
17
|
errorFileNotFound,
|
|
17
|
-
errorJsonFormatNotSupported,
|
|
18
18
|
errorUnexpected,
|
|
19
19
|
} from '../utils/cli-errors';
|
|
20
|
-
import { setCommandDescriptions } from '../utils/command-helpers';
|
|
21
|
-
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
22
20
|
import {
|
|
23
|
-
|
|
21
|
+
addGlobalOptions,
|
|
22
|
+
maskConnectionUrl,
|
|
23
|
+
resolveContractPath,
|
|
24
|
+
setCommandDescriptions,
|
|
25
|
+
setCommandExamples,
|
|
26
|
+
} from '../utils/command-helpers';
|
|
27
|
+
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
28
|
+
import {
|
|
24
29
|
formatSchemaVerifyJson,
|
|
25
30
|
formatSchemaVerifyOutput,
|
|
26
31
|
formatSignJson,
|
|
27
32
|
formatSignOutput,
|
|
28
|
-
|
|
29
|
-
} from '../utils/
|
|
33
|
+
} from '../utils/formatters/verify';
|
|
34
|
+
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
35
|
+
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
30
36
|
import { createProgressAdapter } from '../utils/progress-adapter';
|
|
31
37
|
import { handleResult } from '../utils/result-handler';
|
|
38
|
+
import { TerminalUI } from '../utils/terminal-ui';
|
|
32
39
|
|
|
33
|
-
interface DbSignOptions {
|
|
40
|
+
interface DbSignOptions extends CommonCommandOptions {
|
|
34
41
|
readonly db?: string;
|
|
35
42
|
readonly config?: string;
|
|
36
|
-
readonly json?: string | boolean;
|
|
37
|
-
readonly quiet?: boolean;
|
|
38
|
-
readonly q?: boolean;
|
|
39
|
-
readonly verbose?: boolean;
|
|
40
|
-
readonly v?: boolean;
|
|
41
|
-
readonly vv?: boolean;
|
|
42
|
-
readonly trace?: boolean;
|
|
43
|
-
readonly timestamps?: boolean;
|
|
44
|
-
readonly color?: boolean;
|
|
45
|
-
readonly 'no-color'?: boolean;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
/**
|
|
@@ -59,25 +56,24 @@ type DbSignFailure = CliStructuredError | VerifyDatabaseSchemaResult;
|
|
|
59
56
|
async function executeDbSignCommand(
|
|
60
57
|
options: DbSignOptions,
|
|
61
58
|
flags: GlobalFlags,
|
|
59
|
+
ui: TerminalUI,
|
|
62
60
|
): Promise<Result<SignDatabaseResult, DbSignFailure>> {
|
|
63
61
|
// Load config
|
|
64
62
|
const config = await loadConfig(options.config);
|
|
65
63
|
const configPath = options.config
|
|
66
64
|
? relative(process.cwd(), resolve(options.config))
|
|
67
65
|
: 'prisma-next.config.ts';
|
|
68
|
-
const contractPathAbsolute = config
|
|
69
|
-
? resolve(config.contract.output)
|
|
70
|
-
: resolve('src/prisma/contract.json');
|
|
66
|
+
const contractPathAbsolute = resolveContractPath(config);
|
|
71
67
|
const contractPath = relative(process.cwd(), contractPathAbsolute);
|
|
72
68
|
|
|
73
69
|
// Output header
|
|
74
|
-
if (flags.json
|
|
70
|
+
if (!flags.json && !flags.quiet) {
|
|
75
71
|
const details: Array<{ label: string; value: string }> = [
|
|
76
72
|
{ label: 'config', value: configPath },
|
|
77
73
|
{ label: 'contract', value: contractPath },
|
|
78
74
|
];
|
|
79
75
|
if (options.db) {
|
|
80
|
-
details.push({ label: 'database', value: options.db });
|
|
76
|
+
details.push({ label: 'database', value: maskConnectionUrl(options.db) });
|
|
81
77
|
}
|
|
82
78
|
const header = formatStyledHeader({
|
|
83
79
|
command: 'db sign',
|
|
@@ -86,7 +82,7 @@ async function executeDbSignCommand(
|
|
|
86
82
|
details,
|
|
87
83
|
flags,
|
|
88
84
|
});
|
|
89
|
-
|
|
85
|
+
ui.stderr(header);
|
|
90
86
|
}
|
|
91
87
|
|
|
92
88
|
// Load contract file
|
|
@@ -127,6 +123,7 @@ async function executeDbSignCommand(
|
|
|
127
123
|
return notOk(
|
|
128
124
|
errorDatabaseConnectionRequired({
|
|
129
125
|
why: `Database connection is required for db sign (set db.connection in ${configPath}, or pass --db <url>)`,
|
|
126
|
+
commandName: 'db sign',
|
|
130
127
|
}),
|
|
131
128
|
);
|
|
132
129
|
}
|
|
@@ -146,12 +143,12 @@ async function executeDbSignCommand(
|
|
|
146
143
|
});
|
|
147
144
|
|
|
148
145
|
// Create progress adapter
|
|
149
|
-
const onProgress = createProgressAdapter({ flags });
|
|
146
|
+
const onProgress = createProgressAdapter({ ui, flags });
|
|
150
147
|
|
|
151
148
|
try {
|
|
152
149
|
// Step 1: Schema verification - connect here
|
|
153
150
|
const schemaVerifyResult = await client.schemaVerify({
|
|
154
|
-
|
|
151
|
+
contract: contractJson,
|
|
155
152
|
strict: false,
|
|
156
153
|
connection: dbConnection,
|
|
157
154
|
onProgress,
|
|
@@ -159,26 +156,17 @@ async function executeDbSignCommand(
|
|
|
159
156
|
|
|
160
157
|
// If schema verification failed, return as failure
|
|
161
158
|
if (!schemaVerifyResult.ok) {
|
|
162
|
-
// Add blank line after all async operations if spinners were shown
|
|
163
|
-
if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {
|
|
164
|
-
console.log('');
|
|
165
|
-
}
|
|
166
159
|
return notOk(schemaVerifyResult);
|
|
167
160
|
}
|
|
168
161
|
|
|
169
162
|
// Step 2: Sign (already connected from schemaVerify)
|
|
170
163
|
const signResult = await client.sign({
|
|
171
|
-
|
|
164
|
+
contract: contractJson,
|
|
172
165
|
contractPath,
|
|
173
166
|
configPath,
|
|
174
167
|
onProgress,
|
|
175
168
|
});
|
|
176
169
|
|
|
177
|
-
// Add blank line after all async operations if spinners were shown
|
|
178
|
-
if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {
|
|
179
|
-
console.log('');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
170
|
return ok(signResult);
|
|
183
171
|
} catch (error) {
|
|
184
172
|
// Driver already throws CliStructuredError for connection failures
|
|
@@ -186,6 +174,14 @@ async function executeDbSignCommand(
|
|
|
186
174
|
return notOk(error);
|
|
187
175
|
}
|
|
188
176
|
|
|
177
|
+
if (error instanceof ContractValidationError) {
|
|
178
|
+
return notOk(
|
|
179
|
+
errorContractValidationFailed(`Contract validation failed: ${error.message}`, {
|
|
180
|
+
where: { path: contractPathAbsolute },
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
189
185
|
// Wrap unexpected errors
|
|
190
186
|
return notOk(
|
|
191
187
|
errorUnexpected(error instanceof Error ? error.message : String(error), {
|
|
@@ -203,52 +199,29 @@ export function createDbSignCommand(): Command {
|
|
|
203
199
|
command,
|
|
204
200
|
'Sign the database with your contract so you can safely run queries',
|
|
205
201
|
'Verifies that your database schema satisfies the emitted contract, and if so, writes or\n' +
|
|
206
|
-
'updates the
|
|
207
|
-
'in CI/deployment pipelines. The
|
|
202
|
+
'updates the database signature. This command is idempotent and safe to run\n' +
|
|
203
|
+
'in CI/deployment pipelines. The signature records that this database instance is aligned\n' +
|
|
208
204
|
'with a specific contract version.',
|
|
209
205
|
);
|
|
210
|
-
command
|
|
211
|
-
|
|
212
|
-
formatHelp: (cmd) => {
|
|
213
|
-
const flags = parseGlobalFlags({});
|
|
214
|
-
return formatCommandHelp({ command: cmd, flags });
|
|
215
|
-
},
|
|
216
|
-
})
|
|
206
|
+
setCommandExamples(command, ['prisma-next db sign --db $DATABASE_URL']);
|
|
207
|
+
addGlobalOptions(command)
|
|
217
208
|
.option('--db <url>', 'Database connection string')
|
|
218
209
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
219
|
-
.option('--json [format]', 'Output as JSON (object)', false)
|
|
220
|
-
.option('-q, --quiet', 'Quiet mode: errors only')
|
|
221
|
-
.option('-v, --verbose', 'Verbose output: debug info, timings')
|
|
222
|
-
.option('-vv, --trace', 'Trace output: deep internals, stack traces')
|
|
223
|
-
.option('--timestamps', 'Add timestamps to output')
|
|
224
|
-
.option('--color', 'Force color output')
|
|
225
|
-
.option('--no-color', 'Disable color output')
|
|
226
210
|
.action(async (options: DbSignOptions) => {
|
|
227
211
|
const flags = parseGlobalFlags(options);
|
|
228
212
|
|
|
229
|
-
|
|
230
|
-
if (flags.json === 'ndjson') {
|
|
231
|
-
const result = notOk(
|
|
232
|
-
errorJsonFormatNotSupported({
|
|
233
|
-
command: 'db sign',
|
|
234
|
-
format: 'ndjson',
|
|
235
|
-
supportedFormats: ['object'],
|
|
236
|
-
}),
|
|
237
|
-
);
|
|
238
|
-
const exitCode = handleResult(result, flags);
|
|
239
|
-
process.exit(exitCode);
|
|
240
|
-
}
|
|
213
|
+
const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
|
|
241
214
|
|
|
242
|
-
const result = await executeDbSignCommand(options, flags);
|
|
215
|
+
const result = await executeDbSignCommand(options, flags, ui);
|
|
243
216
|
|
|
244
217
|
if (result.ok) {
|
|
245
218
|
// Success - format sign output
|
|
246
|
-
if (flags.json
|
|
247
|
-
|
|
219
|
+
if (flags.json) {
|
|
220
|
+
ui.output(formatSignJson(result.value));
|
|
248
221
|
} else {
|
|
249
222
|
const output = formatSignOutput(result.value, flags);
|
|
250
223
|
if (output) {
|
|
251
|
-
|
|
224
|
+
ui.log(output);
|
|
252
225
|
}
|
|
253
226
|
}
|
|
254
227
|
process.exit(0);
|
|
@@ -259,17 +232,17 @@ export function createDbSignCommand(): Command {
|
|
|
259
232
|
|
|
260
233
|
if (failure instanceof CliStructuredError) {
|
|
261
234
|
// Infrastructure error - use standard handler
|
|
262
|
-
const exitCode = handleResult(result as Result<never, CliStructuredError>, flags);
|
|
235
|
+
const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);
|
|
263
236
|
process.exit(exitCode);
|
|
264
237
|
}
|
|
265
238
|
|
|
266
239
|
// Schema verification failed - format and print schema verification output
|
|
267
|
-
if (flags.json
|
|
268
|
-
|
|
240
|
+
if (flags.json) {
|
|
241
|
+
ui.output(formatSchemaVerifyJson(failure));
|
|
269
242
|
} else {
|
|
270
243
|
const output = formatSchemaVerifyOutput(failure, flags);
|
|
271
244
|
if (output) {
|
|
272
|
-
|
|
245
|
+
ui.log(output);
|
|
273
246
|
}
|
|
274
247
|
}
|
|
275
248
|
process.exit(1);
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { ContractValidationError } from '../control-api/errors';
|
|
5
|
+
import type { DbUpdateFailure } from '../control-api/types';
|
|
6
|
+
import {
|
|
7
|
+
CliStructuredError,
|
|
8
|
+
ERROR_CODE_DESTRUCTIVE_CHANGES,
|
|
9
|
+
errorContractValidationFailed,
|
|
10
|
+
errorDestructiveChanges,
|
|
11
|
+
errorMigrationPlanningFailed,
|
|
12
|
+
errorRunnerFailed,
|
|
13
|
+
errorUnexpected,
|
|
14
|
+
} from '../utils/cli-errors';
|
|
15
|
+
import type { MigrationCommandOptions } from '../utils/command-helpers';
|
|
16
|
+
import {
|
|
17
|
+
sanitizeErrorMessage,
|
|
18
|
+
setCommandDescriptions,
|
|
19
|
+
setCommandExamples,
|
|
20
|
+
} from '../utils/command-helpers';
|
|
21
|
+
import {
|
|
22
|
+
formatMigrationApplyOutput,
|
|
23
|
+
formatMigrationJson,
|
|
24
|
+
formatMigrationPlanOutput,
|
|
25
|
+
type MigrationCommandResult,
|
|
26
|
+
} from '../utils/formatters/migrations';
|
|
27
|
+
import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
|
|
28
|
+
import {
|
|
29
|
+
addMigrationCommandOptions,
|
|
30
|
+
prepareMigrationContext,
|
|
31
|
+
} from '../utils/migration-command-scaffold';
|
|
32
|
+
import { handleResult } from '../utils/result-handler';
|
|
33
|
+
import { TerminalUI } from '../utils/terminal-ui';
|
|
34
|
+
|
|
35
|
+
type DbUpdateOptions = MigrationCommandOptions;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.
|
|
39
|
+
*/
|
|
40
|
+
function mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {
|
|
41
|
+
if (failure.code === 'PLANNING_FAILED') {
|
|
42
|
+
return errorMigrationPlanningFailed({ conflicts: failure.conflicts ?? [] });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (failure.code === 'RUNNER_FAILED') {
|
|
46
|
+
return errorRunnerFailed(failure.summary, {
|
|
47
|
+
why: failure.why ?? 'Migration runner failed',
|
|
48
|
+
fix: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`',
|
|
49
|
+
...ifDefined('meta', failure.meta),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (failure.code === 'DESTRUCTIVE_CHANGES') {
|
|
54
|
+
return errorDestructiveChanges(failure.summary, {
|
|
55
|
+
...ifDefined('why', failure.why),
|
|
56
|
+
fix: 'Re-run with `-y` to apply destructive changes, or use `--dry-run` to preview first',
|
|
57
|
+
...ifDefined('meta', failure.meta),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const exhaustive: never = failure.code;
|
|
62
|
+
throw new Error(`Unhandled DbUpdateFailure code: ${exhaustive}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Executes the db update command and returns a structured Result.
|
|
67
|
+
*/
|
|
68
|
+
async function executeDbUpdateCommand(
|
|
69
|
+
options: DbUpdateOptions,
|
|
70
|
+
flags: GlobalFlags,
|
|
71
|
+
ui: TerminalUI,
|
|
72
|
+
startTime: number,
|
|
73
|
+
): Promise<Result<MigrationCommandResult, CliStructuredError>> {
|
|
74
|
+
// Prepare shared migration context (config, contract, connection, client)
|
|
75
|
+
const ctxResult = await prepareMigrationContext(options, flags, ui, {
|
|
76
|
+
commandName: 'db update',
|
|
77
|
+
description: 'Update your database schema to match your contract',
|
|
78
|
+
url: 'https://pris.ly/db-update',
|
|
79
|
+
});
|
|
80
|
+
if (!ctxResult.ok) {
|
|
81
|
+
return ctxResult;
|
|
82
|
+
}
|
|
83
|
+
const { client, contractJson, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// Call dbUpdate with connection and progress callback
|
|
87
|
+
const result = await client.dbUpdate({
|
|
88
|
+
contract: contractJson,
|
|
89
|
+
mode: options.dryRun ? 'plan' : 'apply',
|
|
90
|
+
connection: dbConnection,
|
|
91
|
+
...(flags.yes ? { acceptDataLoss: true } : {}),
|
|
92
|
+
onProgress,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Handle failures by mapping to CLI structured error
|
|
96
|
+
if (!result.ok) {
|
|
97
|
+
return notOk(mapDbUpdateFailure(result.failure));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Convert success result to CLI output format
|
|
101
|
+
const dbUpdateResult: MigrationCommandResult = {
|
|
102
|
+
ok: true,
|
|
103
|
+
mode: result.value.mode,
|
|
104
|
+
plan: {
|
|
105
|
+
targetId: ctxResult.value.config.target.targetId,
|
|
106
|
+
destination: {
|
|
107
|
+
storageHash: result.value.destination.storageHash,
|
|
108
|
+
...ifDefined('profileHash', result.value.destination.profileHash),
|
|
109
|
+
},
|
|
110
|
+
operations: result.value.plan.operations.map((op) => ({
|
|
111
|
+
id: op.id,
|
|
112
|
+
label: op.label,
|
|
113
|
+
operationClass: op.operationClass,
|
|
114
|
+
})),
|
|
115
|
+
...ifDefined('sql', result.value.plan.sql),
|
|
116
|
+
},
|
|
117
|
+
...ifDefined(
|
|
118
|
+
'execution',
|
|
119
|
+
result.value.execution
|
|
120
|
+
? {
|
|
121
|
+
operationsPlanned: result.value.execution.operationsPlanned,
|
|
122
|
+
operationsExecuted: result.value.execution.operationsExecuted,
|
|
123
|
+
}
|
|
124
|
+
: undefined,
|
|
125
|
+
),
|
|
126
|
+
...ifDefined(
|
|
127
|
+
'marker',
|
|
128
|
+
result.value.marker
|
|
129
|
+
? {
|
|
130
|
+
storageHash: result.value.marker.storageHash,
|
|
131
|
+
...ifDefined('profileHash', result.value.marker.profileHash),
|
|
132
|
+
}
|
|
133
|
+
: undefined,
|
|
134
|
+
),
|
|
135
|
+
summary: result.value.summary,
|
|
136
|
+
timings: { total: Date.now() - startTime },
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return ok(dbUpdateResult);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (CliStructuredError.is(error)) {
|
|
142
|
+
return notOk(error);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (error instanceof ContractValidationError) {
|
|
146
|
+
return notOk(
|
|
147
|
+
errorContractValidationFailed(`Contract validation failed: ${error.message}`, {
|
|
148
|
+
where: { path: contractPathAbsolute },
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
154
|
+
const safeMessage = sanitizeErrorMessage(
|
|
155
|
+
rawMessage,
|
|
156
|
+
typeof dbConnection === 'string' ? dbConnection : undefined,
|
|
157
|
+
);
|
|
158
|
+
return notOk(
|
|
159
|
+
errorUnexpected(safeMessage, {
|
|
160
|
+
why: `Unexpected error during db update: ${safeMessage}`,
|
|
161
|
+
}),
|
|
162
|
+
);
|
|
163
|
+
} finally {
|
|
164
|
+
await client.close();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function createDbUpdateCommand(): Command {
|
|
169
|
+
const command = new Command('update');
|
|
170
|
+
setCommandDescriptions(
|
|
171
|
+
command,
|
|
172
|
+
'Update your database schema to match your contract',
|
|
173
|
+
'Compares your database schema to the emitted contract and applies the necessary\n' +
|
|
174
|
+
'changes. Works on any database, whether or not it has been initialized with `db init`.\n' +
|
|
175
|
+
'Destructive operations prompt for confirmation in interactive mode. Use -y to\n' +
|
|
176
|
+
'auto-accept or --dry-run to preview first.',
|
|
177
|
+
);
|
|
178
|
+
setCommandExamples(command, [
|
|
179
|
+
'prisma-next db update --db $DATABASE_URL',
|
|
180
|
+
'prisma-next db update --db $DATABASE_URL --dry-run',
|
|
181
|
+
]);
|
|
182
|
+
addMigrationCommandOptions(command);
|
|
183
|
+
command.action(async (options: DbUpdateOptions) => {
|
|
184
|
+
const flags = parseGlobalFlags(options);
|
|
185
|
+
const startTime = Date.now();
|
|
186
|
+
|
|
187
|
+
const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
|
|
188
|
+
|
|
189
|
+
let result = await executeDbUpdateCommand(options, flags, ui, startTime);
|
|
190
|
+
|
|
191
|
+
// Interactive confirmation for destructive operations:
|
|
192
|
+
// When the control API rejects destructive changes, prompt the user instead of failing.
|
|
193
|
+
// In non-interactive mode (CI, piped, --no-interactive, --json), the error is returned as-is.
|
|
194
|
+
if (
|
|
195
|
+
!result.ok &&
|
|
196
|
+
result.failure.code === ERROR_CODE_DESTRUCTIVE_CHANGES &&
|
|
197
|
+
flags.interactive &&
|
|
198
|
+
!flags.json &&
|
|
199
|
+
!flags.yes
|
|
200
|
+
) {
|
|
201
|
+
const meta = result.failure.meta as
|
|
202
|
+
| { destructiveOperations?: readonly { id: string; label: string }[] }
|
|
203
|
+
| undefined;
|
|
204
|
+
const destructiveOps = meta?.destructiveOperations ?? [];
|
|
205
|
+
|
|
206
|
+
if (destructiveOps.length > 0) {
|
|
207
|
+
ui.warn(
|
|
208
|
+
`${destructiveOps.length} destructive operation(s) that may cause data loss:\n${destructiveOps.map((op) => ` ${ui.yellow('▸')} ${op.label}`).join('\n')}`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const confirmed = await ui.confirm('Apply destructive changes? This cannot be undone.');
|
|
213
|
+
|
|
214
|
+
if (confirmed) {
|
|
215
|
+
result = await executeDbUpdateCommand(options, { ...flags, yes: true }, ui, Date.now());
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const exitCode = handleResult(result, flags, ui, (dbUpdateResult) => {
|
|
220
|
+
if (flags.json) {
|
|
221
|
+
ui.output(formatMigrationJson(dbUpdateResult));
|
|
222
|
+
} else {
|
|
223
|
+
const output =
|
|
224
|
+
dbUpdateResult.mode === 'plan'
|
|
225
|
+
? formatMigrationPlanOutput(dbUpdateResult, flags)
|
|
226
|
+
: formatMigrationApplyOutput(dbUpdateResult, flags);
|
|
227
|
+
if (output) {
|
|
228
|
+
ui.log(output);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
process.exit(exitCode);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
return command;
|
|
236
|
+
}
|