prisma-next 0.5.0-dev.9 → 0.6.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/dist/cli-errors-B9OBbled.d.mts +3 -0
- package/dist/cli-errors-D3_sMh2K.mjs +33 -0
- package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
- package/dist/cli.mjs +16 -78
- package/dist/cli.mjs.map +1 -1
- package/dist/client-qVH-rEgd.mjs +1595 -0
- package/dist/client-qVH-rEgd.mjs.map +1 -0
- package/dist/{result-handler-Ba3zWQsI.mjs → command-helpers-BeZHkxV8.mjs} +70 -47
- package/dist/command-helpers-BeZHkxV8.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +2 -4
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +2 -4
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +16 -13
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +6 -7
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +9 -9
- 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 +15 -13
- 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 -321
- package/dist/commands/migration-apply.d.mts +28 -13
- package/dist/commands/migration-apply.d.mts.map +1 -1
- package/dist/commands/migration-apply.mjs +55 -151
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts +0 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +34 -40
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +33 -6
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +2 -348
- package/dist/commands/migration-ref.d.mts +1 -1
- package/dist/commands/migration-ref.d.mts.map +1 -1
- package/dist/commands/migration-ref.mjs +8 -12
- package/dist/commands/migration-ref.mjs.map +1 -1
- package/dist/commands/migration-show.d.mts +13 -7
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +35 -36
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +126 -5
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -4
- package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
- package/dist/config-loader.d.mts +0 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/config-loader.mjs +2 -3
- package/dist/contract-emit-9DBda5Ou.mjs +150 -0
- package/dist/contract-emit-9DBda5Ou.mjs.map +1 -0
- package/dist/contract-emit-B77TsJqf.mjs +327 -0
- package/dist/contract-emit-B77TsJqf.mjs.map +1 -0
- package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-Dani0mMW.mjs} +4 -6
- package/dist/contract-enrichment-Dani0mMW.mjs.map +1 -0
- package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-BK9YFGEG.mjs} +13 -22
- package/dist/contract-infer-BK9YFGEG.mjs.map +1 -0
- package/dist/db-verify-C0y1PCO2.mjs +404 -0
- package/dist/db-verify-C0y1PCO2.mjs.map +1 -0
- package/dist/exports/config-types.mjs +1 -2
- package/dist/exports/control-api.d.mts +101 -586
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +4 -6
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +28 -30
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts +2 -4
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +2 -3
- package/dist/extension-pack-inputs-C7xgE-vv.mjs +74 -0
- package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +1 -0
- package/dist/{framework-components-Cr--XBKy.mjs → framework-components-ChqVUxR-.mjs} +3 -4
- package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-ChqVUxR-.mjs.map} +1 -1
- package/dist/global-flags-Icqpxk23.d.mts +12 -0
- package/dist/global-flags-Icqpxk23.d.mts.map +1 -0
- package/dist/helpers-eqdN8tH6.mjs +25 -0
- package/dist/helpers-eqdN8tH6.mjs.map +1 -0
- package/dist/{init-C5220SY9.mjs → init-DETSgw3h.mjs} +40 -49
- package/dist/init-DETSgw3h.mjs.map +1 -0
- package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-CWYxGKlb.mjs} +10 -11
- package/dist/inspect-live-schema-CWYxGKlb.mjs.map +1 -0
- package/dist/migration-cli.d.mts +41 -12
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +309 -86
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-B5dORFEv.mjs} +8 -9
- package/dist/migration-command-scaffold-B5dORFEv.mjs.map +1 -0
- package/dist/migration-plan-C6lVaHsO.mjs +554 -0
- package/dist/migration-plan-C6lVaHsO.mjs.map +1 -0
- package/dist/{migration-status-DUMiH8_G.mjs → migration-status-CZ-D5k7k.mjs} +272 -65
- package/dist/migration-status-CZ-D5k7k.mjs.map +1 -0
- package/dist/migrations-D_UJnpuW.mjs +216 -0
- package/dist/migrations-D_UJnpuW.mjs.map +1 -0
- package/dist/{output-BpcQrnnq.mjs → output-B16Kefzx.mjs} +9 -3
- package/dist/output-B16Kefzx.mjs.map +1 -0
- package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DFfvZcYL.mjs} +2 -2
- package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DFfvZcYL.mjs.map} +1 -1
- package/dist/result-handler-rmPVKIP2.mjs +25 -0
- package/dist/result-handler-rmPVKIP2.mjs.map +1 -0
- package/dist/rolldown-runtime-twds-ZHy.mjs +14 -0
- package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-C_hFNbAn.mjs} +4 -28
- package/dist/terminal-ui-C_hFNbAn.mjs.map +1 -0
- package/dist/types-D7x-IFLO.d.mts +858 -0
- package/dist/types-D7x-IFLO.d.mts.map +1 -0
- package/dist/{verify-Bkycc-Tf.mjs → verify-CiwNWM9N.mjs} +3 -4
- package/dist/verify-CiwNWM9N.mjs.map +1 -0
- package/package.json +19 -17
- package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
- package/dist/cli-errors-Cd79vmTH.mjs +0 -5
- package/dist/client-CrsnY58k.mjs +0 -997
- package/dist/client-CrsnY58k.mjs.map +0 -1
- package/dist/commands/db-verify.mjs.map +0 -1
- package/dist/commands/migration-plan.mjs.map +0 -1
- package/dist/config-loader-C25b63rJ.mjs.map +0 -1
- package/dist/contract-emit--feXyNd7.mjs +0 -4
- package/dist/contract-emit-NJ01hiiv.mjs +0 -195
- package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
- package/dist/contract-emit-V5SSitUT.mjs +0 -122
- package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
- package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
- package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
- package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
- package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
- package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
- package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
- package/dist/init-C5220SY9.mjs.map +0 -1
- package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
- package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
- package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
- package/dist/migrations-Bo5WtTla.mjs +0 -153
- package/dist/migrations-Bo5WtTla.mjs.map +0 -1
- package/dist/output-BpcQrnnq.mjs.map +0 -1
- package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
- package/dist/terminal-ui-C3ZLwQxK.mjs.map +0 -1
- package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
- package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
- package/dist/verify-Bkycc-Tf.mjs.map +0 -1
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, d as errorMarkerMissing, g as errorTargetMismatch, l as errorFileNotFound, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, u as errorHashMismatch } from "./cli-errors-D3_sMh2K.mjs";
|
|
3
|
+
import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, l as resolveMigrationPaths, o as maskConnectionUrl, t as addGlobalOptions, y as formatStyledHeader } from "./command-helpers-BeZHkxV8.mjs";
|
|
4
|
+
import { t as createProgressAdapter } from "./progress-adapter-DFfvZcYL.mjs";
|
|
5
|
+
import { t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
|
|
6
|
+
import { t as handleResult } from "./result-handler-rmPVKIP2.mjs";
|
|
7
|
+
import { o as ContractValidationError, t as createControlClient } from "./client-qVH-rEgd.mjs";
|
|
8
|
+
import { c as formatVerifyOutput, i as formatSchemaVerifyOutput, r as formatSchemaVerifyJson, s as formatVerifyJson } from "./verify-CiwNWM9N.mjs";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
11
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
12
|
+
import { relative, resolve } from "pathe";
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import { VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
|
|
15
|
+
//#region src/utils/combine-schema-results.ts
|
|
16
|
+
/**
|
|
17
|
+
* Collapse the aggregate verifier's per-space schema results into a
|
|
18
|
+
* single {@link VerifyDatabaseSchemaResult} for the existing CLI
|
|
19
|
+
* display surface. Concatenates issues across members; sums counts;
|
|
20
|
+
* uses the app member's result as the structural envelope (storage
|
|
21
|
+
* hash, target).
|
|
22
|
+
*
|
|
23
|
+
* **Summary policy.** Preserve the per-family phrasing whenever the
|
|
24
|
+
* combined `ok` flag agrees with the app member's `ok` flag — this is
|
|
25
|
+
* the common case (single-family deployments, single-app deployments)
|
|
26
|
+
* and the family's "satisfies / does not satisfy contract" phrasing
|
|
27
|
+
* stays user-visible. When the app passes but an extension fails (or
|
|
28
|
+
* vice versa) the app's summary contradicts the envelope, so fall back
|
|
29
|
+
* to the first failing member's summary. This keeps family phrasing
|
|
30
|
+
* intact and the envelope internally consistent (`ok: false` ↔ failure
|
|
31
|
+
* summary).
|
|
32
|
+
*/
|
|
33
|
+
function combineSchemaResults(perSpace, appSpaceId, strict) {
|
|
34
|
+
const appResult = perSpace.get(appSpaceId) ?? perSpace.values().next().value;
|
|
35
|
+
if (appResult === void 0) throw new Error("Aggregate verifier returned no schema results — this is a wiring bug.");
|
|
36
|
+
let okAll = true;
|
|
37
|
+
let firstFailure;
|
|
38
|
+
let issues = [];
|
|
39
|
+
const counts = {
|
|
40
|
+
pass: 0,
|
|
41
|
+
warn: 0,
|
|
42
|
+
fail: 0,
|
|
43
|
+
totalNodes: 0
|
|
44
|
+
};
|
|
45
|
+
const childRoots = [];
|
|
46
|
+
for (const [, result] of perSpace) {
|
|
47
|
+
if (!result.ok) {
|
|
48
|
+
okAll = false;
|
|
49
|
+
if (firstFailure === void 0) firstFailure = result;
|
|
50
|
+
}
|
|
51
|
+
issues = [...issues, ...result.schema.issues];
|
|
52
|
+
counts.pass += result.schema.counts.pass;
|
|
53
|
+
counts.warn += result.schema.counts.warn;
|
|
54
|
+
counts.fail += result.schema.counts.fail;
|
|
55
|
+
counts.totalNodes += result.schema.counts.totalNodes;
|
|
56
|
+
childRoots.push(result.schema.root);
|
|
57
|
+
}
|
|
58
|
+
const summary = okAll === appResult.ok ? appResult.summary : firstFailure.summary;
|
|
59
|
+
return {
|
|
60
|
+
ok: okAll,
|
|
61
|
+
...okAll ? {} : { code: appResult.code ?? "PN-RUN-3010" },
|
|
62
|
+
summary,
|
|
63
|
+
contract: appResult.contract,
|
|
64
|
+
target: appResult.target,
|
|
65
|
+
schema: {
|
|
66
|
+
issues,
|
|
67
|
+
root: {
|
|
68
|
+
status: okAll ? "pass" : "fail",
|
|
69
|
+
kind: "aggregate",
|
|
70
|
+
name: "aggregate",
|
|
71
|
+
contractPath: "",
|
|
72
|
+
code: "AGGREGATE",
|
|
73
|
+
message: okAll ? "Aggregate schema matches" : "Aggregate schema mismatch",
|
|
74
|
+
expected: void 0,
|
|
75
|
+
actual: void 0,
|
|
76
|
+
children: childRoots
|
|
77
|
+
},
|
|
78
|
+
counts
|
|
79
|
+
},
|
|
80
|
+
meta: { strict },
|
|
81
|
+
timings: { total: 0 }
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/commands/db-verify.ts
|
|
86
|
+
/**
|
|
87
|
+
* Maps a VerifyDatabaseResult failure to a CliStructuredError.
|
|
88
|
+
*/
|
|
89
|
+
function mapVerifyFailure(verifyResult) {
|
|
90
|
+
if (!verifyResult.ok && verifyResult.code) {
|
|
91
|
+
if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) return errorMarkerMissing();
|
|
92
|
+
if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {
|
|
93
|
+
const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;
|
|
94
|
+
const profileMatch = !verifyResult.contract.profileHash || verifyResult.marker?.profileHash === verifyResult.contract.profileHash;
|
|
95
|
+
if (!storageMatch) return errorHashMismatch({
|
|
96
|
+
why: "Contract storageHash does not match database marker",
|
|
97
|
+
expected: verifyResult.contract.storageHash,
|
|
98
|
+
...ifDefined("actual", verifyResult.marker?.storageHash)
|
|
99
|
+
});
|
|
100
|
+
return errorHashMismatch({
|
|
101
|
+
why: profileMatch ? "Contract hash does not match database marker" : "Contract profileHash does not match database marker",
|
|
102
|
+
...ifDefined("expected", verifyResult.contract.profileHash),
|
|
103
|
+
...ifDefined("actual", verifyResult.marker?.profileHash)
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) return errorTargetMismatch(verifyResult.target.expected, verifyResult.target.actual ?? "unknown");
|
|
107
|
+
}
|
|
108
|
+
return errorRuntime(verifyResult.summary);
|
|
109
|
+
}
|
|
110
|
+
function errorInvalidVerifyMode(options) {
|
|
111
|
+
return new CliStructuredError("4012", "Invalid verify mode", {
|
|
112
|
+
domain: "CLI",
|
|
113
|
+
why: options.why,
|
|
114
|
+
fix: options.fix,
|
|
115
|
+
docsUrl: "https://pris.ly/db-verify"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function resolveDbVerifyMode(options) {
|
|
119
|
+
if (options.markerOnly && options.schemaOnly) return notOk(errorInvalidVerifyMode({
|
|
120
|
+
why: "`--marker-only` and `--schema-only` cannot be used together",
|
|
121
|
+
fix: "Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema."
|
|
122
|
+
}));
|
|
123
|
+
if (options.markerOnly && options.strict) return notOk(errorInvalidVerifyMode({
|
|
124
|
+
why: "`--strict` requires schema verification, but `--marker-only` skips it",
|
|
125
|
+
fix: "Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode."
|
|
126
|
+
}));
|
|
127
|
+
if (options.schemaOnly) return ok("schema-only");
|
|
128
|
+
if (options.markerOnly) return ok("marker-only");
|
|
129
|
+
return ok("full");
|
|
130
|
+
}
|
|
131
|
+
function formatDbVerifyModeLabel(mode, strict) {
|
|
132
|
+
if (mode === "marker-only") return "marker only";
|
|
133
|
+
if (mode === "schema-only") return `schema only (${strict ? "strict" : "tolerant"})`;
|
|
134
|
+
return `full (marker + schema, ${strict ? "strict" : "tolerant"})`;
|
|
135
|
+
}
|
|
136
|
+
function formatDbVerifyInvocation(mode, strict) {
|
|
137
|
+
const args = ["db verify"];
|
|
138
|
+
if (mode === "marker-only") args.push("--marker-only");
|
|
139
|
+
if (mode === "schema-only") args.push("--schema-only");
|
|
140
|
+
if (strict) args.push("--strict");
|
|
141
|
+
return args.join(" ");
|
|
142
|
+
}
|
|
143
|
+
function createDbVerifyConnectionRequiredError(options) {
|
|
144
|
+
const invocation = formatDbVerifyInvocation(options.mode, options.strict);
|
|
145
|
+
return errorDatabaseConnectionRequired({
|
|
146
|
+
why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,
|
|
147
|
+
retryCommand: `prisma-next ${invocation} --db <url>`
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function renderVerifyHeader(paths, options, mode, flags, ui) {
|
|
151
|
+
if (flags.json || flags.quiet) return;
|
|
152
|
+
const description = mode === "schema-only" ? "Check whether the live database schema matches your contract" : mode === "marker-only" ? "Check whether the database marker matches your contract" : "Check whether the database marker and live schema match your contract";
|
|
153
|
+
const details = [
|
|
154
|
+
{
|
|
155
|
+
label: "config",
|
|
156
|
+
value: paths.configPath
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
label: "contract",
|
|
160
|
+
value: paths.contractPath
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
label: "mode",
|
|
164
|
+
value: formatDbVerifyModeLabel(mode, options.strict ?? false)
|
|
165
|
+
}
|
|
166
|
+
];
|
|
167
|
+
if (options.db) details.push({
|
|
168
|
+
label: "database",
|
|
169
|
+
value: maskConnectionUrl(options.db)
|
|
170
|
+
});
|
|
171
|
+
ui.stderr(formatStyledHeader({
|
|
172
|
+
command: "db verify",
|
|
173
|
+
description,
|
|
174
|
+
url: "https://pris.ly/db-verify",
|
|
175
|
+
details,
|
|
176
|
+
flags
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
async function resolveVerifyPaths(options) {
|
|
180
|
+
const config = await loadConfig(options.config);
|
|
181
|
+
const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
|
|
182
|
+
const contractPathAbsolute = resolveContractPath(config);
|
|
183
|
+
return {
|
|
184
|
+
config,
|
|
185
|
+
configPath,
|
|
186
|
+
contractPathAbsolute,
|
|
187
|
+
contractPath: relative(process.cwd(), contractPathAbsolute)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async function resolveVerifySetup(paths, options, mode) {
|
|
191
|
+
const { config, configPath, contractPathAbsolute, contractPath } = paths;
|
|
192
|
+
let contractJsonContent;
|
|
193
|
+
try {
|
|
194
|
+
contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
|
|
195
|
+
} catch (error) {
|
|
196
|
+
if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
|
|
197
|
+
why: `Contract file not found at ${contractPathAbsolute}`,
|
|
198
|
+
fix: `Run \`prisma-next contract emit\` to generate ${contractPath}, or update \`config.contract.output\` in ${configPath}`
|
|
199
|
+
}));
|
|
200
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}` }));
|
|
201
|
+
}
|
|
202
|
+
let contractJson;
|
|
203
|
+
try {
|
|
204
|
+
contractJson = JSON.parse(contractJsonContent);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
return notOk(errorContractValidationFailed(`Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
|
|
207
|
+
}
|
|
208
|
+
const dbConnection = options.db ?? config.db?.connection;
|
|
209
|
+
if (typeof dbConnection !== "string" || dbConnection.length === 0) return notOk(createDbVerifyConnectionRequiredError({
|
|
210
|
+
configPath,
|
|
211
|
+
mode,
|
|
212
|
+
strict: options.strict ?? false
|
|
213
|
+
}));
|
|
214
|
+
if (!config.driver) return notOk(errorDriverRequired({ why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}` }));
|
|
215
|
+
return ok({
|
|
216
|
+
...paths,
|
|
217
|
+
contractJson,
|
|
218
|
+
dbConnection
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function createVerifyClient(setup) {
|
|
222
|
+
return createControlClient({
|
|
223
|
+
family: setup.config.family,
|
|
224
|
+
target: setup.config.target,
|
|
225
|
+
adapter: setup.config.adapter,
|
|
226
|
+
driver: setup.config.driver,
|
|
227
|
+
extensionPacks: setup.config.extensionPacks ?? []
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
function wrapVerifyError(error, contractPathAbsolute, modeLabel) {
|
|
231
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
232
|
+
if (error instanceof ContractValidationError) return notOk(errorContractValidationFailed(`Contract validation failed: ${error.message}`, { where: { path: contractPathAbsolute } }));
|
|
233
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}` }));
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Executes the db verify command and returns a structured Result.
|
|
237
|
+
*/
|
|
238
|
+
async function executeDbVerifyCommand(options, flags, ui, mode) {
|
|
239
|
+
const startTime = Date.now();
|
|
240
|
+
const paths = await resolveVerifyPaths(options);
|
|
241
|
+
renderVerifyHeader(paths, options, mode, flags, ui);
|
|
242
|
+
const setupResult = await resolveVerifySetup(paths, options, mode);
|
|
243
|
+
if (!setupResult.ok) return setupResult;
|
|
244
|
+
const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
|
|
245
|
+
const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);
|
|
246
|
+
const client = createVerifyClient(setupResult.value);
|
|
247
|
+
const onProgress = createProgressAdapter({
|
|
248
|
+
ui,
|
|
249
|
+
flags
|
|
250
|
+
});
|
|
251
|
+
try {
|
|
252
|
+
const verifyResult = await client.verify({
|
|
253
|
+
contract: contractJson,
|
|
254
|
+
connection: dbConnection,
|
|
255
|
+
onProgress
|
|
256
|
+
});
|
|
257
|
+
if (!verifyResult.ok) return notOk(mapVerifyFailure(verifyResult));
|
|
258
|
+
const aggregateResult = await client.dbVerify({
|
|
259
|
+
contract: contractJson,
|
|
260
|
+
migrationsDir,
|
|
261
|
+
strict: options.strict ?? false,
|
|
262
|
+
skipSchema: mode === "marker-only",
|
|
263
|
+
skipMarker: false,
|
|
264
|
+
onProgress
|
|
265
|
+
});
|
|
266
|
+
if (!aggregateResult.ok) return notOk(aggregateResult.failure);
|
|
267
|
+
if (mode === "marker-only") return ok({
|
|
268
|
+
ok: true,
|
|
269
|
+
mode: "marker-only",
|
|
270
|
+
summary: "Database marker matches contract",
|
|
271
|
+
contract: verifyResult.contract,
|
|
272
|
+
marker: verifyResult.marker,
|
|
273
|
+
target: verifyResult.target,
|
|
274
|
+
...ifDefined("missingCodecs", verifyResult.missingCodecs),
|
|
275
|
+
...ifDefined("codecCoverageSkipped", verifyResult.codecCoverageSkipped),
|
|
276
|
+
warning: "Schema verification skipped because --marker-only was provided",
|
|
277
|
+
meta: {
|
|
278
|
+
...verifyResult.meta ?? {},
|
|
279
|
+
schemaVerification: "skipped"
|
|
280
|
+
},
|
|
281
|
+
timings: { total: Date.now() - startTime }
|
|
282
|
+
});
|
|
283
|
+
const combined = combineSchemaResults(aggregateResult.value.schemaResults, aggregateResult.value.appSpaceId, options.strict ?? false);
|
|
284
|
+
if (!combined.ok) return notOk(combined);
|
|
285
|
+
return ok({
|
|
286
|
+
ok: true,
|
|
287
|
+
mode: "full",
|
|
288
|
+
summary: "Database marker and schema match contract",
|
|
289
|
+
contract: verifyResult.contract,
|
|
290
|
+
marker: verifyResult.marker,
|
|
291
|
+
target: verifyResult.target,
|
|
292
|
+
...ifDefined("missingCodecs", verifyResult.missingCodecs),
|
|
293
|
+
...ifDefined("codecCoverageSkipped", verifyResult.codecCoverageSkipped),
|
|
294
|
+
schema: {
|
|
295
|
+
summary: combined.summary,
|
|
296
|
+
counts: combined.schema.counts,
|
|
297
|
+
strict: combined.meta?.strict ?? false
|
|
298
|
+
},
|
|
299
|
+
meta: {
|
|
300
|
+
...verifyResult.meta ?? {},
|
|
301
|
+
schemaVerification: "performed"
|
|
302
|
+
},
|
|
303
|
+
timings: { total: Date.now() - startTime }
|
|
304
|
+
});
|
|
305
|
+
} catch (error) {
|
|
306
|
+
return wrapVerifyError(error, contractPathAbsolute, "db verify");
|
|
307
|
+
} finally {
|
|
308
|
+
await client.close();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async function executeDbSchemaOnlyVerifyCommand(options, flags, ui) {
|
|
312
|
+
const paths = await resolveVerifyPaths(options);
|
|
313
|
+
renderVerifyHeader(paths, options, "schema-only", flags, ui);
|
|
314
|
+
const setupResult = await resolveVerifySetup(paths, options, "schema-only");
|
|
315
|
+
if (!setupResult.ok) return setupResult;
|
|
316
|
+
const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
|
|
317
|
+
const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);
|
|
318
|
+
const client = createVerifyClient(setupResult.value);
|
|
319
|
+
const onProgress = createProgressAdapter({
|
|
320
|
+
ui,
|
|
321
|
+
flags
|
|
322
|
+
});
|
|
323
|
+
try {
|
|
324
|
+
await client.connect(dbConnection);
|
|
325
|
+
const aggregateResult = await client.dbVerify({
|
|
326
|
+
contract: contractJson,
|
|
327
|
+
migrationsDir,
|
|
328
|
+
strict: options.strict ?? false,
|
|
329
|
+
skipSchema: false,
|
|
330
|
+
skipMarker: true,
|
|
331
|
+
onProgress
|
|
332
|
+
});
|
|
333
|
+
if (!aggregateResult.ok) return notOk(aggregateResult.failure);
|
|
334
|
+
return ok(combineSchemaResults(aggregateResult.value.schemaResults, aggregateResult.value.appSpaceId, options.strict ?? false));
|
|
335
|
+
} catch (error) {
|
|
336
|
+
return wrapVerifyError(error, contractPathAbsolute, "db verify --schema-only");
|
|
337
|
+
} finally {
|
|
338
|
+
await client.close();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function createDbVerifyCommand() {
|
|
342
|
+
const command = new Command("verify");
|
|
343
|
+
setCommandDescriptions(command, "Check whether the database marker and live schema match your contract", "Verifies the database marker first, then checks the database schema matches your contract.\nUse `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\ninspect only the live schema, and `--strict` to fail if the database includes elements\nnot present in the contract.");
|
|
344
|
+
setCommandExamples(command, [
|
|
345
|
+
"prisma-next db verify --db $DATABASE_URL",
|
|
346
|
+
"prisma-next db verify --db $DATABASE_URL --strict",
|
|
347
|
+
"prisma-next db verify --db $DATABASE_URL --schema-only",
|
|
348
|
+
"prisma-next db verify --db $DATABASE_URL --schema-only --strict",
|
|
349
|
+
"prisma-next db verify --db $DATABASE_URL --marker-only",
|
|
350
|
+
"prisma-next db verify --db $DATABASE_URL --json"
|
|
351
|
+
]);
|
|
352
|
+
addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--marker-only", "Skip schema verification and only check the database marker").option("--schema-only", "Skip marker verification and only check whether the live schema satisfies the contract").option("--strict", "Strict mode: schema elements not present in the contract are considered an error", false).action(async (options) => {
|
|
353
|
+
const flags = parseGlobalFlags(options);
|
|
354
|
+
const ui = new TerminalUI({
|
|
355
|
+
color: flags.color,
|
|
356
|
+
interactive: flags.interactive
|
|
357
|
+
});
|
|
358
|
+
const modeResult = resolveDbVerifyMode(options);
|
|
359
|
+
if (!modeResult.ok) {
|
|
360
|
+
const exitCode = handleResult(modeResult, flags, ui);
|
|
361
|
+
process.exit(exitCode);
|
|
362
|
+
}
|
|
363
|
+
const mode = modeResult.value;
|
|
364
|
+
if (mode === "schema-only") {
|
|
365
|
+
const result = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);
|
|
366
|
+
const exitCode = handleResult(result, flags, ui, (schemaVerifyResult) => {
|
|
367
|
+
if (flags.json) ui.output(formatSchemaVerifyJson(schemaVerifyResult));
|
|
368
|
+
else {
|
|
369
|
+
const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);
|
|
370
|
+
if (output) ui.log(output);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
if (result.ok && !result.value.ok) process.exit(1);
|
|
374
|
+
process.exit(exitCode);
|
|
375
|
+
}
|
|
376
|
+
const result = await executeDbVerifyCommand(options, flags, ui, mode);
|
|
377
|
+
if (result.ok) {
|
|
378
|
+
if (flags.json) ui.output(formatVerifyJson(result.value));
|
|
379
|
+
else {
|
|
380
|
+
const output = formatVerifyOutput(result.value, flags);
|
|
381
|
+
if (output) ui.log(output);
|
|
382
|
+
}
|
|
383
|
+
process.exit(0);
|
|
384
|
+
}
|
|
385
|
+
if (CliStructuredError.is(result.failure)) {
|
|
386
|
+
const exitCode = handleResult(result, flags, ui);
|
|
387
|
+
process.exit(exitCode);
|
|
388
|
+
}
|
|
389
|
+
if (flags.json) ui.output(formatSchemaVerifyJson(result.failure));
|
|
390
|
+
else {
|
|
391
|
+
const output = formatSchemaVerifyOutput(result.failure, {
|
|
392
|
+
...flags,
|
|
393
|
+
quiet: false
|
|
394
|
+
});
|
|
395
|
+
if (output) ui.log(output);
|
|
396
|
+
}
|
|
397
|
+
process.exit(1);
|
|
398
|
+
});
|
|
399
|
+
return command;
|
|
400
|
+
}
|
|
401
|
+
//#endregion
|
|
402
|
+
export { createDbVerifyCommand as t };
|
|
403
|
+
|
|
404
|
+
//# sourceMappingURL=db-verify-C0y1PCO2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-verify-C0y1PCO2.mjs","names":[],"sources":["../src/utils/combine-schema-results.ts","../src/commands/db-verify.ts"],"sourcesContent":["import type { VerifyDatabaseSchemaResult } from '@prisma-next/framework-components/control';\n\n/**\n * Collapse the aggregate verifier's per-space schema results into a\n * single {@link VerifyDatabaseSchemaResult} for the existing CLI\n * display surface. Concatenates issues across members; sums counts;\n * uses the app member's result as the structural envelope (storage\n * hash, target).\n *\n * **Summary policy.** Preserve the per-family phrasing whenever the\n * combined `ok` flag agrees with the app member's `ok` flag — this is\n * the common case (single-family deployments, single-app deployments)\n * and the family's \"satisfies / does not satisfy contract\" phrasing\n * stays user-visible. When the app passes but an extension fails (or\n * vice versa) the app's summary contradicts the envelope, so fall back\n * to the first failing member's summary. This keeps family phrasing\n * intact and the envelope internally consistent (`ok: false` ↔ failure\n * summary).\n */\nexport function combineSchemaResults(\n perSpace: ReadonlyMap<string, VerifyDatabaseSchemaResult>,\n appSpaceId: string,\n strict: boolean,\n): VerifyDatabaseSchemaResult {\n const appResult = perSpace.get(appSpaceId) ?? perSpace.values().next().value;\n if (appResult === undefined) {\n throw new Error('Aggregate verifier returned no schema results — this is a wiring bug.');\n }\n\n let okAll = true;\n let firstFailure: VerifyDatabaseSchemaResult | undefined;\n let issues: VerifyDatabaseSchemaResult['schema']['issues'] = [];\n const counts = { pass: 0, warn: 0, fail: 0, totalNodes: 0 };\n const childRoots: Array<VerifyDatabaseSchemaResult['schema']['root']> = [];\n for (const [, result] of perSpace) {\n if (!result.ok) {\n okAll = false;\n if (firstFailure === undefined) firstFailure = result;\n }\n issues = [...issues, ...result.schema.issues];\n counts.pass += result.schema.counts.pass;\n counts.warn += result.schema.counts.warn;\n counts.fail += result.schema.counts.fail;\n counts.totalNodes += result.schema.counts.totalNodes;\n childRoots.push(result.schema.root);\n }\n\n // When `okAll !== appResult.ok`, exactly one shape is reachable: app passes\n // (`appResult.ok === true`) and at least one other member failed\n // (`okAll === false`). In that shape the failure was assigned to\n // `firstFailure` during iteration, so non-null assertion is safe. The mirror\n // shape (app fails while every member passes) is impossible because\n // `appResult` either *is* a member of `perSpace` or is the first iterator\n // value; either way its `ok` flag participates in `okAll`.\n const summary =\n okAll === appResult.ok\n ? appResult.summary\n : (firstFailure as VerifyDatabaseSchemaResult).summary;\n\n return {\n ok: okAll,\n ...(okAll ? {} : { code: appResult.code ?? 'PN-RUN-3010' }),\n summary,\n contract: appResult.contract,\n target: appResult.target,\n schema: {\n issues,\n root: {\n status: okAll ? 'pass' : 'fail',\n kind: 'aggregate',\n name: 'aggregate',\n contractPath: '',\n code: 'AGGREGATE',\n message: okAll ? 'Aggregate schema matches' : 'Aggregate schema mismatch',\n expected: undefined,\n actual: undefined,\n children: childRoots,\n },\n counts,\n },\n meta: { strict },\n timings: { total: 0 },\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type {\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\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 errorHashMismatch,\n errorMarkerMissing,\n errorRuntime,\n errorTargetMismatch,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { combineSchemaResults } from '../utils/combine-schema-results';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport {\n type DbVerifyCommandSuccessResult,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatVerifyJson,\n formatVerifyOutput,\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 DbVerifyOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly markerOnly?: boolean;\n readonly schemaOnly?: boolean;\n readonly strict?: boolean;\n}\n\ntype DbVerifyMode = 'full' | 'marker-only' | 'schema-only';\n\n/**\n * Maps a VerifyDatabaseResult failure to a CliStructuredError.\n */\nfunction mapVerifyFailure(verifyResult: VerifyDatabaseResult): CliStructuredError {\n if (!verifyResult.ok && verifyResult.code) {\n if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) {\n return errorMarkerMissing();\n }\n if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {\n const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;\n const profileMatch =\n !verifyResult.contract.profileHash ||\n verifyResult.marker?.profileHash === verifyResult.contract.profileHash;\n\n if (!storageMatch) {\n return errorHashMismatch({\n why: 'Contract storageHash does not match database marker',\n expected: verifyResult.contract.storageHash,\n ...ifDefined('actual', verifyResult.marker?.storageHash),\n });\n }\n\n return errorHashMismatch({\n why: profileMatch\n ? 'Contract hash does not match database marker'\n : 'Contract profileHash does not match database marker',\n ...ifDefined('expected', verifyResult.contract.profileHash),\n ...ifDefined('actual', verifyResult.marker?.profileHash),\n });\n }\n if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) {\n return errorTargetMismatch(\n verifyResult.target.expected,\n verifyResult.target.actual ?? 'unknown',\n );\n }\n // Unknown code - fall through to runtime error\n }\n return errorRuntime(verifyResult.summary);\n}\n\ntype DbVerifyFailure = CliStructuredError | VerifyDatabaseSchemaResult;\n\nfunction errorInvalidVerifyMode(options: {\n readonly why: string;\n readonly fix: string;\n}): CliStructuredError {\n return new CliStructuredError('4012', 'Invalid verify mode', {\n domain: 'CLI',\n why: options.why,\n fix: options.fix,\n docsUrl: 'https://pris.ly/db-verify',\n });\n}\n\nfunction resolveDbVerifyMode(options: DbVerifyOptions): Result<DbVerifyMode, CliStructuredError> {\n if (options.markerOnly && options.schemaOnly) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--marker-only` and `--schema-only` cannot be used together',\n fix: 'Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema.',\n }),\n );\n }\n\n if (options.markerOnly && options.strict) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--strict` requires schema verification, but `--marker-only` skips it',\n fix: 'Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode.',\n }),\n );\n }\n\n if (options.schemaOnly) {\n return ok('schema-only');\n }\n\n if (options.markerOnly) {\n return ok('marker-only');\n }\n\n return ok('full');\n}\n\nfunction formatDbVerifyModeLabel(mode: DbVerifyMode, strict: boolean): string {\n if (mode === 'marker-only') {\n return 'marker only';\n }\n\n if (mode === 'schema-only') {\n return `schema only (${strict ? 'strict' : 'tolerant'})`;\n }\n\n return `full (marker + schema, ${strict ? 'strict' : 'tolerant'})`;\n}\n\nfunction formatDbVerifyInvocation(mode: DbVerifyMode, strict: boolean): string {\n const args = ['db verify'];\n\n if (mode === 'marker-only') {\n args.push('--marker-only');\n }\n\n if (mode === 'schema-only') {\n args.push('--schema-only');\n }\n\n if (strict) {\n args.push('--strict');\n }\n\n return args.join(' ');\n}\n\nfunction createDbVerifyConnectionRequiredError(options: {\n readonly configPath: string;\n readonly mode: DbVerifyMode;\n readonly strict: boolean;\n}): CliStructuredError {\n const invocation = formatDbVerifyInvocation(options.mode, options.strict);\n return errorDatabaseConnectionRequired({\n why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,\n retryCommand: `prisma-next ${invocation} --db <url>`,\n });\n}\n\nfunction renderVerifyHeader(\n paths: { configPath: string; contractPath: string },\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n flags: GlobalFlags,\n ui: TerminalUI,\n): void {\n if (flags.json || flags.quiet) return;\n\n const description =\n mode === 'schema-only'\n ? 'Check whether the live database schema matches your contract'\n : mode === 'marker-only'\n ? 'Check whether the database marker matches your contract'\n : 'Check whether the database marker and live schema match your contract';\n\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: paths.configPath },\n { label: 'contract', value: paths.contractPath },\n { label: 'mode', value: formatDbVerifyModeLabel(mode, options.strict ?? false) },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: 'db verify',\n description,\n url: 'https://pris.ly/db-verify',\n details,\n flags,\n }),\n );\n}\n\nasync function resolveVerifyPaths(options: DbVerifyOptions) {\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 return { config, configPath, contractPathAbsolute, contractPath };\n}\n\ntype VerifyPaths = Awaited<ReturnType<typeof resolveVerifyPaths>>;\n\ninterface VerifySetup extends VerifyPaths {\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: string;\n}\n\nasync function resolveVerifySetup(\n paths: VerifyPaths,\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n): Promise<Result<VerifySetup, CliStructuredError>> {\n const { config, configPath, contractPathAbsolute, contractPath } = paths;\n\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 const dbConnection = options.db ?? config.db?.connection;\n if (typeof dbConnection !== 'string' || dbConnection.length === 0) {\n return notOk(\n createDbVerifyConnectionRequiredError({\n configPath,\n mode,\n strict: options.strict ?? false,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}`,\n }),\n );\n }\n\n return ok({ ...paths, contractJson, dbConnection });\n}\n\nfunction createVerifyClient(setup: VerifySetup) {\n return createControlClient({\n family: setup.config.family,\n target: setup.config.target,\n adapter: setup.config.adapter,\n driver: setup.config.driver!,\n extensionPacks: setup.config.extensionPacks ?? [],\n });\n}\n\nfunction wrapVerifyError(\n error: unknown,\n contractPathAbsolute: string,\n modeLabel: string,\n): Result<never, CliStructuredError> {\n if (error instanceof CliStructuredError) {\n return notOk(error);\n }\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n}\n\n/**\n * Executes the db verify command and returns a structured Result.\n */\nasync function executeDbVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n mode: Extract<DbVerifyMode, 'full' | 'marker-only'>,\n): Promise<Result<DbVerifyCommandSuccessResult, DbVerifyFailure>> {\n const startTime = Date.now();\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, mode, flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, mode);\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Single-contract marker verification preserved for the existing\n // marker / target / hash failure surface (`PN-RUN-3001/3002/3003`).\n // The aggregate verifier (run below for the per-space marker /\n // schema checks) does not duplicate this: it concerns itself with\n // marker-vs-on-disk and orphan-marker drift, not the\n // hash-mismatch-against-the-app-contract lane that today's\n // `client.verify` covers.\n const verifyResult = await client.verify({\n contract: contractJson,\n connection: dbConnection,\n onProgress,\n });\n\n if (!verifyResult.ok) {\n return notOk(mapVerifyFailure(verifyResult));\n }\n\n // Aggregate verifier (loader → verifier pipeline). Runs the layout\n // precheck, marker-aware per-space verifier, and (full mode only)\n // per-space pre-projected schema verification (closes F23).\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: mode === 'marker-only',\n skipMarker: false,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n if (mode === 'marker-only') {\n return ok({\n ok: true,\n mode: 'marker-only',\n summary: 'Database marker matches contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n warning: 'Schema verification skipped because --marker-only was provided',\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'skipped',\n },\n timings: { total: Date.now() - startTime },\n });\n }\n\n const combined = combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n );\n if (!combined.ok) {\n return notOk(combined);\n }\n\n return ok({\n ok: true,\n mode: 'full',\n summary: 'Database marker and schema match contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n schema: {\n summary: combined.summary,\n counts: combined.schema.counts,\n strict: combined.meta?.strict ?? false,\n },\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'performed',\n },\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify');\n } finally {\n await client.close();\n }\n}\n\nasync function executeDbSchemaOnlyVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<VerifyDatabaseSchemaResult, CliStructuredError>> {\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, 'schema-only', flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, 'schema-only');\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n await client.connect(dbConnection);\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: false,\n skipMarker: true,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n return ok(\n combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n ),\n );\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify --schema-only');\n } finally {\n await client.close();\n }\n}\n\nexport function createDbVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Check whether the database marker and live schema match your contract',\n 'Verifies the database marker first, then checks the database schema matches your contract.\\n' +\n 'Use `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\\n' +\n 'inspect only the live schema, and `--strict` to fail if the database includes elements\\n' +\n 'not present in the contract.',\n );\n setCommandExamples(command, [\n 'prisma-next db verify --db $DATABASE_URL',\n 'prisma-next db verify --db $DATABASE_URL --strict',\n 'prisma-next db verify --db $DATABASE_URL --schema-only',\n 'prisma-next db verify --db $DATABASE_URL --schema-only --strict',\n 'prisma-next db verify --db $DATABASE_URL --marker-only',\n 'prisma-next db verify --db $DATABASE_URL --json',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--marker-only', 'Skip schema verification and only check the database marker')\n .option(\n '--schema-only',\n 'Skip marker verification and only check whether the live schema satisfies the contract',\n )\n .option(\n '--strict',\n 'Strict mode: schema elements not present in the contract are considered an error',\n false,\n )\n .action(async (options: DbVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const modeResult = resolveDbVerifyMode(options);\n if (!modeResult.ok) {\n const exitCode = handleResult(modeResult as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n const mode = modeResult.value;\n\n if (mode === 'schema-only') {\n const result = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (schemaVerifyResult) => {\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n\n if (result.ok && !result.value.ok) {\n process.exit(1);\n }\n\n process.exit(exitCode);\n }\n\n const result = await executeDbVerifyCommand(options, flags, ui, mode);\n\n if (result.ok) {\n if (flags.json) {\n ui.output(formatVerifyJson(result.value));\n } else {\n const output = formatVerifyOutput(result.value, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(0);\n }\n\n if (CliStructuredError.is(result.failure)) {\n const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(result.failure));\n } else {\n // Always show schema-drift failures, even in quiet mode — exiting 1 without\n // diagnostics is unhelpful.\n const output = formatSchemaVerifyOutput(result.failure, { ...flags, quiet: false });\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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"}
|