prisma-next 0.8.0 → 0.9.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-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
- package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
- package/dist/cli.mjs +67 -19
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-BCnP7cHo.mjs → client-Brv4qlfB.mjs} +28 -30
- package/dist/client-Brv4qlfB.mjs.map +1 -0
- package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
- package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +7 -7
- package/dist/commands/db-schema.mjs +5 -5
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +67 -25
- 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 +37 -9
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +28 -0
- package/dist/commands/migrate.d.mts.map +1 -0
- package/dist/commands/{migration-apply.mjs → migrate.mjs} +65 -39
- package/dist/commands/migrate.mjs.map +1 -0
- package/dist/commands/migration-check.d.mts +18 -0
- package/dist/commands/migration-check.d.mts.map +1 -0
- package/dist/commands/migration-check.mjs +284 -0
- package/dist/commands/migration-check.mjs.map +1 -0
- package/dist/commands/migration-graph.d.mts +16 -0
- package/dist/commands/migration-graph.d.mts.map +1 -0
- package/dist/commands/migration-graph.mjs +141 -0
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +20 -0
- package/dist/commands/migration-list.d.mts.map +1 -0
- package/dist/commands/migration-list.mjs +107 -0
- package/dist/commands/migration-list.mjs.map +1 -0
- package/dist/commands/migration-log.d.mts +21 -0
- package/dist/commands/migration-log.d.mts.map +1 -0
- package/dist/commands/migration-log.mjs +146 -0
- package/dist/commands/migration-log.mjs.map +1 -0
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +30 -29
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +2 -2
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +90 -52
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +5 -17
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +732 -1
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/ref.d.mts +34 -0
- package/dist/commands/ref.d.mts.map +1 -0
- package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
- package/dist/commands/ref.mjs.map +1 -0
- package/dist/{contract-emit-9DBda5Ou.mjs → contract-emit-C3STUIBg.mjs} +6 -6
- package/dist/{contract-emit-9DBda5Ou.mjs.map → contract-emit-C3STUIBg.mjs.map} +1 -1
- package/dist/{contract-emit-B77TsJqf.mjs → contract-emit-iynA3BCA.mjs} +9 -5
- package/dist/contract-emit-iynA3BCA.mjs.map +1 -0
- package/dist/{contract-infer-ByxhPjpW.mjs → contract-infer-Cnj8G1E2.mjs} +5 -5
- package/dist/{contract-infer-ByxhPjpW.mjs.map → contract-infer-Cnj8G1E2.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-pAc8CDfY.mjs} +4 -4
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-pAc8CDfY.mjs.map} +1 -1
- package/dist/{db-verify-Czm5T-J4.mjs → db-verify-D7cyH_zz.mjs} +12 -9
- package/dist/db-verify-D7cyH_zz.mjs.map +1 -0
- package/dist/errors-Cw6kyTyV.mjs +56 -0
- package/dist/errors-Cw6kyTyV.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
- package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
- package/dist/{migration-status-By9G5p2H.mjs → graph-render-eJDcLWny.mjs} +3 -692
- package/dist/graph-render-eJDcLWny.mjs.map +1 -0
- package/dist/{init-B-k3a1Qw.mjs → init-Bqg5JWg7.mjs} +133 -61
- package/dist/init-Bqg5JWg7.mjs.map +1 -0
- package/dist/{inspect-live-schema-DxdBd4Er.mjs → inspect-live-schema-CWLK_lgs.mjs} +4 -4
- package/dist/{inspect-live-schema-DxdBd4Er.mjs.map → inspect-live-schema-CWLK_lgs.mjs.map} +1 -1
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs → migration-command-scaffold-CmXXC1UZ.mjs} +4 -4
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs.map → migration-command-scaffold-CmXXC1UZ.mjs.map} +1 -1
- package/dist/{migration-plan-mRu5K81L.mjs → migration-plan-CHyUlBV0.mjs} +76 -37
- package/dist/migration-plan-CHyUlBV0.mjs.map +1 -0
- package/dist/migration-types-D2FW63pr.d.mts +15 -0
- package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
- package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
- package/dist/migrations-DyUf5lTt.mjs.map +1 -0
- package/dist/{output-BVj6a971.mjs → output-B60Gw5fu.mjs} +12 -11
- package/dist/{output-BVj6a971.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
- package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
- package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
- package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
- package/dist/{types-LItU7E4l.d.mts → types-0aS865QN.d.mts} +14 -8
- package/dist/types-0aS865QN.d.mts.map +1 -0
- package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
- package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
- package/package.json +10 -10
- package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
- package/dist/client-BCnP7cHo.mjs.map +0 -1
- package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
- package/dist/commands/migration-apply.d.mts +0 -51
- package/dist/commands/migration-apply.d.mts.map +0 -1
- package/dist/commands/migration-apply.mjs.map +0 -1
- package/dist/commands/migration-ref.d.mts +0 -45
- package/dist/commands/migration-ref.d.mts.map +0 -1
- package/dist/commands/migration-ref.mjs.map +0 -1
- package/dist/contract-emit-B77TsJqf.mjs.map +0 -1
- package/dist/db-verify-Czm5T-J4.mjs.map +0 -1
- package/dist/init-B-k3a1Qw.mjs.map +0 -1
- package/dist/migration-plan-mRu5K81L.mjs.map +0 -1
- package/dist/migration-status-By9G5p2H.mjs.map +0 -1
- package/dist/migrations-CTsyBXCA.mjs.map +0 -1
- package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
- package/dist/types-LItU7E4l.d.mts.map +0 -1
- /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
import { t as loadConfig } from "../config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, l as errorFileNotFound, o as errorDatabaseConnectionRequired, t as CliStructuredError } from "../cli-errors-
|
|
3
|
-
import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples,
|
|
2
|
+
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, l as errorFileNotFound, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, v as mapMigrationToolsError, y as mapRefResolutionError } from "../cli-errors-CF60g2cG.mjs";
|
|
3
|
+
import { _ as parseGlobalFlags, a as loadMigrationPackages, b as formatStyledHeader, c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, l as resolveMigrationPaths, o as maskConnectionUrl, t as addGlobalOptions } from "../command-helpers-D3vL5yi8.mjs";
|
|
4
4
|
import { t as createProgressAdapter } from "../progress-adapter-DFfvZcYL.mjs";
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as
|
|
7
|
-
import { a as ContractValidationError, t as createControlClient } from "../client-
|
|
8
|
-
import { a as formatSignJson, i as formatSchemaVerifyOutput, o as formatSignOutput, r as formatSchemaVerifyJson } from "../verify-
|
|
5
|
+
import { t as handleResult } from "../result-handler-Bm_6dDYg.mjs";
|
|
6
|
+
import { t as TerminalUI } from "../terminal-ui-XtOQsqe9.mjs";
|
|
7
|
+
import { a as ContractValidationError, t as createControlClient } from "../client-Brv4qlfB.mjs";
|
|
8
|
+
import { a as formatSignJson, i as formatSchemaVerifyOutput, o as formatSignOutput, r as formatSchemaVerifyJson } from "../verify-D7ypCCe6.mjs";
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
11
|
-
import { relative, resolve } from "pathe";
|
|
11
|
+
import { join, relative, resolve } from "pathe";
|
|
12
12
|
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
14
|
+
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
15
|
+
import { readRefs } from "@prisma-next/migration-tools/refs";
|
|
13
16
|
//#region src/commands/db-sign.ts
|
|
14
17
|
/**
|
|
15
18
|
* Executes the db sign command and returns a structured Result.
|
|
16
19
|
* Success: SignDatabaseResult (sign happened)
|
|
17
20
|
* Failure: CliStructuredError (infra error) or VerifyDatabaseSchemaResult (schema mismatch)
|
|
18
21
|
*/
|
|
19
|
-
async function executeDbSignCommand(options, flags, ui) {
|
|
22
|
+
async function executeDbSignCommand(contractArg, options, flags, ui) {
|
|
20
23
|
const config = await loadConfig(options.config);
|
|
21
24
|
const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
|
|
22
25
|
const contractPathAbsolute = resolveContractPath(config);
|
|
23
26
|
const contractPath = relative(process.cwd(), contractPathAbsolute);
|
|
27
|
+
const effectiveContractArg = contractArg ?? options.contract;
|
|
24
28
|
if (!flags.json && !flags.quiet) {
|
|
25
29
|
const details = [{
|
|
26
30
|
label: "config",
|
|
27
31
|
value: configPath
|
|
28
32
|
}, {
|
|
29
33
|
label: "contract",
|
|
30
|
-
value: contractPath
|
|
34
|
+
value: effectiveContractArg ?? contractPath
|
|
31
35
|
}];
|
|
32
36
|
if (options.db) details.push({
|
|
33
37
|
label: "database",
|
|
@@ -42,21 +46,50 @@ async function executeDbSignCommand(options, flags, ui) {
|
|
|
42
46
|
});
|
|
43
47
|
ui.stderr(header);
|
|
44
48
|
}
|
|
45
|
-
let contractJsonContent;
|
|
46
|
-
try {
|
|
47
|
-
contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
|
|
48
|
-
} catch (error) {
|
|
49
|
-
if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
|
|
50
|
-
why: `Contract file not found at ${contractPathAbsolute}`,
|
|
51
|
-
fix: `Run \`prisma-next contract emit\` to generate ${contractPath}, or update \`config.contract.output\` in ${configPath}`
|
|
52
|
-
}));
|
|
53
|
-
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}` }));
|
|
54
|
-
}
|
|
55
49
|
let contractJson;
|
|
56
|
-
try {
|
|
57
|
-
|
|
50
|
+
if (effectiveContractArg) try {
|
|
51
|
+
const { appMigrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
|
|
52
|
+
const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);
|
|
53
|
+
const refResult = parseContractRef(effectiveContractArg, {
|
|
54
|
+
graph,
|
|
55
|
+
refs: await readRefs(refsDir)
|
|
56
|
+
});
|
|
57
|
+
if (!refResult.ok) return notOk(mapRefResolutionError(refResult.failure));
|
|
58
|
+
const targetHash = refResult.value.hash;
|
|
59
|
+
const matchingBundle = bundles.find((p) => p.metadata.to === targetHash);
|
|
60
|
+
if (matchingBundle) {
|
|
61
|
+
const raw = await readFile(join(matchingBundle.dirPath, "end-contract.json"), "utf-8");
|
|
62
|
+
contractJson = JSON.parse(raw);
|
|
63
|
+
} else {
|
|
64
|
+
const defaultRaw = await readFile(contractPathAbsolute, "utf-8");
|
|
65
|
+
const defaultContract = JSON.parse(defaultRaw);
|
|
66
|
+
if (defaultContract["storage"]?.["storageHash"] === targetHash) contractJson = defaultContract;
|
|
67
|
+
else return notOk(errorRuntime(`No contract file found for hash "${targetHash}"`, {
|
|
68
|
+
why: `Resolved contract reference "${effectiveContractArg}" to hash "${targetHash}" but no migration produces that hash and the emitted contract does not match.`,
|
|
69
|
+
fix: "Ensure the target contract exists on disk — either as a migration endpoint or as the emitted contract.json."
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
58
72
|
} catch (error) {
|
|
59
|
-
|
|
73
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
74
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
75
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to resolve contract reference: ${error instanceof Error ? error.message : String(error)}` }));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
let contractJsonContent;
|
|
79
|
+
try {
|
|
80
|
+
contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
|
|
83
|
+
why: `Contract file not found at ${contractPathAbsolute}`,
|
|
84
|
+
fix: `Run \`prisma-next contract emit\` to generate ${contractPath}, or update \`config.contract.output\` in ${configPath}`
|
|
85
|
+
}));
|
|
86
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}` }));
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
contractJson = JSON.parse(contractJsonContent);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return notOk(errorContractValidationFailed(`Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
|
|
92
|
+
}
|
|
60
93
|
}
|
|
61
94
|
const dbConnection = options.db ?? config.db?.connection;
|
|
62
95
|
if (!dbConnection) return notOk(errorDatabaseConnectionRequired({
|
|
@@ -100,14 +133,23 @@ async function executeDbSignCommand(options, flags, ui) {
|
|
|
100
133
|
function createDbSignCommand() {
|
|
101
134
|
const command = new Command("sign");
|
|
102
135
|
setCommandDescriptions(command, "Sign the database with your contract so you can safely run queries", "Verifies that your database schema satisfies the emitted contract, and if so, writes or\nupdates the database signature. This command is idempotent and safe to run\nin CI/deployment pipelines. The signature records that this database instance is aligned\nwith a specific contract version.");
|
|
103
|
-
setCommandExamples(command, [
|
|
104
|
-
|
|
136
|
+
setCommandExamples(command, [
|
|
137
|
+
"prisma-next db sign --db $DATABASE_URL",
|
|
138
|
+
"prisma-next db sign production --db $DATABASE_URL",
|
|
139
|
+
"prisma-next db sign --contract production --db $DATABASE_URL"
|
|
140
|
+
]);
|
|
141
|
+
addGlobalOptions(command).argument("[contract]", "Contract reference (hash, prefix, ref name, or migration dir name)").option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--contract <contract>", "Contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)").action(async (positionalContract, options) => {
|
|
105
142
|
const flags = parseGlobalFlags(options);
|
|
143
|
+
if (positionalContract && options.contract) {
|
|
144
|
+
process.stderr.write("Cannot specify both a positional contract argument and --contract flag.\n");
|
|
145
|
+
process.exit(2);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
106
148
|
const ui = new TerminalUI({
|
|
107
149
|
color: flags.color,
|
|
108
150
|
interactive: flags.interactive
|
|
109
151
|
});
|
|
110
|
-
const result = await executeDbSignCommand(options, flags, ui);
|
|
152
|
+
const result = await executeDbSignCommand(positionalContract, options, flags, ui);
|
|
111
153
|
if (result.ok) {
|
|
112
154
|
if (flags.json) ui.output(formatSignJson(result.value));
|
|
113
155
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-sign.mjs","names":[],"sources":["../../src/commands/db-sign.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type {\n SignDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport { ContractValidationError } from '../control-api/errors';\nimport {\n CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveContractPath,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport {\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatSignJson,\n formatSignOutput,\n} from '../utils/formatters/verify';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface DbSignOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n}\n\n/**\n * Failure type for db sign command.\n * Either an infrastructure error (CliStructuredError) or a logical failure (schema verification failed).\n */\ntype DbSignFailure = CliStructuredError | VerifyDatabaseSchemaResult;\n\n/**\n * Executes the db sign command and returns a structured Result.\n * Success: SignDatabaseResult (sign happened)\n * Failure: CliStructuredError (infra error) or VerifyDatabaseSchemaResult (schema mismatch)\n */\nasync function executeDbSignCommand(\n options: DbSignOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<SignDatabaseResult, DbSignFailure>> {\n // Load config\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n const header = formatStyledHeader({\n command: 'db sign',\n description: 'Sign the database with your contract so you can safely run queries',\n url: 'https://pris.ly/db-sign',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for db sign (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'db sign',\n }),\n );\n }\n\n // Check for driver\n if (!config.driver) {\n return notOk(errorDriverRequired({ why: 'Config.driver is required for db sign' }));\n }\n\n // Create control client\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Step 1: Schema verification - connect here\n const schemaVerifyResult = await client.schemaVerify({\n contract: contractJson,\n strict: false,\n connection: dbConnection,\n onProgress,\n });\n\n // If schema verification failed, return as failure\n if (!schemaVerifyResult.ok) {\n return notOk(schemaVerifyResult);\n }\n\n // Step 2: Sign (already connected from schemaVerify)\n const signResult = await client.sign({\n contract: contractJson,\n contractPath,\n configPath,\n onProgress,\n });\n\n return ok(signResult);\n } catch (error) {\n // Driver already throws CliStructuredError for connection failures\n if (error instanceof CliStructuredError) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n // Wrap unexpected errors\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during db sign: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbSignCommand(): Command {\n const command = new Command('sign');\n setCommandDescriptions(\n command,\n 'Sign the database with your contract so you can safely run queries',\n 'Verifies that your database schema satisfies the emitted contract, and if so, writes or\\n' +\n 'updates the database signature. This command is idempotent and safe to run\\n' +\n 'in CI/deployment pipelines. The signature records that this database instance is aligned\\n' +\n 'with a specific contract version.',\n );\n setCommandExamples(command, ['prisma-next db sign --db $DATABASE_URL']);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: DbSignOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeDbSignCommand(options, flags, ui);\n\n if (result.ok) {\n // Success - format sign output\n if (flags.json) {\n ui.output(formatSignJson(result.value));\n } else {\n const output = formatSignOutput(result.value, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(0);\n }\n\n // Failure - determine type and handle appropriately\n const failure = result.failure;\n\n if (failure instanceof CliStructuredError) {\n // Infrastructure error - use standard handler\n const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n // Schema verification failed - format and print schema verification output\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(failure));\n } else {\n const output = formatSchemaVerifyOutput(failure, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(1);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"db-sign.mjs","names":[],"sources":["../../src/commands/db-sign.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type {\n SignDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport { ContractValidationError } from '../control-api/errors';\nimport {\n CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n loadMigrationPackages,\n maskConnectionUrl,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport {\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatSignJson,\n formatSignOutput,\n} from '../utils/formatters/verify';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface DbSignOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly contract?: string;\n}\n\n/**\n * Failure type for db sign command.\n * Either an infrastructure error (CliStructuredError) or a logical failure (schema verification failed).\n */\ntype DbSignFailure = CliStructuredError | VerifyDatabaseSchemaResult;\n\n/**\n * Executes the db sign command and returns a structured Result.\n * Success: SignDatabaseResult (sign happened)\n * Failure: CliStructuredError (infra error) or VerifyDatabaseSchemaResult (schema mismatch)\n */\nasync function executeDbSignCommand(\n contractArg: string | undefined,\n options: DbSignOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<SignDatabaseResult, DbSignFailure>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n const effectiveContractArg = contractArg ?? options.contract;\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: effectiveContractArg ?? contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n const header = formatStyledHeader({\n command: 'db sign',\n description: 'Sign the database with your contract so you can safely run queries',\n url: 'https://pris.ly/db-sign',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let contractJson: Record<string, unknown>;\n\n if (effectiveContractArg) {\n try {\n const { appMigrationsDir, refsDir } = resolveMigrationPaths(options.config, config);\n const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);\n const refs = await readRefs(refsDir);\n const refResult = parseContractRef(effectiveContractArg, { graph, refs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n const targetHash = refResult.value.hash;\n const matchingBundle = bundles.find((p) => p.metadata.to === targetHash);\n if (matchingBundle) {\n const endContractPath = join(matchingBundle.dirPath, 'end-contract.json');\n const raw = await readFile(endContractPath, 'utf-8');\n contractJson = JSON.parse(raw) as Record<string, unknown>;\n } else {\n const defaultRaw = await readFile(contractPathAbsolute, 'utf-8');\n const defaultContract = JSON.parse(defaultRaw) as Record<string, unknown>;\n const storageHash = (defaultContract['storage'] as Record<string, unknown> | undefined)?.[\n 'storageHash'\n ];\n if (storageHash === targetHash) {\n contractJson = defaultContract;\n } else {\n return notOk(\n errorRuntime(`No contract file found for hash \"${targetHash}\"`, {\n why: `Resolved contract reference \"${effectiveContractArg}\" to hash \"${targetHash}\" but no migration produces that hash and the emitted contract does not match.`,\n fix: 'Ensure the target contract exists on disk — either as a migration endpoint or as the emitted contract.json.',\n }),\n );\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));\n if (error instanceof CliStructuredError) return notOk(error);\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to resolve contract reference: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n } else {\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n }\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for db sign (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'db sign',\n }),\n );\n }\n\n // Check for driver\n if (!config.driver) {\n return notOk(errorDriverRequired({ why: 'Config.driver is required for db sign' }));\n }\n\n // Create control client\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Step 1: Schema verification - connect here\n const schemaVerifyResult = await client.schemaVerify({\n contract: contractJson,\n strict: false,\n connection: dbConnection,\n onProgress,\n });\n\n // If schema verification failed, return as failure\n if (!schemaVerifyResult.ok) {\n return notOk(schemaVerifyResult);\n }\n\n // Step 2: Sign (already connected from schemaVerify)\n const signResult = await client.sign({\n contract: contractJson,\n contractPath,\n configPath,\n onProgress,\n });\n\n return ok(signResult);\n } catch (error) {\n // Driver already throws CliStructuredError for connection failures\n if (error instanceof CliStructuredError) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n // Wrap unexpected errors\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during db sign: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbSignCommand(): Command {\n const command = new Command('sign');\n setCommandDescriptions(\n command,\n 'Sign the database with your contract so you can safely run queries',\n 'Verifies that your database schema satisfies the emitted contract, and if so, writes or\\n' +\n 'updates the database signature. This command is idempotent and safe to run\\n' +\n 'in CI/deployment pipelines. The signature records that this database instance is aligned\\n' +\n 'with a specific contract version.',\n );\n setCommandExamples(command, [\n 'prisma-next db sign --db $DATABASE_URL',\n 'prisma-next db sign production --db $DATABASE_URL',\n 'prisma-next db sign --contract production --db $DATABASE_URL',\n ]);\n addGlobalOptions(command)\n .argument('[contract]', 'Contract reference (hash, prefix, ref name, or migration dir name)')\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option(\n '--contract <contract>',\n 'Contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .action(async (positionalContract: string | undefined, options: DbSignOptions) => {\n const flags = parseGlobalFlags(options);\n\n if (positionalContract && options.contract) {\n process.stderr.write(\n 'Cannot specify both a positional contract argument and --contract flag.\\n',\n );\n process.exit(2);\n return;\n }\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeDbSignCommand(positionalContract, options, flags, ui);\n\n if (result.ok) {\n // Success - format sign output\n if (flags.json) {\n ui.output(formatSignJson(result.value));\n } else {\n const output = formatSignOutput(result.value, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(0);\n }\n\n // Failure - determine type and handle appropriately\n const failure = result.failure;\n\n if (failure instanceof CliStructuredError) {\n // Infrastructure error - use standard handler\n const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n // Schema verification failed - format and print schema verification output\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(failure));\n } else {\n const output = formatSchemaVerifyOutput(failure, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(1);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-update.d.mts","names":[],"sources":["../../src/commands/db-update.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"db-update.d.mts","names":[],"sources":["../../src/commands/db-update.ts"],"mappings":";;;iBA4NgB,qBAAA,CAAA,GAAyB,OAAA"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { _ as errorUnexpected, a as errorContractValidationFailed, f as errorMigrationPlanningFailed, n as ERROR_CODE_DESTRUCTIVE_CHANGES, p as errorRunnerFailed, s as errorDestructiveChanges, t as CliStructuredError } from "../cli-errors-
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as
|
|
5
|
-
import { a as ContractValidationError } from "../client-
|
|
6
|
-
import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-
|
|
7
|
-
import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-
|
|
1
|
+
import { _ as errorUnexpected, a as errorContractValidationFailed, f as errorMigrationPlanningFailed, n as ERROR_CODE_DESTRUCTIVE_CHANGES, p as errorRunnerFailed, s as errorDestructiveChanges, t as CliStructuredError, v as mapMigrationToolsError, y as mapRefResolutionError } from "../cli-errors-CF60g2cG.mjs";
|
|
2
|
+
import { _ as parseGlobalFlags, a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, l as resolveMigrationPaths, u as sanitizeErrorMessage } from "../command-helpers-D3vL5yi8.mjs";
|
|
3
|
+
import { t as handleResult } from "../result-handler-Bm_6dDYg.mjs";
|
|
4
|
+
import { t as TerminalUI } from "../terminal-ui-XtOQsqe9.mjs";
|
|
5
|
+
import { a as ContractValidationError } from "../client-Brv4qlfB.mjs";
|
|
6
|
+
import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-DyUf5lTt.mjs";
|
|
7
|
+
import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-CmXXC1UZ.mjs";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
10
10
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
11
|
+
import { join } from "pathe";
|
|
12
|
+
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
14
|
+
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
15
|
+
import { readRefs } from "@prisma-next/migration-tools/refs";
|
|
11
16
|
//#region src/commands/db-update.ts
|
|
12
17
|
/**
|
|
13
18
|
* Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.
|
|
@@ -37,8 +42,30 @@ async function executeDbUpdateCommand(options, flags, ui, startTime) {
|
|
|
37
42
|
url: "https://pris.ly/db-update"
|
|
38
43
|
});
|
|
39
44
|
if (!ctxResult.ok) return ctxResult;
|
|
40
|
-
const { client, config,
|
|
41
|
-
|
|
45
|
+
const { client, config, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;
|
|
46
|
+
let { contractJson } = ctxResult.value;
|
|
47
|
+
const { migrationsDir, appMigrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
|
|
48
|
+
if (options.to) try {
|
|
49
|
+
const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);
|
|
50
|
+
const refs = await readRefs(refsDir);
|
|
51
|
+
const refResult = parseContractRef(options.to, {
|
|
52
|
+
graph,
|
|
53
|
+
refs
|
|
54
|
+
});
|
|
55
|
+
if (!refResult.ok) return notOk(mapRefResolutionError(refResult.failure));
|
|
56
|
+
const targetHash = refResult.value.hash;
|
|
57
|
+
const matchingBundle = bundles.find((p) => p.metadata.to === targetHash);
|
|
58
|
+
if (!matchingBundle) return notOk(errorUnexpected(`No migration bundle found for --to "${options.to}" (resolved hash: ${targetHash})`, {
|
|
59
|
+
why: `The ref resolved successfully but no on-disk migration package has an end-contract hash matching ${targetHash}.`,
|
|
60
|
+
fix: "Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations."
|
|
61
|
+
}));
|
|
62
|
+
const raw = await readFile(join(matchingBundle.dirPath, "end-contract.json"), "utf-8");
|
|
63
|
+
contractJson = JSON.parse(raw);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
66
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
42
69
|
try {
|
|
43
70
|
await client.connect(dbConnection);
|
|
44
71
|
const result = await client.dbUpdate({
|
|
@@ -91,6 +118,7 @@ function createDbUpdateCommand() {
|
|
|
91
118
|
setCommandDescriptions(command, "Update your database schema to match your contract", "Compares your database schema to the emitted contract and applies the necessary\nchanges. Works on any database, whether or not it has been initialized with `db init`.\nDestructive operations prompt for confirmation in interactive mode. Use -y to\nauto-accept or --dry-run to preview first.");
|
|
92
119
|
setCommandExamples(command, ["prisma-next db update --db $DATABASE_URL", "prisma-next db update --db $DATABASE_URL --dry-run"]);
|
|
93
120
|
addMigrationCommandOptions(command);
|
|
121
|
+
command.option("--to <contract>", "Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)");
|
|
94
122
|
command.action(async (options) => {
|
|
95
123
|
const flags = parseGlobalFlags(options);
|
|
96
124
|
const startTime = Date.now();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-update.mjs","names":[],"sources":["../../src/commands/db-update.ts"],"sourcesContent":["import { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { ContractValidationError } from '../control-api/errors';\nimport type { DbUpdateFailure } from '../control-api/types';\nimport {\n CliStructuredError,\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorContractValidationFailed,\n errorDestructiveChanges,\n errorMigrationPlanningFailed,\n errorRunnerFailed,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport type { MigrationCommandOptions } from '../utils/command-helpers';\nimport {\n resolveMigrationPaths,\n sanitizeErrorMessage,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n formatMigrationApplyOutput,\n formatMigrationJson,\n formatMigrationPlanOutput,\n type MigrationCommandResult,\n} from '../utils/formatters/migrations';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n addMigrationCommandOptions,\n prepareMigrationContext,\n} from '../utils/migration-command-scaffold';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ntype DbUpdateOptions = MigrationCommandOptions;\n\n/**\n * Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.\n */\nfunction mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {\n if (failure.code === 'PLANNING_FAILED') {\n return errorMigrationPlanningFailed({ conflicts: failure.conflicts ?? [] });\n }\n\n if (failure.code === 'RUNNER_FAILED') {\n return errorRunnerFailed(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n if (failure.code === 'DESTRUCTIVE_CHANGES') {\n return errorDestructiveChanges(failure.summary, {\n ...ifDefined('why', failure.why),\n fix: 'Re-run with `-y` to apply destructive changes, or use `--dry-run` to preview first',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n const exhaustive: never = failure.code;\n throw new Error(`Unhandled DbUpdateFailure code: ${exhaustive}`);\n}\n\n/**\n * Executes the db update command and returns a structured Result.\n */\nasync function executeDbUpdateCommand(\n options: DbUpdateOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationCommandResult, CliStructuredError>> {\n // Prepare shared migration context (config, contract, connection, client)\n const ctxResult = await prepareMigrationContext(options, flags, ui, {\n commandName: 'db update',\n description: 'Update your database schema to match your contract',\n url: 'https://pris.ly/db-update',\n });\n if (!ctxResult.ok) {\n return ctxResult;\n }\n const { client, config, contractJson, dbConnection, onProgress, contractPathAbsolute } =\n ctxResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, config);\n\n try {\n await client.connect(dbConnection);\n\n const result = await client.dbUpdate({\n contract: contractJson,\n mode: options.dryRun ? 'plan' : 'apply',\n migrationsDir,\n ...(flags.yes ? { acceptDataLoss: true } : {}),\n onProgress,\n });\n\n // Handle failures by mapping to CLI structured error\n if (!result.ok) {\n return notOk(mapDbUpdateFailure(result.failure));\n }\n\n // Convert success result to CLI output format\n const dbUpdateResult: MigrationCommandResult = {\n ok: true,\n mode: result.value.mode,\n plan: {\n targetId: ctxResult.value.config.target.targetId,\n destination: {\n storageHash: result.value.destination.storageHash,\n ...ifDefined('profileHash', result.value.destination.profileHash),\n },\n operations: result.value.plan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n ...ifDefined('preview', result.value.plan.preview),\n },\n ...ifDefined(\n 'execution',\n result.value.execution\n ? {\n operationsPlanned: result.value.execution.operationsPlanned,\n operationsExecuted: result.value.execution.operationsExecuted,\n }\n : undefined,\n ),\n ...ifDefined(\n 'marker',\n result.value.marker\n ? {\n storageHash: result.value.marker.storageHash,\n ...ifDefined('profileHash', result.value.marker.profileHash),\n }\n : undefined,\n ),\n ...ifDefined('perSpace', result.value.perSpace),\n summary: result.value.summary,\n timings: { total: Date.now() - startTime },\n };\n\n return ok(dbUpdateResult);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during db update: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbUpdateCommand(): Command {\n const command = new Command('update');\n setCommandDescriptions(\n command,\n 'Update your database schema to match your contract',\n 'Compares your database schema to the emitted contract and applies the necessary\\n' +\n 'changes. Works on any database, whether or not it has been initialized with `db init`.\\n' +\n 'Destructive operations prompt for confirmation in interactive mode. Use -y to\\n' +\n 'auto-accept or --dry-run to preview first.',\n );\n setCommandExamples(command, [\n 'prisma-next db update --db $DATABASE_URL',\n 'prisma-next db update --db $DATABASE_URL --dry-run',\n ]);\n addMigrationCommandOptions(command);\n command.action(async (options: DbUpdateOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n let result = await executeDbUpdateCommand(options, flags, ui, startTime);\n\n // Interactive confirmation for destructive operations:\n // When the control API rejects destructive changes, prompt the user instead of failing.\n // In non-interactive mode (CI, piped, --no-interactive, --json), the error is returned as-is.\n if (\n !result.ok &&\n result.failure.code === ERROR_CODE_DESTRUCTIVE_CHANGES &&\n flags.interactive &&\n !flags.json &&\n !flags.yes\n ) {\n const meta = result.failure.meta as\n | { destructiveOperations?: readonly { id: string; label: string }[] }\n | undefined;\n const destructiveOps = meta?.destructiveOperations ?? [];\n\n if (destructiveOps.length > 0) {\n ui.warn(\n `${destructiveOps.length} destructive operation(s) that may cause data loss:\\n${destructiveOps.map((op) => ` ${ui.yellow('▸')} ${op.label}`).join('\\n')}`,\n );\n }\n\n const confirmed = await ui.confirm('Apply destructive changes? This cannot be undone.');\n\n if (confirmed) {\n result = await executeDbUpdateCommand(options, { ...flags, yes: true }, ui, Date.now());\n }\n }\n\n const exitCode = handleResult(result, flags, ui, (dbUpdateResult) => {\n if (flags.json) {\n ui.output(formatMigrationJson(dbUpdateResult));\n } else {\n const output =\n dbUpdateResult.mode === 'plan'\n ? formatMigrationPlanOutput(dbUpdateResult, flags)\n : formatMigrationApplyOutput(dbUpdateResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;AAwCA,SAAS,mBAAmB,SAA8C;CACxE,IAAI,QAAQ,SAAS,mBACnB,OAAO,6BAA6B,EAAE,WAAW,QAAQ,aAAa,EAAE,EAAE,CAAC;CAG7E,IAAI,QAAQ,SAAS,iBACnB,OAAO,kBAAkB,QAAQ,SAAS;EACxC,KAAK,QAAQ,OAAO;EACpB,KAAK;EACL,GAAG,UAAU,QAAQ,QAAQ,KAAK;EACnC,CAAC;CAGJ,IAAI,QAAQ,SAAS,uBACnB,OAAO,wBAAwB,QAAQ,SAAS;EAC9C,GAAG,UAAU,OAAO,QAAQ,IAAI;EAChC,KAAK;EACL,GAAG,UAAU,QAAQ,QAAQ,KAAK;EACnC,CAAC;CAGJ,MAAM,aAAoB,QAAQ;CAClC,MAAM,IAAI,MAAM,mCAAmC,aAAa;;;;;AAMlE,eAAe,uBACb,SACA,OACA,IACA,WAC6D;CAE7D,MAAM,YAAY,MAAM,wBAAwB,SAAS,OAAO,IAAI;EAClE,aAAa;EACb,aAAa;EACb,KAAK;EACN,CAAC;CACF,IAAI,CAAC,UAAU,IACb,OAAO;CAET,MAAM,EAAE,QAAQ,QAAQ,cAAc,cAAc,YAAY,yBAC9D,UAAU;CACZ,MAAM,EAAE,kBAAkB,sBAAsB,QAAQ,QAAQ,OAAO;CAEvE,IAAI;EACF,MAAM,OAAO,QAAQ,aAAa;EAElC,MAAM,SAAS,MAAM,OAAO,SAAS;GACnC,UAAU;GACV,MAAM,QAAQ,SAAS,SAAS;GAChC;GACA,GAAI,MAAM,MAAM,EAAE,gBAAgB,MAAM,GAAG,EAAE;GAC7C;GACD,CAAC;EAGF,IAAI,CAAC,OAAO,IACV,OAAO,MAAM,mBAAmB,OAAO,QAAQ,CAAC;EA2ClD,OAAO,GAAG;GAtCR,IAAI;GACJ,MAAM,OAAO,MAAM;GACnB,MAAM;IACJ,UAAU,UAAU,MAAM,OAAO,OAAO;IACxC,aAAa;KACX,aAAa,OAAO,MAAM,YAAY;KACtC,GAAG,UAAU,eAAe,OAAO,MAAM,YAAY,YAAY;KAClE;IACD,YAAY,OAAO,MAAM,KAAK,WAAW,KAAK,QAAQ;KACpD,IAAI,GAAG;KACP,OAAO,GAAG;KACV,gBAAgB,GAAG;KACpB,EAAE;IACH,GAAG,UAAU,WAAW,OAAO,MAAM,KAAK,QAAQ;IACnD;GACD,GAAG,UACD,aACA,OAAO,MAAM,YACT;IACE,mBAAmB,OAAO,MAAM,UAAU;IAC1C,oBAAoB,OAAO,MAAM,UAAU;IAC5C,GACD,KAAA,EACL;GACD,GAAG,UACD,UACA,OAAO,MAAM,SACT;IACE,aAAa,OAAO,MAAM,OAAO;IACjC,GAAG,UAAU,eAAe,OAAO,MAAM,OAAO,YAAY;IAC7D,GACD,KAAA,EACL;GACD,GAAG,UAAU,YAAY,OAAO,MAAM,SAAS;GAC/C,SAAS,OAAO,MAAM;GACtB,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAGpB,CAAC;UAClB,OAAO;EACd,IAAI,mBAAmB,GAAG,MAAM,EAC9B,OAAO,MAAM,MAAM;EAGrB,IAAI,iBAAiB,yBACnB,OAAO,MACL,8BAA8B,+BAA+B,MAAM,WAAW,EAC5E,OAAO,EAAE,MAAM,sBAAsB,EACtC,CAAC,CACH;EAIH,MAAM,cAAc,qBADD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAGvE,OAAO,iBAAiB,WAAW,eAAe,KAAA,EACnD;EACD,OAAO,MACL,gBAAgB,aAAa,EAC3B,KAAK,sCAAsC,eAC5C,CAAC,CACH;WACO;EACR,MAAM,OAAO,OAAO;;;AAIxB,SAAgB,wBAAiC;CAC/C,MAAM,UAAU,IAAI,QAAQ,SAAS;CACrC,uBACE,SACA,sDACA,qSAID;CACD,mBAAmB,SAAS,CAC1B,4CACA,qDACD,CAAC;CACF,2BAA2B,QAAQ;CACnC,QAAQ,OAAO,OAAO,YAA6B;EACjD,MAAM,QAAQ,iBAAiB,QAAQ;EACvC,MAAM,YAAY,KAAK,KAAK;EAE5B,MAAM,KAAK,IAAI,WAAW;GAAE,OAAO,MAAM;GAAO,aAAa,MAAM;GAAa,CAAC;EAEjF,IAAI,SAAS,MAAM,uBAAuB,SAAS,OAAO,IAAI,UAAU;EAKxE,IACE,CAAC,OAAO,MACR,OAAO,QAAQ,SAAS,kCACxB,MAAM,eACN,CAAC,MAAM,QACP,CAAC,MAAM,KACP;GAIA,MAAM,iBAHO,OAAO,QAAQ,MAGC,yBAAyB,EAAE;GAExD,IAAI,eAAe,SAAS,GAC1B,GAAG,KACD,GAAG,eAAe,OAAO,uDAAuD,eAAe,KAAK,OAAO,KAAK,GAAG,OAAO,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC,KAAK,KAAK,GACzJ;GAKH,IAAI,MAFoB,GAAG,QAAQ,oDAAoD,EAGrF,SAAS,MAAM,uBAAuB,SAAS;IAAE,GAAG;IAAO,KAAK;IAAM,EAAE,IAAI,KAAK,KAAK,CAAC;;EAI3F,MAAM,WAAW,aAAa,QAAQ,OAAO,KAAK,mBAAmB;GACnE,IAAI,MAAM,MACR,GAAG,OAAO,oBAAoB,eAAe,CAAC;QACzC;IACL,MAAM,SACJ,eAAe,SAAS,SACpB,0BAA0B,gBAAgB,MAAM,GAChD,2BAA2B,gBAAgB,MAAM;IACvD,IAAI,QACF,GAAG,IAAI,OAAO;;IAGlB;EACF,QAAQ,KAAK,SAAS;GACtB;CAEF,OAAO"}
|
|
1
|
+
{"version":3,"file":"db-update.mjs","names":[],"sources":["../../src/commands/db-update.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join } from 'pathe';\nimport { ContractValidationError } from '../control-api/errors';\nimport type { DbUpdateFailure } from '../control-api/types';\nimport {\n CliStructuredError,\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorContractValidationFailed,\n errorDestructiveChanges,\n errorMigrationPlanningFailed,\n errorRunnerFailed,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport type { MigrationCommandOptions } from '../utils/command-helpers';\nimport {\n loadMigrationPackages,\n resolveMigrationPaths,\n sanitizeErrorMessage,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n formatMigrationApplyOutput,\n formatMigrationJson,\n formatMigrationPlanOutput,\n type MigrationCommandResult,\n} from '../utils/formatters/migrations';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n addMigrationCommandOptions,\n prepareMigrationContext,\n} from '../utils/migration-command-scaffold';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface DbUpdateOptions extends MigrationCommandOptions {\n readonly to?: string;\n}\n\n/**\n * Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.\n */\nfunction mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {\n if (failure.code === 'PLANNING_FAILED') {\n return errorMigrationPlanningFailed({ conflicts: failure.conflicts ?? [] });\n }\n\n if (failure.code === 'RUNNER_FAILED') {\n return errorRunnerFailed(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n if (failure.code === 'DESTRUCTIVE_CHANGES') {\n return errorDestructiveChanges(failure.summary, {\n ...ifDefined('why', failure.why),\n fix: 'Re-run with `-y` to apply destructive changes, or use `--dry-run` to preview first',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n const exhaustive: never = failure.code;\n throw new Error(`Unhandled DbUpdateFailure code: ${exhaustive}`);\n}\n\n/**\n * Executes the db update command and returns a structured Result.\n */\nasync function executeDbUpdateCommand(\n options: DbUpdateOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationCommandResult, CliStructuredError>> {\n // Prepare shared migration context (config, contract, connection, client)\n const ctxResult = await prepareMigrationContext(options, flags, ui, {\n commandName: 'db update',\n description: 'Update your database schema to match your contract',\n url: 'https://pris.ly/db-update',\n });\n if (!ctxResult.ok) {\n return ctxResult;\n }\n const { client, config, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;\n let { contractJson } = ctxResult.value;\n const { migrationsDir, appMigrationsDir, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (options.to) {\n try {\n const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);\n const refs = await readRefs(refsDir);\n const refResult = parseContractRef(options.to, { graph, refs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n const targetHash = refResult.value.hash;\n const matchingBundle = bundles.find((p) => p.metadata.to === targetHash);\n if (!matchingBundle) {\n return notOk(\n errorUnexpected(\n `No migration bundle found for --to \"${options.to}\" (resolved hash: ${targetHash})`,\n {\n why: `The ref resolved successfully but no on-disk migration package has an end-contract hash matching ${targetHash}.`,\n fix: 'Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations.',\n },\n ),\n );\n }\n const endContractPath = join(matchingBundle.dirPath, 'end-contract.json');\n const raw = await readFile(endContractPath, 'utf-8');\n contractJson = JSON.parse(raw) as Record<string, unknown>;\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n throw error;\n }\n }\n\n try {\n await client.connect(dbConnection);\n\n const result = await client.dbUpdate({\n contract: contractJson,\n mode: options.dryRun ? 'plan' : 'apply',\n migrationsDir,\n ...(flags.yes ? { acceptDataLoss: true } : {}),\n onProgress,\n });\n\n // Handle failures by mapping to CLI structured error\n if (!result.ok) {\n return notOk(mapDbUpdateFailure(result.failure));\n }\n\n // Convert success result to CLI output format\n const dbUpdateResult: MigrationCommandResult = {\n ok: true,\n mode: result.value.mode,\n plan: {\n targetId: ctxResult.value.config.target.targetId,\n destination: {\n storageHash: result.value.destination.storageHash,\n ...ifDefined('profileHash', result.value.destination.profileHash),\n },\n operations: result.value.plan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n ...ifDefined('preview', result.value.plan.preview),\n },\n ...ifDefined(\n 'execution',\n result.value.execution\n ? {\n operationsPlanned: result.value.execution.operationsPlanned,\n operationsExecuted: result.value.execution.operationsExecuted,\n }\n : undefined,\n ),\n ...ifDefined(\n 'marker',\n result.value.marker\n ? {\n storageHash: result.value.marker.storageHash,\n ...ifDefined('profileHash', result.value.marker.profileHash),\n }\n : undefined,\n ),\n ...ifDefined('perSpace', result.value.perSpace),\n summary: result.value.summary,\n timings: { total: Date.now() - startTime },\n };\n\n return ok(dbUpdateResult);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during db update: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbUpdateCommand(): Command {\n const command = new Command('update');\n setCommandDescriptions(\n command,\n 'Update your database schema to match your contract',\n 'Compares your database schema to the emitted contract and applies the necessary\\n' +\n 'changes. Works on any database, whether or not it has been initialized with `db init`.\\n' +\n 'Destructive operations prompt for confirmation in interactive mode. Use -y to\\n' +\n 'auto-accept or --dry-run to preview first.',\n );\n setCommandExamples(command, [\n 'prisma-next db update --db $DATABASE_URL',\n 'prisma-next db update --db $DATABASE_URL --dry-run',\n ]);\n addMigrationCommandOptions(command);\n command.option(\n '--to <contract>',\n 'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n );\n command.action(async (options: DbUpdateOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n let result = await executeDbUpdateCommand(options, flags, ui, startTime);\n\n // Interactive confirmation for destructive operations:\n // When the control API rejects destructive changes, prompt the user instead of failing.\n // In non-interactive mode (CI, piped, --no-interactive, --json), the error is returned as-is.\n if (\n !result.ok &&\n result.failure.code === ERROR_CODE_DESTRUCTIVE_CHANGES &&\n flags.interactive &&\n !flags.json &&\n !flags.yes\n ) {\n const meta = result.failure.meta as\n | { destructiveOperations?: readonly { id: string; label: string }[] }\n | undefined;\n const destructiveOps = meta?.destructiveOperations ?? [];\n\n if (destructiveOps.length > 0) {\n ui.warn(\n `${destructiveOps.length} destructive operation(s) that may cause data loss:\\n${destructiveOps.map((op) => ` ${ui.yellow('▸')} ${op.label}`).join('\\n')}`,\n );\n }\n\n const confirmed = await ui.confirm('Apply destructive changes? This cannot be undone.');\n\n if (confirmed) {\n result = await executeDbUpdateCommand(options, { ...flags, yes: true }, ui, Date.now());\n }\n }\n\n const exitCode = handleResult(result, flags, ui, (dbUpdateResult) => {\n if (flags.json) {\n ui.output(formatMigrationJson(dbUpdateResult));\n } else {\n const output =\n dbUpdateResult.mode === 'plan'\n ? formatMigrationPlanOutput(dbUpdateResult, flags)\n : formatMigrationApplyOutput(dbUpdateResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-verify.d.mts","names":[],"sources":["../../src/commands/db-verify.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"db-verify.d.mts","names":[],"sources":["../../src/commands/db-verify.ts"],"mappings":";;;iBAmfgB,qBAAA,CAAA,GAAyB,OAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createDbVerifyCommand } from "../db-verify-
|
|
1
|
+
import { t as createDbVerifyCommand } from "../db-verify-D7cyH_zz.mjs";
|
|
2
2
|
export { createDbVerifyCommand };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { T as MigrationApplyPathDecision, t as AggregatePerSpaceExecutionEntry } from "../types-0aS865QN.mjs";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/migrate.d.ts
|
|
5
|
+
interface MigrateResult {
|
|
6
|
+
readonly ok: boolean;
|
|
7
|
+
readonly migrationsApplied: number;
|
|
8
|
+
readonly migrationsTotal: number;
|
|
9
|
+
readonly markerHash: string;
|
|
10
|
+
readonly applied: readonly {
|
|
11
|
+
readonly spaceId: string;
|
|
12
|
+
readonly dirName: string;
|
|
13
|
+
readonly migrationHash: string;
|
|
14
|
+
readonly from: string;
|
|
15
|
+
readonly to: string;
|
|
16
|
+
readonly operationsExecuted: number;
|
|
17
|
+
}[];
|
|
18
|
+
readonly summary: string;
|
|
19
|
+
readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];
|
|
20
|
+
readonly pathDecision?: MigrationApplyPathDecision;
|
|
21
|
+
readonly timings: {
|
|
22
|
+
readonly total: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
declare function createMigrateCommand(): Command;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { MigrateResult, createMigrateCommand };
|
|
28
|
+
//# sourceMappingURL=migrate.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.mts","names":[],"sources":["../../src/commands/migrate.ts"],"mappings":";;;;UAuDiB,aAAA;EAAA,SACN,EAAA;EAAA,SACA,iBAAA;EAAA,SACA,eAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA;IAAA,SACE,OAAA;IAAA,SACA,OAAA;IAAA,SACA,aAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,kBAAA;EAAA;EAAA,SAEF,OAAA;EAAA,SACA,QAAA,WAAmB,+BAAA;EAAA,SACnB,YAAA,GAAe,0BAAA;EAAA,SACf,OAAA;IAAA,SACE,KAAA;EAAA;AAAA;AAAA,iBAkOG,oBAAA,CAAA,GAAwB,OAAA"}
|
|
@@ -1,53 +1,75 @@
|
|
|
1
1
|
import { t as loadConfig } from "../config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, v as mapMigrationToolsError } from "../cli-errors-
|
|
3
|
-
import { a as loadMigrationPackages, c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples,
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as createControlClient } from "../client-
|
|
7
|
-
import { t as formatMigrationApplyCommandOutput } from "../migrations-
|
|
2
|
+
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, v as mapMigrationToolsError, y as mapRefResolutionError } from "../cli-errors-CF60g2cG.mjs";
|
|
3
|
+
import { _ as parseGlobalFlags, a as loadMigrationPackages, b as formatStyledHeader, c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, l as resolveMigrationPaths, m as targetSupportsMigrations, n as collectDeclaredInvariants, o as maskConnectionUrl, t as addGlobalOptions } from "../command-helpers-D3vL5yi8.mjs";
|
|
4
|
+
import { t as handleResult } from "../result-handler-Bm_6dDYg.mjs";
|
|
5
|
+
import { t as TerminalUI } from "../terminal-ui-XtOQsqe9.mjs";
|
|
6
|
+
import { t as createControlClient } from "../client-Brv4qlfB.mjs";
|
|
7
|
+
import { t as formatMigrationApplyCommandOutput } from "../migrations-DyUf5lTt.mjs";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
10
10
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
11
11
|
import { readFile } from "node:fs/promises";
|
|
12
|
+
import { createControlStack } from "@prisma-next/framework-components/control";
|
|
12
13
|
import { MigrationToolsError, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
|
|
13
|
-
import {
|
|
14
|
-
|
|
14
|
+
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
15
|
+
import { readRefs } from "@prisma-next/migration-tools/refs";
|
|
16
|
+
//#region src/commands/migrate.ts
|
|
15
17
|
function mapApplyFailure(failure) {
|
|
16
18
|
return errorRuntime(failure.summary, {
|
|
17
19
|
why: failure.why ?? "Migration runner failed",
|
|
18
|
-
fix: "Fix the issue and re-run `prisma-next
|
|
20
|
+
fix: "Fix the issue and re-run `prisma-next migrate --to <contract>` — previously applied migrations are preserved.",
|
|
19
21
|
meta: failure.meta ?? {}
|
|
20
22
|
});
|
|
21
23
|
}
|
|
22
|
-
async function
|
|
24
|
+
async function executeMigrateCommand(options, flags, ui, startTime) {
|
|
23
25
|
const config = await loadConfig(options.config);
|
|
24
26
|
const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
|
|
25
27
|
const dbConnection = options.db ?? config.db?.connection;
|
|
26
28
|
if (!dbConnection) return notOk(errorDatabaseConnectionRequired({
|
|
27
|
-
why: `Database connection is required for
|
|
28
|
-
commandName: "
|
|
29
|
+
why: `Database connection is required for migrate (set db.connection in ${configPath}, or pass --db <url>)`,
|
|
30
|
+
commandName: "migrate"
|
|
29
31
|
}));
|
|
30
|
-
if (!config.driver) return notOk(errorDriverRequired({ why: "Config.driver is required for
|
|
32
|
+
if (!config.driver) return notOk(errorDriverRequired({ why: "Config.driver is required for migrate" }));
|
|
31
33
|
if (!targetSupportsMigrations(config.target)) return notOk(errorTargetMigrationNotSupported({ why: `Target "${config.target.id}" does not support migrations` }));
|
|
32
34
|
let refEntry;
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
|
|
35
|
+
const toArg = options.to;
|
|
36
|
+
if (toArg) try {
|
|
37
|
+
const refs = await readRefs(refsDir);
|
|
38
|
+
const { graph } = await loadMigrationPackages(appMigrationsDir);
|
|
39
|
+
const refResult = parseContractRef(toArg, {
|
|
40
|
+
graph,
|
|
41
|
+
refs
|
|
42
|
+
});
|
|
43
|
+
if (!refResult.ok) return notOk(mapRefResolutionError(refResult.failure));
|
|
44
|
+
if (refResult.value.provenance.kind === "ref") {
|
|
45
|
+
const resolved = refs[refResult.value.provenance.refName];
|
|
46
|
+
if (resolved) refEntry = resolved;
|
|
47
|
+
} else refEntry = {
|
|
48
|
+
hash: refResult.value.hash,
|
|
49
|
+
invariants: []
|
|
50
|
+
};
|
|
36
51
|
} catch (error) {
|
|
37
52
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
38
53
|
throw error;
|
|
39
54
|
}
|
|
55
|
+
const stack = createControlStack(config);
|
|
56
|
+
const familyInstance = config.family.create(stack);
|
|
40
57
|
const contractPathAbsolute = resolveContractPath(config);
|
|
41
58
|
let contractRaw;
|
|
59
|
+
let contractContent;
|
|
42
60
|
try {
|
|
43
|
-
|
|
44
|
-
contractRaw = JSON.parse(contractContent);
|
|
61
|
+
contractContent = await readFile(contractPathAbsolute, "utf-8");
|
|
45
62
|
} catch (error) {
|
|
46
63
|
if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
|
|
47
64
|
why: `Contract file not found at ${contractPathAbsolute}`,
|
|
48
|
-
fix: "Run `prisma-next contract emit` to generate a valid contract.json, then retry
|
|
65
|
+
fix: "Run `prisma-next contract emit` to generate a valid contract.json, then retry."
|
|
49
66
|
}));
|
|
50
|
-
return notOk(errorContractValidationFailed(`
|
|
67
|
+
return notOk(errorContractValidationFailed(`Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
contractRaw = familyInstance.deserializeContract(JSON.parse(contractContent));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return notOk(errorContractValidationFailed(`Contract at ${contractPathAbsolute} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
|
|
51
73
|
}
|
|
52
74
|
if (!flags.json && !flags.quiet) {
|
|
53
75
|
const details = [{
|
|
@@ -61,14 +83,14 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
|
|
|
61
83
|
label: "database",
|
|
62
84
|
value: maskConnectionUrl(dbConnection)
|
|
63
85
|
});
|
|
64
|
-
if (
|
|
65
|
-
label: "
|
|
66
|
-
value:
|
|
86
|
+
if (toArg) details.push({
|
|
87
|
+
label: "to",
|
|
88
|
+
value: toArg
|
|
67
89
|
});
|
|
68
90
|
const header = formatStyledHeader({
|
|
69
|
-
command: "
|
|
70
|
-
description: "Apply planned migrations to the database",
|
|
71
|
-
url: "https://pris.ly/
|
|
91
|
+
command: "migrate",
|
|
92
|
+
description: "Apply planned migrations to advance the database",
|
|
93
|
+
url: "https://pris.ly/migrate",
|
|
72
94
|
details,
|
|
73
95
|
flags
|
|
74
96
|
});
|
|
@@ -97,7 +119,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
|
|
|
97
119
|
for (const id of appMarker?.invariants ?? []) known.add(id);
|
|
98
120
|
const unknown = refEntry.invariants.filter((id) => !known.has(id));
|
|
99
121
|
if (unknown.length > 0) return notOk(mapMigrationToolsError(errorUnknownInvariant({
|
|
100
|
-
...ifDefined("refName",
|
|
122
|
+
...ifDefined("refName", toArg),
|
|
101
123
|
unknown,
|
|
102
124
|
declared: [...declared].sort()
|
|
103
125
|
})));
|
|
@@ -109,7 +131,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
|
|
|
109
131
|
appMigrationPackages: appPackages.bundles,
|
|
110
132
|
...ifDefined("refHash", refEntry?.hash),
|
|
111
133
|
...refEntry?.invariants ? { refInvariants: refEntry.invariants } : {},
|
|
112
|
-
...refEntry !== void 0 ? ifDefined("refName",
|
|
134
|
+
...refEntry !== void 0 ? ifDefined("refName", toArg) : {}
|
|
113
135
|
});
|
|
114
136
|
if (!applyResult.ok) return notOk(mapApplyFailure(applyResult.failure));
|
|
115
137
|
const { value } = applyResult;
|
|
@@ -127,31 +149,35 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
|
|
|
127
149
|
} catch (error) {
|
|
128
150
|
if (CliStructuredError.is(error)) return notOk(error);
|
|
129
151
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
130
|
-
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Unexpected error during
|
|
152
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Unexpected error during migrate: ${error instanceof Error ? error.message : String(error)}` }));
|
|
131
153
|
} finally {
|
|
132
154
|
await client.close();
|
|
133
155
|
}
|
|
134
156
|
}
|
|
135
|
-
function
|
|
136
|
-
const command = new Command("
|
|
137
|
-
setCommandDescriptions(command, "Apply planned migrations to the database", "Walks every contract space (app + extensions) and applies pending\non-disk migrations in canonical order (extensions alphabetically,\nthen app). Graph-walks the on-disk migration graph for every space
|
|
138
|
-
setCommandExamples(command, [
|
|
139
|
-
|
|
157
|
+
function createMigrateCommand() {
|
|
158
|
+
const command = new Command("migrate");
|
|
159
|
+
setCommandDescriptions(command, "Apply planned migrations to advance the database", "Walks every contract space (app + extensions) and applies pending\non-disk migrations in canonical order (extensions alphabetically,\nthen app). Graph-walks the on-disk migration graph for every space.\nUse --to to target a specific contract (hash, ref name, migration dir).");
|
|
160
|
+
setCommandExamples(command, [
|
|
161
|
+
"prisma-next migrate --db $DATABASE_URL",
|
|
162
|
+
"prisma-next migrate --to production --db $DATABASE_URL",
|
|
163
|
+
"prisma-next migrate --to sha256:abc123 --db $DATABASE_URL"
|
|
164
|
+
]);
|
|
165
|
+
addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--to <contract>", "Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)").action(async (options) => {
|
|
140
166
|
const flags = parseGlobalFlags(options);
|
|
141
167
|
const startTime = Date.now();
|
|
142
168
|
const ui = new TerminalUI({
|
|
143
169
|
color: flags.color,
|
|
144
170
|
interactive: flags.interactive
|
|
145
171
|
});
|
|
146
|
-
const exitCode = handleResult(await
|
|
147
|
-
if (flags.json) ui.output(JSON.stringify(
|
|
148
|
-
else if (!flags.quiet) ui.log(formatMigrationApplyCommandOutput(
|
|
172
|
+
const exitCode = handleResult(await executeMigrateCommand(options, flags, ui, startTime), flags, ui, (migrateResult) => {
|
|
173
|
+
if (flags.json) ui.output(JSON.stringify(migrateResult, null, 2));
|
|
174
|
+
else if (!flags.quiet) ui.log(formatMigrationApplyCommandOutput(migrateResult, flags));
|
|
149
175
|
});
|
|
150
176
|
process.exit(exitCode);
|
|
151
177
|
});
|
|
152
178
|
return command;
|
|
153
179
|
}
|
|
154
180
|
//#endregion
|
|
155
|
-
export {
|
|
181
|
+
export { createMigrateCommand };
|
|
156
182
|
|
|
157
|
-
//# sourceMappingURL=
|
|
183
|
+
//# sourceMappingURL=migrate.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.mjs","names":[],"sources":["../../src/commands/migrate.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport { errorUnknownInvariant, MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport type { RefEntry } from '@prisma-next/migration-tools/refs';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\n\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type {\n AggregatePerSpaceExecutionEntry,\n MigrationApplyFailure,\n MigrationApplyPathDecision,\n} from '../control-api/types';\nimport {\n CliStructuredError,\n type CliStructuredError as CliStructuredErrorType,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n collectDeclaredInvariants,\n loadMigrationPackages,\n maskConnectionUrl,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n targetSupportsMigrations,\n} from '../utils/command-helpers';\nimport { formatMigrationApplyCommandOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrateCommandOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly to?: string;\n}\n\nexport interface MigrateResult {\n readonly ok: boolean;\n readonly migrationsApplied: number;\n readonly migrationsTotal: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly spaceId: string;\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];\n readonly pathDecision?: MigrationApplyPathDecision;\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapApplyFailure(failure: MigrationApplyFailure): CliStructuredErrorType {\n return errorRuntime(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Fix the issue and re-run `prisma-next migrate --to <contract>` — previously applied migrations are preserved.',\n meta: failure.meta ?? {},\n });\n}\n\nasync function executeMigrateCommand(\n options: MigrateCommandOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrateResult, CliStructuredErrorType>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative, refsDir } =\n resolveMigrationPaths(options.config, config);\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for migrate (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'migrate',\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: 'Config.driver is required for migrate',\n }),\n );\n }\n\n if (!targetSupportsMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n let refEntry: RefEntry | undefined;\n const toArg = options.to;\n\n if (toArg) {\n try {\n const refs = await readRefs(refsDir);\n const { graph } = await loadMigrationPackages(appMigrationsDir);\n const refResult = parseContractRef(toArg, { graph, refs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n if (refResult.value.provenance.kind === 'ref') {\n const resolved = refs[refResult.value.provenance.refName];\n if (resolved) refEntry = resolved;\n } else {\n refEntry = { hash: refResult.value.hash, invariants: [] };\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n }\n\n // Construct the family instance up-front so the on-disk contract read\n // crosses the serializer seam (`familyInstance.deserializeContract`) at\n // the read site. The downstream `client.migrationApply({ contract })`\n // re-validates internally (no harm — validation is idempotent), but\n // closing the gap at the read site is what makes the cast-pattern\n // lint enforceable and matches the other CLI commands. See TML-2536.\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n\n const contractPathAbsolute = resolveContractPath(config);\n let contractRaw: Contract;\n let contractContent: string;\n try {\n contractContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: 'Run `prisma-next contract emit` to generate a valid contract.json, then retry.',\n }),\n );\n }\n return notOk(\n errorContractValidationFailed(\n `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n try {\n contractRaw = familyInstance.deserializeContract(JSON.parse(contractContent) as unknown);\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract at ${contractPathAbsolute} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (typeof dbConnection === 'string') {\n details.push({\n label: 'database',\n value: maskConnectionUrl(dbConnection),\n });\n }\n if (toArg) {\n details.push({ label: 'to', value: toArg });\n }\n const header = formatStyledHeader({\n command: 'migrate',\n description: 'Apply planned migrations to advance the database',\n url: 'https://pris.ly/migrate',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let appPackages: Awaited<ReturnType<typeof loadMigrationPackages>>;\n try {\n appPackages = await loadMigrationPackages(appMigrationsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n try {\n await client.connect(dbConnection);\n\n if (refEntry && refEntry.invariants.length > 0) {\n const allMarkers = await client.readAllMarkers();\n const appMarker = allMarkers.get('app') ?? null;\n const declared = collectDeclaredInvariants(appPackages.graph);\n const known = new Set<string>(declared);\n for (const id of appMarker?.invariants ?? []) known.add(id);\n const unknown = refEntry.invariants.filter((id) => !known.has(id));\n if (unknown.length > 0) {\n return notOk(\n mapMigrationToolsError(\n errorUnknownInvariant({\n ...ifDefined('refName', toArg),\n unknown,\n declared: [...declared].sort(),\n }),\n ),\n );\n }\n }\n\n if (!flags.quiet && !flags.json) {\n ui.step('Loading contract spaces…');\n }\n\n const applyResult = await client.migrationApply({\n contract: contractRaw,\n migrationsDir,\n appMigrationPackages: appPackages.bundles,\n ...ifDefined('refHash', refEntry?.hash),\n ...(refEntry?.invariants ? { refInvariants: refEntry.invariants } : {}),\n ...(refEntry !== undefined ? ifDefined('refName', toArg) : {}),\n });\n\n if (!applyResult.ok) {\n return notOk(mapApplyFailure(applyResult.failure));\n }\n\n const { value } = applyResult;\n\n return ok({\n ok: true,\n migrationsApplied: value.migrationsApplied,\n migrationsTotal: value.perSpace.length,\n markerHash: value.markerHash,\n applied: value.applied,\n summary: value.summary,\n perSpace: value.perSpace,\n ...ifDefined('pathDecision', value.pathDecision),\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migrate: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createMigrateCommand(): Command {\n const command = new Command('migrate');\n setCommandDescriptions(\n command,\n 'Apply planned migrations to advance the database',\n 'Walks every contract space (app + extensions) and applies pending\\n' +\n 'on-disk migrations in canonical order (extensions alphabetically,\\n' +\n 'then app). Graph-walks the on-disk migration graph for every space.\\n' +\n 'Use --to to target a specific contract (hash, ref name, migration dir).',\n );\n setCommandExamples(command, [\n 'prisma-next migrate --db $DATABASE_URL',\n 'prisma-next migrate --to production --db $DATABASE_URL',\n 'prisma-next migrate --to sha256:abc123 --db $DATABASE_URL',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option(\n '--to <contract>',\n 'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .action(async (options: MigrateCommandOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({\n color: flags.color,\n interactive: flags.interactive,\n });\n\n const result = await executeMigrateCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (migrateResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(migrateResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationApplyCommandOutput(migrateResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|