@prisma-next/cli 0.3.0-dev.7 → 0.3.0-dev.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +314 -80
- package/dist/cli-errors-JlPTsazx.mjs +3 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.js +1 -2376
- package/dist/cli.mjs +198 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/client-PimzSD1f.mjs +981 -0
- package/dist/client-PimzSD1f.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts +7 -0
- package/dist/commands/contract-emit.d.mts.map +1 -0
- package/dist/commands/contract-emit.mjs +150 -0
- package/dist/commands/contract-emit.mjs.map +1 -0
- package/dist/commands/db-init.d.mts +7 -0
- package/dist/commands/db-init.d.mts.map +1 -0
- package/dist/commands/db-init.mjs +132 -0
- package/dist/commands/db-init.mjs.map +1 -0
- package/dist/commands/db-introspect.d.mts +7 -0
- package/dist/commands/db-introspect.d.mts.map +1 -0
- package/dist/commands/db-introspect.mjs +117 -0
- package/dist/commands/db-introspect.mjs.map +1 -0
- package/dist/commands/db-schema-verify.d.mts +7 -0
- package/dist/commands/db-schema-verify.d.mts.map +1 -0
- package/dist/commands/db-schema-verify.mjs +119 -0
- package/dist/commands/db-schema-verify.mjs.map +1 -0
- package/dist/commands/db-sign.d.mts +7 -0
- package/dist/commands/db-sign.d.mts.map +1 -0
- package/dist/commands/db-sign.mjs +141 -0
- package/dist/commands/db-sign.mjs.map +1 -0
- package/dist/commands/db-update.d.mts +7 -0
- package/dist/commands/db-update.d.mts.map +1 -0
- package/dist/commands/db-update.mjs +121 -0
- package/dist/commands/db-update.mjs.map +1 -0
- package/dist/commands/db-verify.d.mts +7 -0
- package/dist/commands/db-verify.d.mts.map +1 -0
- package/dist/commands/db-verify.mjs +132 -0
- package/dist/commands/db-verify.mjs.map +1 -0
- package/dist/commands/migration-apply.d.mts +23 -0
- package/dist/commands/migration-apply.d.mts.map +1 -0
- package/dist/commands/migration-apply.mjs +249 -0
- package/dist/commands/migration-apply.mjs.map +1 -0
- package/dist/commands/migration-plan.d.mts +25 -0
- package/dist/commands/migration-plan.d.mts.map +1 -0
- package/dist/commands/migration-plan.mjs +266 -0
- package/dist/commands/migration-plan.mjs.map +1 -0
- package/dist/commands/migration-show.d.mts +28 -0
- package/dist/commands/migration-show.d.mts.map +1 -0
- package/dist/commands/migration-show.mjs +138 -0
- package/dist/commands/migration-show.mjs.map +1 -0
- package/dist/commands/migration-status.d.mts +35 -0
- package/dist/commands/migration-status.d.mts.map +1 -0
- package/dist/commands/migration-status.mjs +259 -0
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/migration-verify.d.mts +16 -0
- package/dist/commands/migration-verify.d.mts.map +1 -0
- package/dist/commands/migration-verify.mjs +86 -0
- package/dist/commands/migration-verify.mjs.map +1 -0
- package/dist/config-loader-PPf4CtDj.mjs +43 -0
- package/dist/config-loader-PPf4CtDj.mjs.map +1 -0
- package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
- package/dist/config-loader.d.mts.map +1 -0
- package/dist/config-loader.mjs +3 -0
- package/dist/exports/config-types.d.mts +2 -0
- package/dist/exports/config-types.mjs +3 -0
- package/dist/exports/control-api.d.mts +621 -0
- package/dist/exports/control-api.d.mts.map +1 -0
- package/dist/exports/control-api.mjs +97 -0
- package/dist/exports/control-api.mjs.map +1 -0
- package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
- package/dist/exports/index.d.mts.map +1 -0
- package/dist/exports/index.mjs +130 -0
- package/dist/exports/index.mjs.map +1 -0
- package/dist/extract-sql-ddl-BmlKvk4o.mjs +26 -0
- package/dist/extract-sql-ddl-BmlKvk4o.mjs.map +1 -0
- package/dist/framework-components-CjV_jD8f.mjs +59 -0
- package/dist/framework-components-CjV_jD8f.mjs.map +1 -0
- package/dist/migration-command-scaffold-DfY_F3ev.mjs +97 -0
- package/dist/migration-command-scaffold-DfY_F3ev.mjs.map +1 -0
- package/dist/progress-adapter-DENrzF6I.mjs +49 -0
- package/dist/progress-adapter-DENrzF6I.mjs.map +1 -0
- package/dist/result-handler-iA9JtUC7.mjs +1186 -0
- package/dist/result-handler-iA9JtUC7.mjs.map +1 -0
- package/package.json +75 -38
- package/src/cli.ts +43 -0
- package/src/commands/contract-emit.ts +221 -111
- package/src/commands/db-init.ts +217 -426
- package/src/commands/db-introspect.ts +148 -185
- package/src/commands/db-schema-verify.ts +162 -149
- package/src/commands/db-sign.ts +215 -202
- package/src/commands/db-update.ts +220 -0
- package/src/commands/db-verify.ts +193 -156
- package/src/commands/migration-apply.ts +431 -0
- package/src/commands/migration-plan.ts +446 -0
- package/src/commands/migration-show.ts +255 -0
- package/src/commands/migration-status.ts +436 -0
- package/src/commands/migration-verify.ts +151 -0
- package/src/config-loader.ts +13 -3
- package/src/control-api/client.ts +605 -0
- package/src/control-api/errors.ts +9 -0
- package/src/control-api/operations/contract-emit.ts +161 -0
- package/src/control-api/operations/db-init.ts +286 -0
- package/src/control-api/operations/db-update.ts +221 -0
- package/src/control-api/operations/extract-sql-ddl.ts +47 -0
- package/src/control-api/operations/migration-apply.ts +195 -0
- package/src/control-api/operations/migration-helpers.ts +49 -0
- package/src/control-api/types.ts +687 -0
- package/src/exports/config-types.ts +3 -3
- package/src/exports/control-api.ts +53 -0
- package/src/load-ts-contract.ts +16 -11
- package/src/utils/cli-errors.ts +3 -1
- package/src/utils/command-helpers.ts +92 -3
- package/src/utils/framework-components.ts +11 -30
- package/src/utils/migration-command-scaffold.ts +190 -0
- package/src/utils/output.ts +363 -25
- package/src/utils/progress-adapter.ts +86 -0
- package/dist/chunk-464LNZCE.js +0 -134
- package/dist/chunk-464LNZCE.js.map +0 -1
- package/dist/chunk-BZMBKEEQ.js +0 -997
- package/dist/chunk-BZMBKEEQ.js.map +0 -1
- package/dist/chunk-HWYQOCAJ.js +0 -47
- package/dist/chunk-HWYQOCAJ.js.map +0 -1
- package/dist/chunk-ZKYEJROM.js +0 -94
- package/dist/chunk-ZKYEJROM.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/contract-emit.d.ts +0 -3
- package/dist/commands/contract-emit.d.ts.map +0 -1
- package/dist/commands/contract-emit.js +0 -9
- package/dist/commands/contract-emit.js.map +0 -1
- package/dist/commands/db-init.d.ts +0 -3
- package/dist/commands/db-init.d.ts.map +0 -1
- package/dist/commands/db-init.js +0 -341
- package/dist/commands/db-init.js.map +0 -1
- package/dist/commands/db-introspect.d.ts +0 -3
- package/dist/commands/db-introspect.d.ts.map +0 -1
- package/dist/commands/db-introspect.js +0 -190
- package/dist/commands/db-introspect.js.map +0 -1
- package/dist/commands/db-schema-verify.d.ts +0 -3
- package/dist/commands/db-schema-verify.d.ts.map +0 -1
- package/dist/commands/db-schema-verify.js +0 -164
- package/dist/commands/db-schema-verify.js.map +0 -1
- package/dist/commands/db-sign.d.ts +0 -3
- package/dist/commands/db-sign.d.ts.map +0 -1
- package/dist/commands/db-sign.js +0 -199
- package/dist/commands/db-sign.js.map +0 -1
- package/dist/commands/db-verify.d.ts +0 -3
- package/dist/commands/db-verify.d.ts.map +0 -1
- package/dist/commands/db-verify.js +0 -173
- package/dist/commands/db-verify.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js +0 -7
- package/dist/config-loader.js.map +0 -1
- package/dist/exports/config-types.d.ts +0 -3
- package/dist/exports/config-types.d.ts.map +0 -1
- package/dist/exports/config-types.js +0 -6
- package/dist/exports/config-types.js.map +0 -1
- package/dist/exports/index.d.ts +0 -4
- package/dist/exports/index.d.ts.map +0 -1
- package/dist/exports/index.js +0 -175
- package/dist/exports/index.js.map +0 -1
- package/dist/load-ts-contract.d.ts.map +0 -1
- package/dist/utils/action.d.ts +0 -16
- package/dist/utils/action.d.ts.map +0 -1
- package/dist/utils/cli-errors.d.ts +0 -7
- package/dist/utils/cli-errors.d.ts.map +0 -1
- package/dist/utils/command-helpers.d.ts +0 -12
- package/dist/utils/command-helpers.d.ts.map +0 -1
- package/dist/utils/framework-components.d.ts +0 -81
- package/dist/utils/framework-components.d.ts.map +0 -1
- package/dist/utils/global-flags.d.ts +0 -25
- package/dist/utils/global-flags.d.ts.map +0 -1
- package/dist/utils/output.d.ts +0 -142
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/result-handler.d.ts +0 -15
- package/dist/utils/result-handler.d.ts.map +0 -1
- package/dist/utils/spinner.d.ts +0 -29
- package/dist/utils/spinner.d.ts.map +0 -1
- package/src/utils/action.ts +0 -43
- package/src/utils/spinner.ts +0 -67
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { t as loadConfig } from "../config-loader-PPf4CtDj.mjs";
|
|
2
|
+
import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-JlPTsazx.mjs";
|
|
3
|
+
import { t as createControlClient } from "../client-PimzSD1f.mjs";
|
|
4
|
+
import { C as parseGlobalFlags, D as setCommandDescriptions, T as resolveContractPath, f as formatMigrationStatusOutput, n as formatCommandHelp, t as handleResult, w as maskConnectionUrl, y as formatStyledHeader } from "../result-handler-iA9JtUC7.mjs";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
|
+
import { relative, resolve } from "pathe";
|
|
8
|
+
import { EMPTY_CONTRACT_HASH } from "@prisma-next/core-control-plane/constants";
|
|
9
|
+
import { readFile } from "node:fs/promises";
|
|
10
|
+
import { findLeaf, findPath, reconstructGraph } from "@prisma-next/migration-tools/dag";
|
|
11
|
+
import { readMigrationsDir } from "@prisma-next/migration-tools/io";
|
|
12
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/types";
|
|
13
|
+
|
|
14
|
+
//#region src/commands/migration-status.ts
|
|
15
|
+
function summarizeOps(ops) {
|
|
16
|
+
if (ops.length === 0) return {
|
|
17
|
+
summary: "0 ops",
|
|
18
|
+
hasDestructive: false
|
|
19
|
+
};
|
|
20
|
+
const classes = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const op of ops) classes.set(op.operationClass, (classes.get(op.operationClass) ?? 0) + 1);
|
|
22
|
+
const hasDestructive = classes.has("destructive");
|
|
23
|
+
const count = ops.length;
|
|
24
|
+
const noun = count === 1 ? "op" : "ops";
|
|
25
|
+
if (classes.size === 1) return {
|
|
26
|
+
summary: `${count} ${noun} (all ${[...classes.keys()][0]})`,
|
|
27
|
+
hasDestructive
|
|
28
|
+
};
|
|
29
|
+
const destructiveCount = classes.get("destructive");
|
|
30
|
+
if (destructiveCount) return {
|
|
31
|
+
summary: `${count} ${noun} (${destructiveCount} destructive)`,
|
|
32
|
+
hasDestructive
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
summary: `${count} ${noun} (${[...classes.entries()].map(([cls, n]) => `${n} ${cls}`).join(", ")})`,
|
|
36
|
+
hasDestructive
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function buildMigrationEntries(chain, packages, markerHash) {
|
|
40
|
+
const pkgByDirName = new Map(packages.map((p) => [p.dirName, p]));
|
|
41
|
+
const markerInChain = markerHash === void 0 || markerHash === EMPTY_CONTRACT_HASH || chain.some((e) => e.to === markerHash);
|
|
42
|
+
const entries = [];
|
|
43
|
+
let reachedMarker = markerHash === void 0 || markerHash === EMPTY_CONTRACT_HASH;
|
|
44
|
+
for (const migration of chain) {
|
|
45
|
+
const ops = pkgByDirName.get(migration.dirName)?.ops ?? [];
|
|
46
|
+
const { summary, hasDestructive } = summarizeOps(ops);
|
|
47
|
+
let status;
|
|
48
|
+
if (markerHash === void 0 || !markerInChain) status = "unknown";
|
|
49
|
+
else if (reachedMarker) status = "pending";
|
|
50
|
+
else status = "applied";
|
|
51
|
+
entries.push({
|
|
52
|
+
dirName: migration.dirName,
|
|
53
|
+
from: migration.from,
|
|
54
|
+
to: migration.to,
|
|
55
|
+
migrationId: migration.migrationId,
|
|
56
|
+
operationCount: ops.length,
|
|
57
|
+
operationSummary: summary,
|
|
58
|
+
hasDestructive,
|
|
59
|
+
status
|
|
60
|
+
});
|
|
61
|
+
if (!reachedMarker && migration.to === markerHash) reachedMarker = true;
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
async function executeMigrationStatusCommand(options, flags) {
|
|
66
|
+
const config = await loadConfig(options.config);
|
|
67
|
+
const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
|
|
68
|
+
const migrationsDir = resolve(options.config ? resolve(options.config, "..") : process.cwd(), config.migrations?.dir ?? "migrations");
|
|
69
|
+
const migrationsRelative = relative(process.cwd(), migrationsDir);
|
|
70
|
+
const dbConnection = options.db ?? config.db?.connection;
|
|
71
|
+
const hasDriver = !!config.driver;
|
|
72
|
+
if (flags.json !== "object" && !flags.quiet) {
|
|
73
|
+
const details = [{
|
|
74
|
+
label: "config",
|
|
75
|
+
value: configPath
|
|
76
|
+
}, {
|
|
77
|
+
label: "migrations",
|
|
78
|
+
value: migrationsRelative
|
|
79
|
+
}];
|
|
80
|
+
if (dbConnection && hasDriver) details.push({
|
|
81
|
+
label: "database",
|
|
82
|
+
value: maskConnectionUrl(String(dbConnection))
|
|
83
|
+
});
|
|
84
|
+
const header = formatStyledHeader({
|
|
85
|
+
command: "migration status",
|
|
86
|
+
description: "Show migration chain and applied status",
|
|
87
|
+
details,
|
|
88
|
+
flags
|
|
89
|
+
});
|
|
90
|
+
console.log(header);
|
|
91
|
+
}
|
|
92
|
+
const diagnostics = [];
|
|
93
|
+
let contractHash = EMPTY_CONTRACT_HASH;
|
|
94
|
+
try {
|
|
95
|
+
const contractContent = await readFile(resolveContractPath(config), "utf-8");
|
|
96
|
+
try {
|
|
97
|
+
const hash = JSON.parse(contractContent)["storageHash"];
|
|
98
|
+
if (typeof hash === "string") contractHash = hash;
|
|
99
|
+
else diagnostics.push({
|
|
100
|
+
code: "CONTRACT.MISSING_HASH",
|
|
101
|
+
severity: "warn",
|
|
102
|
+
message: "Contract file exists but has no storageHash field",
|
|
103
|
+
hints: ["Run 'prisma-next contract emit' to regenerate the contract"]
|
|
104
|
+
});
|
|
105
|
+
} catch {
|
|
106
|
+
diagnostics.push({
|
|
107
|
+
code: "CONTRACT.INVALID_JSON",
|
|
108
|
+
severity: "warn",
|
|
109
|
+
message: "Contract file contains invalid JSON",
|
|
110
|
+
hints: ["Run 'prisma-next contract emit' to regenerate the contract"]
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
diagnostics.push({
|
|
115
|
+
code: "CONTRACT.UNREADABLE",
|
|
116
|
+
severity: "warn",
|
|
117
|
+
message: "Could not read contract file — contract state unknown",
|
|
118
|
+
hints: ["Run 'prisma-next contract emit' to generate a contract"]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
let allPackages;
|
|
122
|
+
try {
|
|
123
|
+
allPackages = await readMigrationsDir(migrationsDir);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
|
|
126
|
+
why: error.why,
|
|
127
|
+
fix: error.fix,
|
|
128
|
+
meta: { code: error.code }
|
|
129
|
+
}));
|
|
130
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}` }));
|
|
131
|
+
}
|
|
132
|
+
const attested = allPackages.filter((p) => typeof p.manifest.migrationId === "string");
|
|
133
|
+
if (attested.length === 0) {
|
|
134
|
+
if (contractHash !== EMPTY_CONTRACT_HASH) diagnostics.push({
|
|
135
|
+
code: "CONTRACT.AHEAD",
|
|
136
|
+
severity: "warn",
|
|
137
|
+
message: "Contract has changed since the last migration was planned",
|
|
138
|
+
hints: ["Run 'prisma-next migration plan' to generate a migration for the current contract"]
|
|
139
|
+
});
|
|
140
|
+
return ok({
|
|
141
|
+
ok: true,
|
|
142
|
+
mode: dbConnection && hasDriver ? "online" : "offline",
|
|
143
|
+
migrations: [],
|
|
144
|
+
leafHash: EMPTY_CONTRACT_HASH,
|
|
145
|
+
contractHash,
|
|
146
|
+
summary: "No migrations found",
|
|
147
|
+
diagnostics
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
let graph;
|
|
151
|
+
let leafHash;
|
|
152
|
+
try {
|
|
153
|
+
graph = reconstructGraph(attested);
|
|
154
|
+
leafHash = findLeaf(graph);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
|
|
157
|
+
why: error.why,
|
|
158
|
+
fix: error.fix,
|
|
159
|
+
meta: { code: error.code }
|
|
160
|
+
}));
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
const chain = findPath(graph, EMPTY_CONTRACT_HASH, leafHash);
|
|
164
|
+
if (!chain) return notOk(errorRuntime("Cannot reconstruct migration chain", {
|
|
165
|
+
why: `No path from ${EMPTY_CONTRACT_HASH} to leaf ${leafHash}`,
|
|
166
|
+
fix: "The migration history may have gaps. Check the migrations directory for missing or corrupted packages."
|
|
167
|
+
}));
|
|
168
|
+
let markerHash;
|
|
169
|
+
let mode = "offline";
|
|
170
|
+
if (dbConnection && hasDriver) try {
|
|
171
|
+
const client = createControlClient({
|
|
172
|
+
family: config.family,
|
|
173
|
+
target: config.target,
|
|
174
|
+
adapter: config.adapter,
|
|
175
|
+
driver: config.driver,
|
|
176
|
+
extensionPacks: config.extensionPacks ?? []
|
|
177
|
+
});
|
|
178
|
+
try {
|
|
179
|
+
await client.connect(dbConnection);
|
|
180
|
+
markerHash = (await client.readMarker())?.storageHash ?? EMPTY_CONTRACT_HASH;
|
|
181
|
+
mode = "online";
|
|
182
|
+
} finally {
|
|
183
|
+
await client.close();
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
if (flags.json !== "object" && !flags.quiet) console.log(" ⚠ Could not connect to database — showing offline status\n");
|
|
187
|
+
}
|
|
188
|
+
const entries = buildMigrationEntries(chain, attested, mode === "online" ? markerHash : void 0);
|
|
189
|
+
const markerInChain = markerHash === void 0 || markerHash === EMPTY_CONTRACT_HASH || chain.some((e) => e.to === markerHash);
|
|
190
|
+
let summary;
|
|
191
|
+
if (mode === "online") if (!markerInChain) summary = `Database marker does not match any migration — was the database managed with 'db update'?`;
|
|
192
|
+
else {
|
|
193
|
+
const pendingCount = entries.filter((e) => e.status === "pending").length;
|
|
194
|
+
const appliedCount = entries.filter((e) => e.status === "applied").length;
|
|
195
|
+
if (pendingCount === 0) summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? "s" : ""} applied)`;
|
|
196
|
+
else if (markerHash === EMPTY_CONTRACT_HASH) summary = `${pendingCount} pending migration(s) — database has no marker`;
|
|
197
|
+
else summary = `${pendingCount} pending migration(s) — run 'prisma-next migration apply' to apply`;
|
|
198
|
+
}
|
|
199
|
+
else summary = `${entries.length} migration(s) on disk`;
|
|
200
|
+
if (contractHash !== EMPTY_CONTRACT_HASH && contractHash !== leafHash) diagnostics.push({
|
|
201
|
+
code: "CONTRACT.AHEAD",
|
|
202
|
+
severity: "warn",
|
|
203
|
+
message: "Contract has changed since the last migration was planned",
|
|
204
|
+
hints: ["Run 'prisma-next migration plan' to generate a migration for the current contract"]
|
|
205
|
+
});
|
|
206
|
+
if (mode === "online") {
|
|
207
|
+
const pendingCount = entries.filter((e) => e.status === "pending").length;
|
|
208
|
+
if (!markerInChain) diagnostics.push({
|
|
209
|
+
code: "MIGRATION.MARKER_DIVERGED",
|
|
210
|
+
severity: "warn",
|
|
211
|
+
message: "Database marker does not match any migration in the chain",
|
|
212
|
+
hints: ["The database may have been managed with 'db update' instead of migrations", "Run 'prisma-next db verify' to inspect the database state"]
|
|
213
|
+
});
|
|
214
|
+
else if (pendingCount > 0) diagnostics.push({
|
|
215
|
+
code: "MIGRATION.DATABASE_BEHIND",
|
|
216
|
+
severity: "info",
|
|
217
|
+
message: `${pendingCount} migration(s) pending`,
|
|
218
|
+
hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
|
|
219
|
+
});
|
|
220
|
+
else diagnostics.push({
|
|
221
|
+
code: "MIGRATION.UP_TO_DATE",
|
|
222
|
+
severity: "info",
|
|
223
|
+
message: "Database is up to date",
|
|
224
|
+
hints: []
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return ok({
|
|
228
|
+
ok: true,
|
|
229
|
+
mode,
|
|
230
|
+
migrations: entries,
|
|
231
|
+
leafHash,
|
|
232
|
+
contractHash,
|
|
233
|
+
summary,
|
|
234
|
+
diagnostics,
|
|
235
|
+
...markerHash !== void 0 ? { markerHash } : {}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function createMigrationStatusCommand() {
|
|
239
|
+
const command = new Command("status");
|
|
240
|
+
setCommandDescriptions(command, "Show migration chain and applied status", "Displays the migration chain in order. When a database connection\nis available, shows which migrations are applied and which are pending.\nWithout a database connection, shows the chain from disk only.");
|
|
241
|
+
command.configureHelp({ formatHelp: (cmd) => {
|
|
242
|
+
return formatCommandHelp({
|
|
243
|
+
command: cmd,
|
|
244
|
+
flags: parseGlobalFlags({})
|
|
245
|
+
});
|
|
246
|
+
} }).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--json [format]", "Output as JSON (object)", false).option("-q, --quiet", "Quiet mode: errors only").option("-v, --verbose", "Verbose output").option("-vv, --trace", "Trace output").option("--timestamps", "Add timestamps to output").option("--color", "Force color output").option("--no-color", "Disable color output").action(async (options) => {
|
|
247
|
+
const flags = parseGlobalFlags(options);
|
|
248
|
+
const exitCode = handleResult(await executeMigrationStatusCommand(options, flags), flags, (statusResult) => {
|
|
249
|
+
if (flags.json === "object") console.log(JSON.stringify(statusResult, null, 2));
|
|
250
|
+
else if (!flags.quiet) console.log(formatMigrationStatusOutput(statusResult, flags));
|
|
251
|
+
});
|
|
252
|
+
process.exit(exitCode);
|
|
253
|
+
});
|
|
254
|
+
return command;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
//#endregion
|
|
258
|
+
export { buildMigrationEntries, createMigrationStatusCommand };
|
|
259
|
+
//# sourceMappingURL=migration-status.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-status.mjs","names":["entries: MigrationStatusEntry[]","status: 'applied' | 'pending' | 'unknown'","details: Array<{ label: string; value: string }>","diagnostics: StatusDiagnostic[]","contractHash: string","allPackages: readonly MigrationPackage[]","graph: MigrationGraph","leafHash: string","markerHash: string | undefined","mode: 'online' | 'offline'","summary: string"],"sources":["../../src/commands/migration-status.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/core-control-plane/constants';\nimport type { MigrationPlanOperation } from '@prisma-next/core-control-plane/types';\nimport { findLeaf, findPath, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type {\n MigrationChainEntry,\n MigrationGraph,\n MigrationPackage,\n} from '@prisma-next/migration-tools/types';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\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 { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport {\n maskConnectionUrl,\n resolveContractPath,\n setCommandDescriptions,\n} from '../utils/command-helpers';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatMigrationStatusOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\n\ninterface MigrationStatusOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport interface MigrationStatusEntry {\n readonly dirName: string;\n readonly from: string;\n readonly to: string;\n readonly migrationId: string | null;\n readonly operationCount: number;\n readonly operationSummary: string;\n readonly hasDestructive: boolean;\n readonly status: 'applied' | 'pending' | 'unknown';\n}\n\nexport interface StatusDiagnostic {\n readonly code: string;\n readonly severity: 'warn' | 'info';\n readonly message: string;\n readonly hints: readonly string[];\n}\n\nexport interface MigrationStatusResult {\n readonly ok: true;\n readonly mode: 'online' | 'offline';\n readonly migrations: readonly MigrationStatusEntry[];\n readonly markerHash?: string;\n readonly leafHash: string;\n readonly contractHash: string;\n readonly summary: string;\n readonly diagnostics: readonly StatusDiagnostic[];\n}\n\nfunction summarizeOps(ops: readonly MigrationPlanOperation[]): {\n summary: string;\n hasDestructive: boolean;\n} {\n if (ops.length === 0) return { summary: '0 ops', hasDestructive: false };\n\n const classes = new Map<string, number>();\n for (const op of ops) {\n classes.set(op.operationClass, (classes.get(op.operationClass) ?? 0) + 1);\n }\n\n const hasDestructive = classes.has('destructive');\n const count = ops.length;\n const noun = count === 1 ? 'op' : 'ops';\n\n if (classes.size === 1) {\n const cls = [...classes.keys()][0]!;\n return { summary: `${count} ${noun} (all ${cls})`, hasDestructive };\n }\n\n const destructiveCount = classes.get('destructive');\n if (destructiveCount) {\n return { summary: `${count} ${noun} (${destructiveCount} destructive)`, hasDestructive };\n }\n\n const parts = [...classes.entries()].map(([cls, n]) => `${n} ${cls}`);\n return { summary: `${count} ${noun} (${parts.join(', ')})`, hasDestructive };\n}\n\nexport function buildMigrationEntries(\n chain: readonly MigrationChainEntry[],\n packages: readonly MigrationPackage[],\n markerHash: string | undefined,\n): MigrationStatusEntry[] {\n const pkgByDirName = new Map(packages.map((p) => [p.dirName, p]));\n\n const markerInChain =\n markerHash === undefined ||\n markerHash === EMPTY_CONTRACT_HASH ||\n chain.some((e) => e.to === markerHash);\n\n const entries: MigrationStatusEntry[] = [];\n let reachedMarker = markerHash === undefined || markerHash === EMPTY_CONTRACT_HASH;\n\n for (const migration of chain) {\n const pkg = pkgByDirName.get(migration.dirName);\n const ops = (pkg?.ops ?? []) as readonly MigrationPlanOperation[];\n const { summary, hasDestructive } = summarizeOps(ops);\n\n let status: 'applied' | 'pending' | 'unknown';\n if (markerHash === undefined || !markerInChain) {\n status = 'unknown';\n } else if (reachedMarker) {\n status = 'pending';\n } else {\n status = 'applied';\n }\n\n entries.push({\n dirName: migration.dirName,\n from: migration.from,\n to: migration.to,\n migrationId: migration.migrationId,\n operationCount: ops.length,\n operationSummary: summary,\n hasDestructive,\n status,\n });\n\n if (!reachedMarker && migration.to === markerHash) {\n reachedMarker = true;\n }\n }\n\n return entries;\n}\n\nasync function executeMigrationStatusCommand(\n options: MigrationStatusOptions,\n flags: GlobalFlags,\n): Promise<Result<MigrationStatusResult, CliStructuredError>> {\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\n const migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n const dbConnection = options.db ?? config.db?.connection;\n const hasDriver = !!config.driver;\n\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (dbConnection && hasDriver) {\n details.push({ label: 'database', value: maskConnectionUrl(String(dbConnection)) });\n }\n const header = formatStyledHeader({\n command: 'migration status',\n description: 'Show migration chain and applied status',\n details,\n flags,\n });\n console.log(header);\n }\n\n const diagnostics: StatusDiagnostic[] = [];\n let contractHash: string = EMPTY_CONTRACT_HASH;\n try {\n const contractPathAbsolute = resolveContractPath(config);\n const contractContent = await readFile(contractPathAbsolute, 'utf-8');\n try {\n const contractRaw = JSON.parse(contractContent) as Record<string, unknown>;\n const hash = contractRaw['storageHash'];\n if (typeof hash === 'string') {\n contractHash = hash;\n } else {\n diagnostics.push({\n code: 'CONTRACT.MISSING_HASH',\n severity: 'warn',\n message: 'Contract file exists but has no storageHash field',\n hints: [\"Run 'prisma-next contract emit' to regenerate the contract\"],\n });\n }\n } catch {\n diagnostics.push({\n code: 'CONTRACT.INVALID_JSON',\n severity: 'warn',\n message: 'Contract file contains invalid JSON',\n hints: [\"Run 'prisma-next contract emit' to regenerate the contract\"],\n });\n }\n } catch {\n diagnostics.push({\n code: 'CONTRACT.UNREADABLE',\n severity: 'warn',\n message: 'Could not read contract file — contract state unknown',\n hints: [\"Run 'prisma-next contract emit' to generate a contract\"],\n });\n }\n\n let allPackages: readonly MigrationPackage[];\n try {\n allPackages = await readMigrationsDir(migrationsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, { why: error.why, fix: error.fix, meta: { code: error.code } }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const attested = allPackages.filter((p) => typeof p.manifest.migrationId === 'string');\n\n if (attested.length === 0) {\n if (contractHash !== EMPTY_CONTRACT_HASH) {\n diagnostics.push({\n code: 'CONTRACT.AHEAD',\n severity: 'warn',\n message: 'Contract has changed since the last migration was planned',\n hints: [\n \"Run 'prisma-next migration plan' to generate a migration for the current contract\",\n ],\n });\n }\n return ok({\n ok: true,\n mode: dbConnection && hasDriver ? 'online' : 'offline',\n migrations: [],\n leafHash: EMPTY_CONTRACT_HASH,\n contractHash,\n summary: 'No migrations found',\n diagnostics,\n });\n }\n\n let graph: MigrationGraph;\n let leafHash: string;\n try {\n graph = reconstructGraph(attested);\n leafHash = findLeaf(graph);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, { why: error.why, fix: error.fix, meta: { code: error.code } }),\n );\n }\n throw error;\n }\n\n const chain = findPath(graph, EMPTY_CONTRACT_HASH, leafHash);\n if (!chain) {\n return notOk(\n errorRuntime('Cannot reconstruct migration chain', {\n why: `No path from ${EMPTY_CONTRACT_HASH} to leaf ${leafHash}`,\n fix: 'The migration history may have gaps. Check the migrations directory for missing or corrupted packages.',\n }),\n );\n }\n\n let markerHash: string | undefined;\n let mode: 'online' | 'offline' = 'offline';\n\n if (dbConnection && hasDriver) {\n try {\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 try {\n await client.connect(dbConnection);\n const marker = await client.readMarker();\n markerHash = marker?.storageHash ?? EMPTY_CONTRACT_HASH;\n mode = 'online';\n } finally {\n await client.close();\n }\n } catch {\n if (flags.json !== 'object' && !flags.quiet) {\n console.log(' ⚠ Could not connect to database — showing offline status\\n');\n }\n }\n }\n\n const entries = buildMigrationEntries(\n chain,\n attested,\n mode === 'online' ? markerHash : undefined,\n );\n\n const markerInChain =\n markerHash === undefined ||\n markerHash === EMPTY_CONTRACT_HASH ||\n chain.some((e) => e.to === markerHash);\n\n let summary: string;\n if (mode === 'online') {\n if (!markerInChain) {\n summary = `Database marker does not match any migration — was the database managed with 'db update'?`;\n } else {\n const pendingCount = entries.filter((e) => e.status === 'pending').length;\n const appliedCount = entries.filter((e) => e.status === 'applied').length;\n if (pendingCount === 0) {\n summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? 's' : ''} applied)`;\n } else if (markerHash === EMPTY_CONTRACT_HASH) {\n summary = `${pendingCount} pending migration(s) — database has no marker`;\n } else {\n summary = `${pendingCount} pending migration(s) — run 'prisma-next migration apply' to apply`;\n }\n }\n } else {\n summary = `${entries.length} migration(s) on disk`;\n }\n\n if (contractHash !== EMPTY_CONTRACT_HASH && contractHash !== leafHash) {\n diagnostics.push({\n code: 'CONTRACT.AHEAD',\n severity: 'warn',\n message: 'Contract has changed since the last migration was planned',\n hints: [\"Run 'prisma-next migration plan' to generate a migration for the current contract\"],\n });\n }\n\n if (mode === 'online') {\n const pendingCount = entries.filter((e) => e.status === 'pending').length;\n if (!markerInChain) {\n diagnostics.push({\n code: 'MIGRATION.MARKER_DIVERGED',\n severity: 'warn',\n message: 'Database marker does not match any migration in the chain',\n hints: [\n \"The database may have been managed with 'db update' instead of migrations\",\n \"Run 'prisma-next db verify' to inspect the database state\",\n ],\n });\n } else if (pendingCount > 0) {\n diagnostics.push({\n code: 'MIGRATION.DATABASE_BEHIND',\n severity: 'info',\n message: `${pendingCount} migration(s) pending`,\n hints: [\"Run 'prisma-next migration apply' to apply pending migrations\"],\n });\n } else {\n diagnostics.push({\n code: 'MIGRATION.UP_TO_DATE',\n severity: 'info',\n message: 'Database is up to date',\n hints: [],\n });\n }\n }\n\n const result: MigrationStatusResult = {\n ok: true,\n mode,\n migrations: entries,\n leafHash,\n contractHash,\n summary,\n diagnostics,\n ...(markerHash !== undefined ? { markerHash } : {}),\n };\n return ok(result);\n}\n\nexport function createMigrationStatusCommand(): Command {\n const command = new Command('status');\n setCommandDescriptions(\n command,\n 'Show migration chain and applied status',\n 'Displays the migration chain in order. When a database connection\\n' +\n 'is available, shows which migrations are applied and which are pending.\\n' +\n 'Without a database connection, shows the chain from disk only.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const defaultFlags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags: defaultFlags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output')\n .option('-vv, --trace', 'Trace output')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: MigrationStatusOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await executeMigrationStatusCommand(options, flags);\n\n const exitCode = handleResult(result, flags, (statusResult) => {\n if (flags.json === 'object') {\n console.log(JSON.stringify(statusResult, null, 2));\n } else if (!flags.quiet) {\n console.log(formatMigrationStatusOutput(statusResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/migration-verify.d.ts
|
|
4
|
+
interface MigrationVerifyResult {
|
|
5
|
+
readonly ok: boolean;
|
|
6
|
+
readonly status: 'verified' | 'attested';
|
|
7
|
+
readonly dir: string;
|
|
8
|
+
readonly migrationId?: string;
|
|
9
|
+
readonly storedMigrationId?: string;
|
|
10
|
+
readonly computedMigrationId?: string;
|
|
11
|
+
readonly summary: string;
|
|
12
|
+
}
|
|
13
|
+
declare function createMigrationVerifyCommand(): Command;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { MigrationVerifyResult, createMigrationVerifyCommand };
|
|
16
|
+
//# sourceMappingURL=migration-verify.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-verify.d.mts","names":[],"sources":["../../src/commands/migration-verify.ts"],"sourcesContent":[],"mappings":";;;UA6BiB,qBAAA;;EAAA,SAAA,MAAA,EAAA,UAAqB,GAAA,UAAA;EAgFtB,SAAA,GAAA,EAAA,MAAA;;;;;;iBAAA,4BAAA,CAAA,GAAgC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-JlPTsazx.mjs";
|
|
2
|
+
import { C as parseGlobalFlags, D as setCommandDescriptions, n as formatCommandHelp, p as formatMigrationVerifyCommandOutput, t as handleResult, y as formatStyledHeader } from "../result-handler-iA9JtUC7.mjs";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
5
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
6
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/types";
|
|
7
|
+
import { attestMigration, verifyMigration } from "@prisma-next/migration-tools/attestation";
|
|
8
|
+
|
|
9
|
+
//#region src/commands/migration-verify.ts
|
|
10
|
+
async function executeMigrationVerifyCommand(options, flags) {
|
|
11
|
+
const dir = options.dir;
|
|
12
|
+
if (flags.json !== "object" && !flags.quiet) {
|
|
13
|
+
const header = formatStyledHeader({
|
|
14
|
+
command: "migration verify",
|
|
15
|
+
description: "Verify migration package integrity",
|
|
16
|
+
details: [{
|
|
17
|
+
label: "dir",
|
|
18
|
+
value: dir
|
|
19
|
+
}],
|
|
20
|
+
flags
|
|
21
|
+
});
|
|
22
|
+
console.log(header);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const result = await verifyMigration(dir);
|
|
26
|
+
if (result.ok) return ok({
|
|
27
|
+
ok: true,
|
|
28
|
+
status: "verified",
|
|
29
|
+
dir,
|
|
30
|
+
...ifDefined("migrationId", result.storedMigrationId),
|
|
31
|
+
...ifDefined("storedMigrationId", result.storedMigrationId),
|
|
32
|
+
...ifDefined("computedMigrationId", result.computedMigrationId),
|
|
33
|
+
summary: "Migration package verified — migrationId matches"
|
|
34
|
+
});
|
|
35
|
+
if (result.reason === "draft") {
|
|
36
|
+
const migrationId = await attestMigration(dir);
|
|
37
|
+
return ok({
|
|
38
|
+
ok: true,
|
|
39
|
+
status: "attested",
|
|
40
|
+
dir,
|
|
41
|
+
migrationId,
|
|
42
|
+
summary: `Draft migration attested with migrationId: ${migrationId}`
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return notOk(errorRuntime("migrationId mismatch — migration has been modified", {
|
|
46
|
+
why: `stored=${result.storedMigrationId}, computed=${result.computedMigrationId}`,
|
|
47
|
+
fix: "If the change was intentional, set \"migrationId\" to null in migration.json and rerun `migration verify` to re-attest. Otherwise, restore the original migration.",
|
|
48
|
+
meta: {
|
|
49
|
+
storedMigrationId: result.storedMigrationId,
|
|
50
|
+
computedMigrationId: result.computedMigrationId
|
|
51
|
+
}
|
|
52
|
+
}));
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
|
|
55
|
+
why: error.why,
|
|
56
|
+
fix: error.fix,
|
|
57
|
+
meta: {
|
|
58
|
+
code: error.code,
|
|
59
|
+
...error.details ?? {}
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to verify migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function createMigrationVerifyCommand() {
|
|
66
|
+
const command = new Command("verify");
|
|
67
|
+
setCommandDescriptions(command, "Verify a migration package migrationId", "Recomputes the content-addressed migrationId for a migration package and compares\nit against the stored value. Draft migrations (migrationId: null) are automatically\nattested.");
|
|
68
|
+
command.configureHelp({ formatHelp: (cmd) => {
|
|
69
|
+
return formatCommandHelp({
|
|
70
|
+
command: cmd,
|
|
71
|
+
flags: parseGlobalFlags({})
|
|
72
|
+
});
|
|
73
|
+
} }).requiredOption("--dir <path>", "Path to the migration package directory").option("--json [format]", "Output as JSON (object)", false).option("-q, --quiet", "Quiet mode: errors only").option("-v, --verbose", "Verbose output").option("-vv, --trace", "Trace output").option("--timestamps", "Add timestamps to output").option("--color", "Force color output").option("--no-color", "Disable color output").action(async (options) => {
|
|
74
|
+
const flags = parseGlobalFlags(options);
|
|
75
|
+
const exitCode = handleResult(await executeMigrationVerifyCommand(options, flags), flags, (verifyResult) => {
|
|
76
|
+
if (flags.json === "object") console.log(JSON.stringify(verifyResult, null, 2));
|
|
77
|
+
else if (!flags.quiet) console.log(formatMigrationVerifyCommandOutput(verifyResult, flags));
|
|
78
|
+
});
|
|
79
|
+
process.exit(exitCode);
|
|
80
|
+
});
|
|
81
|
+
return command;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
export { createMigrationVerifyCommand };
|
|
86
|
+
//# sourceMappingURL=migration-verify.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-verify.mjs","names":[],"sources":["../../src/commands/migration-verify.ts"],"sourcesContent":["import { attestMigration, verifyMigration } from '@prisma-next/migration-tools/attestation';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatMigrationVerifyCommandOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\n\ninterface MigrationVerifyOptions {\n readonly dir: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport interface MigrationVerifyResult {\n readonly ok: boolean;\n readonly status: 'verified' | 'attested';\n readonly dir: string;\n readonly migrationId?: string;\n readonly storedMigrationId?: string;\n readonly computedMigrationId?: string;\n readonly summary: string;\n}\n\nasync function executeMigrationVerifyCommand(\n options: MigrationVerifyOptions,\n flags: GlobalFlags,\n): Promise<Result<MigrationVerifyResult, CliStructuredError>> {\n const dir = options.dir;\n\n if (flags.json !== 'object' && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration verify',\n description: 'Verify migration package integrity',\n details: [{ label: 'dir', value: dir }],\n flags,\n });\n console.log(header);\n }\n\n try {\n const result = await verifyMigration(dir);\n\n if (result.ok) {\n return ok({\n ok: true,\n status: 'verified',\n dir,\n ...ifDefined('migrationId', result.storedMigrationId),\n ...ifDefined('storedMigrationId', result.storedMigrationId),\n ...ifDefined('computedMigrationId', result.computedMigrationId),\n summary: 'Migration package verified — migrationId matches',\n });\n }\n\n if (result.reason === 'draft') {\n const migrationId = await attestMigration(dir);\n return ok({\n ok: true,\n status: 'attested',\n dir,\n migrationId,\n summary: `Draft migration attested with migrationId: ${migrationId}`,\n });\n }\n\n return notOk(\n errorRuntime('migrationId mismatch — migration has been modified', {\n why: `stored=${result.storedMigrationId}, computed=${result.computedMigrationId}`,\n fix: 'If the change was intentional, set \"migrationId\" to null in migration.json and rerun `migration verify` to re-attest. Otherwise, restore the original migration.',\n meta: {\n storedMigrationId: result.storedMigrationId,\n computedMigrationId: result.computedMigrationId,\n },\n }),\n );\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nexport function createMigrationVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Verify a migration package migrationId',\n 'Recomputes the content-addressed migrationId for a migration package and compares\\n' +\n 'it against the stored value. Draft migrations (migrationId: null) are automatically\\n' +\n 'attested.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const defaultFlags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags: defaultFlags });\n },\n })\n .requiredOption('--dir <path>', 'Path to the migration package directory')\n .option('--json [format]', 'Output as JSON (object)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output')\n .option('-vv, --trace', 'Trace output')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: MigrationVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await executeMigrationVerifyCommand(options, flags);\n\n const exitCode = handleResult(result, flags, (verifyResult) => {\n if (flags.json === 'object') {\n console.log(JSON.stringify(verifyResult, null, 2));\n } else if (!flags.quiet) {\n console.log(formatMigrationVerifyCommandOutput(verifyResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;AAuCA,eAAe,8BACb,SACA,OAC4D;CAC5D,MAAM,MAAM,QAAQ;AAEpB,KAAI,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;EAC3C,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb,SAAS,CAAC;IAAE,OAAO;IAAO,OAAO;IAAK,CAAC;GACvC;GACD,CAAC;AACF,UAAQ,IAAI,OAAO;;AAGrB,KAAI;EACF,MAAM,SAAS,MAAM,gBAAgB,IAAI;AAEzC,MAAI,OAAO,GACT,QAAO,GAAG;GACR,IAAI;GACJ,QAAQ;GACR;GACA,GAAG,UAAU,eAAe,OAAO,kBAAkB;GACrD,GAAG,UAAU,qBAAqB,OAAO,kBAAkB;GAC3D,GAAG,UAAU,uBAAuB,OAAO,oBAAoB;GAC/D,SAAS;GACV,CAAC;AAGJ,MAAI,OAAO,WAAW,SAAS;GAC7B,MAAM,cAAc,MAAM,gBAAgB,IAAI;AAC9C,UAAO,GAAG;IACR,IAAI;IACJ,QAAQ;IACR;IACA;IACA,SAAS,8CAA8C;IACxD,CAAC;;AAGJ,SAAO,MACL,aAAa,sDAAsD;GACjE,KAAK,UAAU,OAAO,kBAAkB,aAAa,OAAO;GAC5D,KAAK;GACL,MAAM;IACJ,mBAAmB,OAAO;IAC1B,qBAAqB,OAAO;IAC7B;GACF,CAAC,CACH;UACM,OAAO;AACd,MAAI,oBAAoB,GAAG,MAAM,CAC/B,QAAO,MACL,aAAa,MAAM,SAAS;GAC1B,KAAK,MAAM;GACX,KAAK,MAAM;GACX,MAAM;IAAE,MAAM,MAAM;IAAM,GAAI,MAAM,WAAW,EAAE;IAAG;GACrD,CAAC,CACH;AAEH,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC3F,CAAC,CACH;;;AAIL,SAAgB,+BAAwC;CACtD,MAAM,UAAU,IAAI,QAAQ,SAAS;AACrC,wBACE,SACA,0CACA,oLAGD;AACD,SACG,cAAc,EACb,aAAa,QAAQ;AAEnB,SAAO,kBAAkB;GAAE,SAAS;GAAK,OADpB,iBAAiB,EAAE,CAAC;GACqB,CAAC;IAElE,CAAC,CACD,eAAe,gBAAgB,0CAA0C,CACzE,OAAO,mBAAmB,2BAA2B,MAAM,CAC3D,OAAO,eAAe,0BAA0B,CAChD,OAAO,iBAAiB,iBAAiB,CACzC,OAAO,gBAAgB,eAAe,CACtC,OAAO,gBAAgB,2BAA2B,CAClD,OAAO,WAAW,qBAAqB,CACvC,OAAO,cAAc,uBAAuB,CAC5C,OAAO,OAAO,YAAoC;EACjD,MAAM,QAAQ,iBAAiB,QAAQ;EAIvC,MAAM,WAAW,aAFF,MAAM,8BAA8B,SAAS,MAAM,EAE5B,QAAQ,iBAAiB;AAC7D,OAAI,MAAM,SAAS,SACjB,SAAQ,IAAI,KAAK,UAAU,cAAc,MAAM,EAAE,CAAC;YACzC,CAAC,MAAM,MAChB,SAAQ,IAAI,mCAAmC,cAAc,MAAM,CAAC;IAEtE;AAEF,UAAQ,KAAK,SAAS;GACtB;AAEJ,QAAO"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { errorConfigFileNotFound, errorConfigValidation, errorUnexpected } from "@prisma-next/core-control-plane/errors";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { ConfigValidationError, validateConfig } from "@prisma-next/config/config-validation";
|
|
4
|
+
import { loadConfig } from "c12";
|
|
5
|
+
|
|
6
|
+
//#region src/config-loader.ts
|
|
7
|
+
/**
|
|
8
|
+
* Loads the Prisma Next config from a TypeScript file.
|
|
9
|
+
* Supports both default export and named export.
|
|
10
|
+
* Uses c12 to automatically handle TypeScript compilation and config file discovery.
|
|
11
|
+
*
|
|
12
|
+
* @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.
|
|
13
|
+
* @returns The loaded config object.
|
|
14
|
+
* @throws Error if config file doesn't exist or is invalid.
|
|
15
|
+
*/
|
|
16
|
+
async function loadConfig$1(configPath) {
|
|
17
|
+
try {
|
|
18
|
+
const cwd = process.cwd();
|
|
19
|
+
const resolvedConfigPath = configPath ? resolve(cwd, configPath) : void 0;
|
|
20
|
+
const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;
|
|
21
|
+
const result = await loadConfig({
|
|
22
|
+
name: "prisma-next",
|
|
23
|
+
...resolvedConfigPath ? { configFile: resolvedConfigPath } : {},
|
|
24
|
+
cwd: configCwd
|
|
25
|
+
});
|
|
26
|
+
if (resolvedConfigPath && result.configFile !== resolvedConfigPath) throw errorConfigFileNotFound(resolvedConfigPath);
|
|
27
|
+
if (!result.config || Object.keys(result.config).length === 0) throw errorConfigFileNotFound(result.configFile || resolvedConfigPath || configPath);
|
|
28
|
+
validateConfig(result.config);
|
|
29
|
+
return result.config;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (error instanceof ConfigValidationError) throw errorConfigValidation(error.field, { why: error.why });
|
|
32
|
+
if (error instanceof Error && "code" in error && typeof error.code === "string") throw error;
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
if (error.message.includes("not found") || error.message.includes("Cannot find") || error.message.includes("ENOENT")) throw errorConfigFileNotFound(configPath ? resolve(process.cwd(), configPath) : void 0, { why: error.message });
|
|
35
|
+
throw errorUnexpected(error.message, { why: `Failed to load config: ${error.message}` });
|
|
36
|
+
}
|
|
37
|
+
throw errorUnexpected(String(error));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
export { loadConfig$1 as t };
|
|
43
|
+
//# sourceMappingURL=config-loader-PPf4CtDj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader-PPf4CtDj.mjs","names":["loadConfig","loadConfigC12"],"sources":["../src/config-loader.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path';\nimport type { PrismaNextConfig } from '@prisma-next/config/config-types';\nimport { ConfigValidationError, validateConfig } from '@prisma-next/config/config-validation';\nimport {\n errorConfigFileNotFound,\n errorConfigValidation,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport { loadConfig as loadConfigC12 } from 'c12';\n\n/**\n * Loads the Prisma Next config from a TypeScript file.\n * Supports both default export and named export.\n * Uses c12 to automatically handle TypeScript compilation and config file discovery.\n *\n * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.\n * @returns The loaded config object.\n * @throws Error if config file doesn't exist or is invalid.\n */\nexport async function loadConfig(configPath?: string): Promise<PrismaNextConfig> {\n try {\n const cwd = process.cwd();\n // Resolve config path to absolute path and set cwd to config directory when path is provided\n const resolvedConfigPath = configPath ? resolve(cwd, configPath) : undefined;\n const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;\n\n const result = await loadConfigC12<PrismaNextConfig>({\n name: 'prisma-next',\n ...(resolvedConfigPath ? { configFile: resolvedConfigPath } : {}),\n cwd: configCwd,\n });\n\n // When a specific config file was requested, verify it was actually loaded\n // (c12 falls back to searching by name if the specified file doesn't exist)\n if (resolvedConfigPath && result.configFile !== resolvedConfigPath) {\n throw errorConfigFileNotFound(resolvedConfigPath);\n }\n\n // Check if config is missing or empty (c12 may return empty object when file doesn't exist)\n if (!result.config || Object.keys(result.config).length === 0) {\n // Use c12's configFile if available, otherwise use explicit configPath, otherwise omit path\n const displayPath = result.configFile || resolvedConfigPath || configPath;\n throw errorConfigFileNotFound(displayPath);\n }\n\n // Validate config structure\n validateConfig(result.config);\n\n return result.config;\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw errorConfigValidation(error.field, {\n why: error.why,\n });\n }\n\n // Re-throw structured errors as-is\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code: string }).code === 'string'\n ) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Check for file not found errors\n if (\n error.message.includes('not found') ||\n error.message.includes('Cannot find') ||\n error.message.includes('ENOENT')\n ) {\n // Use resolved path if available, otherwise use original configPath\n const displayPath = configPath ? resolve(process.cwd(), configPath) : undefined;\n throw errorConfigFileNotFound(displayPath, {\n why: error.message,\n });\n }\n // For other errors, wrap in unexpected error\n throw errorUnexpected(error.message, {\n why: `Failed to load config: ${error.message}`,\n });\n }\n throw errorUnexpected(String(error));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,eAAsBA,aAAW,YAAgD;AAC/E,KAAI;EACF,MAAM,MAAM,QAAQ,KAAK;EAEzB,MAAM,qBAAqB,aAAa,QAAQ,KAAK,WAAW,GAAG;EACnE,MAAM,YAAY,qBAAqB,QAAQ,mBAAmB,GAAG;EAErE,MAAM,SAAS,MAAMC,WAAgC;GACnD,MAAM;GACN,GAAI,qBAAqB,EAAE,YAAY,oBAAoB,GAAG,EAAE;GAChE,KAAK;GACN,CAAC;AAIF,MAAI,sBAAsB,OAAO,eAAe,mBAC9C,OAAM,wBAAwB,mBAAmB;AAInD,MAAI,CAAC,OAAO,UAAU,OAAO,KAAK,OAAO,OAAO,CAAC,WAAW,EAG1D,OAAM,wBADc,OAAO,cAAc,sBAAsB,WACrB;AAI5C,iBAAe,OAAO,OAAO;AAE7B,SAAO,OAAO;UACP,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM,sBAAsB,MAAM,OAAO,EACvC,KAAK,MAAM,KACZ,CAAC;AAIJ,MACE,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAA2B,SAAS,SAE5C,OAAM;AAGR,MAAI,iBAAiB,OAAO;AAE1B,OACE,MAAM,QAAQ,SAAS,YAAY,IACnC,MAAM,QAAQ,SAAS,cAAc,IACrC,MAAM,QAAQ,SAAS,SAAS,CAIhC,OAAM,wBADc,aAAa,QAAQ,QAAQ,KAAK,EAAE,WAAW,GAAG,QAC3B,EACzC,KAAK,MAAM,SACZ,CAAC;AAGJ,SAAM,gBAAgB,MAAM,SAAS,EACnC,KAAK,0BAA0B,MAAM,WACtC,CAAC;;AAEJ,QAAM,gBAAgB,OAAO,MAAM,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { PrismaNextConfig } from "@prisma-next/config/config-types";
|
|
2
|
+
|
|
3
|
+
//#region src/config-loader.d.ts
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
6
|
* Loads the Prisma Next config from a TypeScript file.
|
|
4
7
|
* Supports both default export and named export.
|
|
@@ -8,5 +11,7 @@ import type { PrismaNextConfig } from '@prisma-next/core-control-plane/config-ty
|
|
|
8
11
|
* @returns The loaded config object.
|
|
9
12
|
* @throws Error if config file doesn't exist or is invalid.
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
//#
|
|
14
|
+
declare function loadConfig(configPath?: string): Promise<PrismaNextConfig>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { loadConfig };
|
|
17
|
+
//# sourceMappingURL=config-loader.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.mts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;AAmBA;;;;;;;iBAAsB,UAAA,uBAAiC,QAAQ"}
|