prisma-next 0.12.0-dev.25 → 0.12.0-dev.26
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.mjs +11 -11
- package/dist/{client-BHe8szOW.mjs → client-V7BkIQrQ.mjs} +4 -4
- package/dist/{client-BHe8szOW.mjs.map → client-V7BkIQrQ.mjs.map} +1 -1
- package/dist/{command-helpers-Cmdqyhz9.mjs → command-helpers-DlrUCI7s.mjs} +3 -24
- package/dist/{command-helpers-Cmdqyhz9.mjs.map → command-helpers-DlrUCI7s.mjs.map} +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +4 -4
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.mjs +5 -5
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -1
- package/dist/commands/migrate.mjs +5 -5
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +2 -11
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +8 -35
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +13 -24
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +4 -4
- package/dist/commands/migration-list.mjs.map +1 -1
- package/dist/commands/migration-log.d.mts +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.mjs +3 -3
- package/dist/commands/migration-status.d.mts +24 -142
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +3 -759
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +2 -2
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-Cz0z5PJi.mjs → contract-at-errors-DlZHXSkI.mjs} +2 -2
- package/dist/{contract-at-errors-Cz0z5PJi.mjs.map → contract-at-errors-DlZHXSkI.mjs.map} +1 -1
- package/dist/{contract-emit-DPMij44i.mjs → contract-emit-CaKp92-Q.mjs} +3 -3
- package/dist/{contract-emit-DPMij44i.mjs.map → contract-emit-CaKp92-Q.mjs.map} +1 -1
- package/dist/{contract-emit-CC9jDOmu.mjs → contract-emit-S53EyBRV.mjs} +3 -3
- package/dist/{contract-emit-CC9jDOmu.mjs.map → contract-emit-S53EyBRV.mjs.map} +1 -1
- package/dist/{contract-infer-OCn12Zvn.mjs → contract-infer-Cebb-_Qx.mjs} +3 -3
- package/dist/{contract-infer-OCn12Zvn.mjs.map → contract-infer-Cebb-_Qx.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-CirAEsM8.mjs → contract-space-aggregate-loader-Dvl1SJ4C.mjs} +3 -3
- package/dist/{contract-space-aggregate-loader-CirAEsM8.mjs.map → contract-space-aggregate-loader-Dvl1SJ4C.mjs.map} +1 -1
- package/dist/{db-verify-DJxengYP.mjs → db-verify-B1OoWEWn.mjs} +4 -4
- package/dist/{db-verify-DJxengYP.mjs.map → db-verify-B1OoWEWn.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/{framework-components-DynSvww4.mjs → framework-components-DCAT1uUC.mjs} +2 -2
- package/dist/{framework-components-DynSvww4.mjs.map → framework-components-DCAT1uUC.mjs.map} +1 -1
- package/dist/{init-B6kKrmf7.mjs → init-Kf3T4A4W.mjs} +3 -3
- package/dist/{init-B6kKrmf7.mjs.map → init-Kf3T4A4W.mjs.map} +1 -1
- package/dist/{inspect-live-schema-DVZlDlnF.mjs → inspect-live-schema-DTqflZ8X.mjs} +3 -3
- package/dist/{inspect-live-schema-DVZlDlnF.mjs.map → inspect-live-schema-DTqflZ8X.mjs.map} +1 -1
- package/dist/{migration-check-DzH1u-O1.mjs → migration-check-Ccyd0QKb.mjs} +2 -2
- package/dist/{migration-check-DzH1u-O1.mjs.map → migration-check-Ccyd0QKb.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-Cs7Ky-m5.mjs → migration-command-scaffold-DI7_SFL0.mjs} +3 -3
- package/dist/{migration-command-scaffold-Cs7Ky-m5.mjs.map → migration-command-scaffold-DI7_SFL0.mjs.map} +1 -1
- package/dist/{migration-graph-tree-render-BQdhKBO8.mjs → migration-graph-tree-render-DyDBuJEX.mjs} +25 -2
- package/dist/{migration-graph-tree-render-BQdhKBO8.mjs.map → migration-graph-tree-render-DyDBuJEX.mjs.map} +1 -1
- package/dist/migration-list-types-DV9PBc7Z.d.mts +23 -0
- package/dist/migration-list-types-DV9PBc7Z.d.mts.map +1 -0
- package/dist/{migration-log-BzPmks3c.mjs → migration-log-Des4seHP.mjs} +4 -4
- package/dist/{migration-log-BzPmks3c.mjs.map → migration-log-Des4seHP.mjs.map} +1 -1
- package/dist/{migration-plan-CaeKCKp4.mjs → migration-plan-DxDTBzGS.mjs} +5 -5
- package/dist/{migration-plan-CaeKCKp4.mjs.map → migration-plan-DxDTBzGS.mjs.map} +1 -1
- package/dist/migration-status-CCwqA-vi.mjs +416 -0
- package/dist/migration-status-CCwqA-vi.mjs.map +1 -0
- package/dist/{migrations-DQ1t3XFL.mjs → migrations-B3H6RTXb.mjs} +2 -2
- package/dist/{migrations-DQ1t3XFL.mjs.map → migrations-B3H6RTXb.mjs.map} +1 -1
- package/dist/{telemetry-Q88WHwlv.mjs → telemetry-LFFQmqHd.mjs} +2 -2
- package/dist/{telemetry-Q88WHwlv.mjs.map → telemetry-LFFQmqHd.mjs.map} +1 -1
- package/dist/{types-DiC683UW.d.mts → types-BdS8PoKM.d.mts} +2 -1
- package/dist/types-BdS8PoKM.d.mts.map +1 -0
- package/dist/{verify-CreSJ1Mz.mjs → verify-C0TARc6h.mjs} +2 -2
- package/dist/{verify-CreSJ1Mz.mjs.map → verify-C0TARc6h.mjs.map} +1 -1
- package/package.json +11 -12
- package/dist/commands/migration-status.mjs.map +0 -1
- package/dist/graph-render-rFAqZujX.mjs +0 -1081
- package/dist/graph-render-rFAqZujX.mjs.map +0 -1
- package/dist/types-DiC683UW.d.mts.map +0 -1
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
import { A as CliStructuredError, F as errorDatabaseConnectionRequired, T as formatStyledHeader, _ as createTerminalUI, a as readContractEnvelope, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, i as maskConnectionUrl, l as setCommandDescriptions, n as collectDeclaredInvariants, nt as mapMigrationToolsError, p as toStructuralEdge, rt as mapRefResolutionError, s as resolveMigrationPaths, t as addGlobalOptions, tt as errorUnexpected, u as setCommandExamples, y as handleResult } from "./command-helpers-DlrUCI7s.mjs";
|
|
3
|
+
import { t as createControlClient } from "./client-V7BkIQrQ.mjs";
|
|
4
|
+
import { n as buildReadAggregate, o as refusePackageCorruptionOnAggregate, r as loadContractRawSafely } from "./contract-space-aggregate-loader-Dvl1SJ4C.mjs";
|
|
5
|
+
import { c as buildMigrationGraphLayout, n as renderMigrationGraphTree, s as buildMigrationGraphRows } from "./migration-graph-tree-render-DyDBuJEX.mjs";
|
|
6
|
+
import { listRefsByContractHash, migrationSpaceListEntriesFromAggregate, runMigrationList } from "./commands/migration-list.mjs";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
9
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
10
|
+
import { dim, yellow } from "colorette";
|
|
11
|
+
import { requireHeadRef } from "@prisma-next/migration-tools/aggregate";
|
|
12
|
+
import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
|
|
13
|
+
import { MigrationToolsError, errorNoInvariantPath, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
|
|
14
|
+
import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/migration-graph";
|
|
15
|
+
import { readRefs } from "@prisma-next/migration-tools/refs";
|
|
16
|
+
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
17
|
+
//#region src/commands/migration-status-overlay.ts
|
|
18
|
+
function deriveStatusEdgeAnnotations(input) {
|
|
19
|
+
const annotations = /* @__PURE__ */ new Map();
|
|
20
|
+
if (input.showAppliedOverlay) {
|
|
21
|
+
for (const edge of input.graph.migrationByHash.values()) if (input.appliedMigrationHashes.has(edge.migrationHash)) annotations.set(edge.migrationHash, { status: "applied" });
|
|
22
|
+
}
|
|
23
|
+
if (!input.graph.nodes.has(input.originHash)) return annotations;
|
|
24
|
+
const pendingPath = findPath(input.graph, input.originHash, input.targetHash);
|
|
25
|
+
if (!pendingPath) return annotations;
|
|
26
|
+
for (const edge of pendingPath) {
|
|
27
|
+
if (input.appliedMigrationHashes.has(edge.migrationHash)) continue;
|
|
28
|
+
if (annotations.get(edge.migrationHash)?.status === "applied") continue;
|
|
29
|
+
annotations.set(edge.migrationHash, { status: "pending" });
|
|
30
|
+
}
|
|
31
|
+
return annotations;
|
|
32
|
+
}
|
|
33
|
+
function appliedHashesFromLedger(ledgerEntries) {
|
|
34
|
+
return new Set(ledgerEntries.map((entry) => entry.migrationHash));
|
|
35
|
+
}
|
|
36
|
+
function statusForMigrationHash(migrationHash, annotations) {
|
|
37
|
+
return annotations.get(migrationHash)?.status ?? null;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/commands/migration-status.ts
|
|
41
|
+
function shortDisplayHash(hash) {
|
|
42
|
+
return (hash.startsWith("sha256:") ? hash.slice(7) : hash).slice(0, 12);
|
|
43
|
+
}
|
|
44
|
+
function resolveTargetHashForSpace(member, contractHash, activeRefHash) {
|
|
45
|
+
const graph = member.graph();
|
|
46
|
+
if (activeRefHash !== void 0 && graph.nodes.has(activeRefHash)) return activeRefHash;
|
|
47
|
+
if (graph.nodes.has(contractHash)) return contractHash;
|
|
48
|
+
if (graph.nodes.size === 0) return requireHeadRef(member).hash;
|
|
49
|
+
const leaves = findReachableLeaves(graph, EMPTY_CONTRACT_HASH);
|
|
50
|
+
if (leaves.length === 1) return leaves[0];
|
|
51
|
+
}
|
|
52
|
+
function buildStatusMigrations(listMigrations, annotations) {
|
|
53
|
+
return listMigrations.map((migration) => ({
|
|
54
|
+
...migration,
|
|
55
|
+
status: statusForMigrationHash(migration.migrationHash, annotations)
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
function renderSpaceTree(args) {
|
|
59
|
+
const graph = args.member.graph();
|
|
60
|
+
if (graph.nodes.size === 0) return "";
|
|
61
|
+
const refsByHash = listRefsByContractHash(args.member);
|
|
62
|
+
return renderMigrationGraphTree(buildMigrationGraphLayout(buildMigrationGraphRows(graph, { contractHash: args.contractHash })), {
|
|
63
|
+
refsByHash,
|
|
64
|
+
...args.showDbMarker && args.markerHash !== void 0 ? { dbHash: args.markerHash } : {},
|
|
65
|
+
contractHash: args.contractHash,
|
|
66
|
+
edgeAnnotationsByHash: args.edgeAnnotations,
|
|
67
|
+
colorize: args.colorize,
|
|
68
|
+
glyphMode: args.glyphMode
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function countPending(migrations) {
|
|
72
|
+
return migrations.filter((m) => m.status === "pending").length;
|
|
73
|
+
}
|
|
74
|
+
function buildStatusHeadline(args) {
|
|
75
|
+
if (args.markerDiverged && args.markerHash !== void 0) return `Database marker ${shortDisplayHash(args.markerHash)} is not in the on-disk migration graph`;
|
|
76
|
+
if (args.pendingCount === 0) return "up to date";
|
|
77
|
+
return `${args.pendingCount} pending — run \`prisma-next migrate --to ${shortDisplayHash(args.targetHash)}\``;
|
|
78
|
+
}
|
|
79
|
+
function formatStatusSummary(result, colorize) {
|
|
80
|
+
const c = (fn, s) => colorize ? fn(s) : s;
|
|
81
|
+
const lines = [];
|
|
82
|
+
const pendingTotal = result.spaces.reduce((sum, space) => sum + countPending(space.migrations), 0);
|
|
83
|
+
if (result.diagnostics.some((d) => d.code === "MIGRATION.MARKER_NOT_IN_HISTORY") || pendingTotal > 0) lines.push(c(yellow, result.summary));
|
|
84
|
+
else lines.push(result.summary);
|
|
85
|
+
if (result.missingInvariantsLine !== void 0) lines.push(c(dim, result.missingInvariantsLine));
|
|
86
|
+
return lines.join("\n");
|
|
87
|
+
}
|
|
88
|
+
function formatStatusHumanOutput(result, colorize) {
|
|
89
|
+
const sections = [];
|
|
90
|
+
for (const section of result.treeSections) {
|
|
91
|
+
if (section.showHeading) sections.push(`${section.spaceId}:`);
|
|
92
|
+
if (section.tree.length > 0) sections.push(section.tree);
|
|
93
|
+
else sections.push("(no migrations)");
|
|
94
|
+
sections.push("");
|
|
95
|
+
}
|
|
96
|
+
sections.push(formatStatusSummary(result, colorize));
|
|
97
|
+
return sections.join("\n").trimEnd();
|
|
98
|
+
}
|
|
99
|
+
async function readMarkersAndLedgers(args) {
|
|
100
|
+
const markersBySpace = /* @__PURE__ */ new Map();
|
|
101
|
+
const all = await args.client.readAllMarkers();
|
|
102
|
+
for (const [spaceId, marker] of all) markersBySpace.set(spaceId, marker);
|
|
103
|
+
const ledgersBySpace = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const spaceId of args.spaceIds) ledgersBySpace.set(spaceId, await args.client.readLedger(spaceId));
|
|
105
|
+
return {
|
|
106
|
+
markersBySpace,
|
|
107
|
+
ledgersBySpace
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async function executeMigrationStatusCommand(options, flags, ui) {
|
|
111
|
+
const config = await loadConfig(options.config);
|
|
112
|
+
const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
|
|
113
|
+
const dbConnection = options.db ?? config.db?.connection;
|
|
114
|
+
const hasDriver = !!config.driver;
|
|
115
|
+
const usingFromOverride = options.from !== void 0;
|
|
116
|
+
if (!usingFromOverride && (!dbConnection || !hasDriver)) return notOk(errorDatabaseConnectionRequired({
|
|
117
|
+
why: "migration status needs a database connection to read the marker and ledger (or pass --from for offline path preview)",
|
|
118
|
+
retryCommand: "prisma-next migration status --from <contract>"
|
|
119
|
+
}));
|
|
120
|
+
let allRefs = {};
|
|
121
|
+
try {
|
|
122
|
+
allRefs = await readRefs(refsDir);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
const diagnostics = [];
|
|
128
|
+
let contractHash = EMPTY_CONTRACT_HASH;
|
|
129
|
+
try {
|
|
130
|
+
contractHash = (await readContractEnvelope(config)).storageHash;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
diagnostics.push({
|
|
133
|
+
code: "CONTRACT.UNREADABLE",
|
|
134
|
+
severity: "warn",
|
|
135
|
+
message: `Could not read contract: ${error instanceof Error ? error.message : "unknown error"}`,
|
|
136
|
+
hints: ["Run 'prisma-next contract emit' to generate a valid contract"]
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const loaded = await buildReadAggregate(config, { migrationsDir });
|
|
140
|
+
if (!loaded.ok) return notOk(loaded.failure);
|
|
141
|
+
const { aggregate } = loaded.value;
|
|
142
|
+
if (await loadContractRawSafely(config) !== null) {
|
|
143
|
+
const corruptionFailure = refusePackageCorruptionOnAggregate(aggregate);
|
|
144
|
+
if (corruptionFailure) return notOk(corruptionFailure);
|
|
145
|
+
}
|
|
146
|
+
const appGraph = aggregate.app.graph();
|
|
147
|
+
let activeRefHash;
|
|
148
|
+
let activeRefName;
|
|
149
|
+
let activeRefEntry;
|
|
150
|
+
let fromOverrideHash;
|
|
151
|
+
if (options.to) {
|
|
152
|
+
const refResult = parseContractRef(options.to, {
|
|
153
|
+
graph: appGraph,
|
|
154
|
+
refs: allRefs
|
|
155
|
+
});
|
|
156
|
+
if (!refResult.ok) return notOk(mapRefResolutionError(refResult.failure));
|
|
157
|
+
activeRefHash = refResult.value.hash;
|
|
158
|
+
if (refResult.value.provenance.kind === "ref") {
|
|
159
|
+
activeRefName = refResult.value.provenance.refName;
|
|
160
|
+
activeRefEntry = allRefs[activeRefName];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (options.from) {
|
|
164
|
+
const fromResult = parseContractRef(options.from, {
|
|
165
|
+
graph: appGraph,
|
|
166
|
+
refs: allRefs
|
|
167
|
+
});
|
|
168
|
+
if (!fromResult.ok) return notOk(mapRefResolutionError(fromResult.failure));
|
|
169
|
+
fromOverrideHash = fromResult.value.hash;
|
|
170
|
+
}
|
|
171
|
+
const requiredInvariants = [...activeRefEntry?.invariants ?? []].sort();
|
|
172
|
+
if (!flags.json && !flags.quiet) {
|
|
173
|
+
const details = [{
|
|
174
|
+
label: "config",
|
|
175
|
+
value: configPath
|
|
176
|
+
}, {
|
|
177
|
+
label: "migrations",
|
|
178
|
+
value: migrationsRelative
|
|
179
|
+
}];
|
|
180
|
+
if (dbConnection && hasDriver) details.push({
|
|
181
|
+
label: "database",
|
|
182
|
+
value: maskConnectionUrl(String(dbConnection))
|
|
183
|
+
});
|
|
184
|
+
if (activeRefName) details.push({
|
|
185
|
+
label: "ref",
|
|
186
|
+
value: activeRefName
|
|
187
|
+
});
|
|
188
|
+
if (options.from) details.push({
|
|
189
|
+
label: "from",
|
|
190
|
+
value: options.from
|
|
191
|
+
});
|
|
192
|
+
if (options.space) details.push({
|
|
193
|
+
label: "space",
|
|
194
|
+
value: options.space
|
|
195
|
+
});
|
|
196
|
+
const header = formatStyledHeader({
|
|
197
|
+
command: "migration status",
|
|
198
|
+
description: "Show migration history and applied status",
|
|
199
|
+
details,
|
|
200
|
+
flags
|
|
201
|
+
});
|
|
202
|
+
ui.stderr(header);
|
|
203
|
+
}
|
|
204
|
+
const listResult = runMigrationList({
|
|
205
|
+
spaces: await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir),
|
|
206
|
+
...ifDefined("spaceFilter", options.space)
|
|
207
|
+
});
|
|
208
|
+
if (!listResult.ok) return listResult;
|
|
209
|
+
const scopedSpaces = listResult.value.spaces;
|
|
210
|
+
const showSpaceHeadings = scopedSpaces.length > 1;
|
|
211
|
+
let markersBySpace = /* @__PURE__ */ new Map();
|
|
212
|
+
let ledgersBySpace = /* @__PURE__ */ new Map();
|
|
213
|
+
let connected = false;
|
|
214
|
+
if (dbConnection && hasDriver && !usingFromOverride) {
|
|
215
|
+
const client = createControlClient({
|
|
216
|
+
family: config.family,
|
|
217
|
+
target: config.target,
|
|
218
|
+
adapter: config.adapter,
|
|
219
|
+
driver: config.driver,
|
|
220
|
+
extensionPacks: config.extensionPacks ?? []
|
|
221
|
+
});
|
|
222
|
+
try {
|
|
223
|
+
await client.connect(dbConnection);
|
|
224
|
+
connected = true;
|
|
225
|
+
const read = await readMarkersAndLedgers({
|
|
226
|
+
client,
|
|
227
|
+
spaceIds: scopedSpaces.map((s) => s.spaceId)
|
|
228
|
+
});
|
|
229
|
+
markersBySpace = new Map(read.markersBySpace);
|
|
230
|
+
ledgersBySpace = new Map(read.ledgersBySpace);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
233
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read database state: ${error instanceof Error ? error.message : String(error)}` }));
|
|
234
|
+
} finally {
|
|
235
|
+
await client.close();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (activeRefEntry && activeRefEntry.invariants.length > 0 && connected) {
|
|
239
|
+
const declared = collectDeclaredInvariants(appGraph);
|
|
240
|
+
const markerInvariants = markersBySpace.get(aggregate.app.spaceId)?.invariants ?? [];
|
|
241
|
+
const known = new Set(declared);
|
|
242
|
+
for (const id of markerInvariants) known.add(id);
|
|
243
|
+
const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));
|
|
244
|
+
if (unknown.length > 0) return notOk(mapMigrationToolsError(errorUnknownInvariant({
|
|
245
|
+
...ifDefined("refName", activeRefName),
|
|
246
|
+
unknown,
|
|
247
|
+
declared: [...declared].sort()
|
|
248
|
+
})));
|
|
249
|
+
}
|
|
250
|
+
const showAppliedOverlay = connected && !usingFromOverride;
|
|
251
|
+
const showDbMarker = connected && !usingFromOverride;
|
|
252
|
+
const glyphMode = ui.resolveGlyphMode(false);
|
|
253
|
+
const colorize = flags.color !== false;
|
|
254
|
+
const statusSpaces = [];
|
|
255
|
+
const treeSections = [];
|
|
256
|
+
let markerDiverged = false;
|
|
257
|
+
let markerCannotReachTarget = false;
|
|
258
|
+
let headlineTargetHash = activeRefHash ?? contractHash;
|
|
259
|
+
let totalPending = 0;
|
|
260
|
+
let hasAmbiguousTarget = false;
|
|
261
|
+
for (const spaceEntry of scopedSpaces) {
|
|
262
|
+
const member = aggregate.space(spaceEntry.spaceId);
|
|
263
|
+
if (member === void 0) continue;
|
|
264
|
+
const graph = member.graph();
|
|
265
|
+
const spaceContractHash = member.contract().storage.storageHash;
|
|
266
|
+
const targetHash = resolveTargetHashForSpace(member, spaceContractHash, activeRefHash);
|
|
267
|
+
if (targetHash === void 0) {
|
|
268
|
+
hasAmbiguousTarget = true;
|
|
269
|
+
diagnostics.push({
|
|
270
|
+
code: "MIGRATION.DIVERGED",
|
|
271
|
+
severity: "warn",
|
|
272
|
+
message: "There are multiple valid migration paths — you must select a target",
|
|
273
|
+
hints: ["Use '--to <contract>' to select a target", "Or 'prisma-next ref set <name> <hash>' to create one"]
|
|
274
|
+
});
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (spaceEntry.spaceId === aggregate.app.spaceId) headlineTargetHash = targetHash;
|
|
278
|
+
const markerRecord = markersBySpace.get(spaceEntry.spaceId);
|
|
279
|
+
const markerHash = usingFromOverride ? fromOverrideHash : markerRecord?.storageHash ?? void 0;
|
|
280
|
+
const originHash = markerHash ?? EMPTY_CONTRACT_HASH;
|
|
281
|
+
const markerInGraph = markerHash === void 0 || graph.nodes.has(markerHash) || markerHash === spaceContractHash;
|
|
282
|
+
if (connected && !usingFromOverride && markerHash !== void 0 && markerInGraph && markerHash !== targetHash && findPath(graph, originHash, targetHash) === null) markerCannotReachTarget = true;
|
|
283
|
+
if (connected && !usingFromOverride && markerHash !== void 0 && !markerInGraph) {
|
|
284
|
+
markerDiverged = true;
|
|
285
|
+
diagnostics.push({
|
|
286
|
+
code: "MIGRATION.MARKER_NOT_IN_HISTORY",
|
|
287
|
+
severity: "warn",
|
|
288
|
+
message: "Database was updated outside the migration system (marker does not match any migration)",
|
|
289
|
+
hints: ["Run 'prisma-next db sign' to overwrite the marker if the database already matches the contract", "Run 'prisma-next db update' to push the current contract to the database"]
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const ledger = ledgersBySpace.get(spaceEntry.spaceId) ?? [];
|
|
293
|
+
const annotations = deriveStatusEdgeAnnotations({
|
|
294
|
+
graph,
|
|
295
|
+
targetHash,
|
|
296
|
+
originHash,
|
|
297
|
+
appliedMigrationHashes: showAppliedOverlay ? appliedHashesFromLedger(ledger) : /* @__PURE__ */ new Set(),
|
|
298
|
+
showAppliedOverlay
|
|
299
|
+
});
|
|
300
|
+
const tree = renderSpaceTree({
|
|
301
|
+
member,
|
|
302
|
+
contractHash: spaceContractHash,
|
|
303
|
+
markerHash,
|
|
304
|
+
showDbMarker,
|
|
305
|
+
targetHash,
|
|
306
|
+
edgeAnnotations: annotations,
|
|
307
|
+
colorize,
|
|
308
|
+
glyphMode
|
|
309
|
+
});
|
|
310
|
+
const migrations = buildStatusMigrations(spaceEntry.migrations, annotations);
|
|
311
|
+
const pending = countPending(migrations);
|
|
312
|
+
totalPending += pending;
|
|
313
|
+
statusSpaces.push({
|
|
314
|
+
spaceId: spaceEntry.spaceId,
|
|
315
|
+
markerHash: markerHash ?? null,
|
|
316
|
+
targetHash,
|
|
317
|
+
migrations
|
|
318
|
+
});
|
|
319
|
+
treeSections.push({
|
|
320
|
+
spaceId: spaceEntry.spaceId,
|
|
321
|
+
tree,
|
|
322
|
+
showHeading: showSpaceHeadings
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
let missingInvariantsLine;
|
|
326
|
+
if (connected && requiredInvariants.length > 0) {
|
|
327
|
+
const markerInvariants = markersBySpace.get(aggregate.app.spaceId)?.invariants ?? [];
|
|
328
|
+
const markerSet = new Set(markerInvariants);
|
|
329
|
+
const missing = requiredInvariants.filter((id) => !markerSet.has(id));
|
|
330
|
+
if (missing.length > 0) {
|
|
331
|
+
missingInvariantsLine = `missing invariant(s): ${missing.join(", ")}`;
|
|
332
|
+
if (activeRefHash !== void 0) {
|
|
333
|
+
const outcome = findPathWithDecision(appGraph, markersBySpace.get(aggregate.app.spaceId)?.storageHash ?? EMPTY_CONTRACT_HASH, activeRefHash, {
|
|
334
|
+
...ifDefined("refName", activeRefName),
|
|
335
|
+
required: new Set(missing)
|
|
336
|
+
});
|
|
337
|
+
if (outcome.kind === "unsatisfiable") return notOk(mapMigrationToolsError(errorNoInvariantPath({
|
|
338
|
+
...ifDefined("refName", activeRefName),
|
|
339
|
+
required: [...missing].sort(),
|
|
340
|
+
missing: outcome.missing,
|
|
341
|
+
structuralPath: outcome.structuralPath.map(toStructuralEdge)
|
|
342
|
+
})));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const appMarkerHash = markersBySpace.get(aggregate.app.spaceId)?.storageHash;
|
|
347
|
+
const summary = hasAmbiguousTarget ? "Multiple valid migration paths — select a target with --to" : markerCannotReachTarget ? "Database marker cannot reach the selected target" : buildStatusHeadline({
|
|
348
|
+
pendingCount: totalPending,
|
|
349
|
+
targetHash: headlineTargetHash,
|
|
350
|
+
markerDiverged,
|
|
351
|
+
markerHash: appMarkerHash
|
|
352
|
+
});
|
|
353
|
+
if (scopedSpaces.every((s) => s.migrations.length === 0)) return ok({
|
|
354
|
+
ok: true,
|
|
355
|
+
spaces: statusSpaces,
|
|
356
|
+
summary: "No migrations found",
|
|
357
|
+
diagnostics,
|
|
358
|
+
treeSections,
|
|
359
|
+
...ifDefined("missingInvariantsLine", missingInvariantsLine)
|
|
360
|
+
});
|
|
361
|
+
return ok({
|
|
362
|
+
ok: true,
|
|
363
|
+
spaces: statusSpaces,
|
|
364
|
+
summary,
|
|
365
|
+
diagnostics,
|
|
366
|
+
treeSections,
|
|
367
|
+
...ifDefined("missingInvariantsLine", missingInvariantsLine)
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function createMigrationStatusCommand() {
|
|
371
|
+
const command = new Command("status");
|
|
372
|
+
setCommandDescriptions(command, "Show migration path and pending status", "Shows which migrations are pending between the database marker and\nthe target contract. Requires a database connection for live status.\nUse `migration graph` for topology, `migration log` for history,\nand `migration list` for on-disk enumeration.");
|
|
373
|
+
setCommandExamples(command, [
|
|
374
|
+
"prisma-next migration status --db $DATABASE_URL",
|
|
375
|
+
"prisma-next migration status --to production --db $DATABASE_URL",
|
|
376
|
+
"prisma-next migration status --from sha256:abc --to production"
|
|
377
|
+
]);
|
|
378
|
+
setCommandSeeAlso(command, [
|
|
379
|
+
{
|
|
380
|
+
verb: "migration log",
|
|
381
|
+
oneLiner: "Show executed migration history"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
verb: "migration list",
|
|
385
|
+
oneLiner: "List on-disk migrations"
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
verb: "migration graph",
|
|
389
|
+
oneLiner: "Show the migration graph topology"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
verb: "migration show",
|
|
393
|
+
oneLiner: "Display migration package contents"
|
|
394
|
+
}
|
|
395
|
+
]);
|
|
396
|
+
addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--space <id>", "Narrow output to a single contract space").option("--to <contract>", "Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)").option("--from <contract>", "Origin contract reference; same grammar as --to. Supplying --from switches to offline path computation.").action(async (options) => {
|
|
397
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
398
|
+
const ui = createTerminalUI(flags);
|
|
399
|
+
const exitCode = handleResult(await executeMigrationStatusCommand(options, flags, ui), flags, ui, (statusResult) => {
|
|
400
|
+
if (flags.json) ui.output(JSON.stringify({
|
|
401
|
+
ok: true,
|
|
402
|
+
spaces: statusResult.spaces,
|
|
403
|
+
summary: statusResult.summary,
|
|
404
|
+
...statusResult.diagnostics.length > 0 ? { diagnostics: statusResult.diagnostics } : {},
|
|
405
|
+
...statusResult.missingInvariantsLine ? { missingInvariants: statusResult.missingInvariantsLine } : {}
|
|
406
|
+
}, null, 2));
|
|
407
|
+
else if (!flags.quiet) ui.output(formatStatusHumanOutput(statusResult, flags.color !== false));
|
|
408
|
+
});
|
|
409
|
+
process.exit(exitCode);
|
|
410
|
+
});
|
|
411
|
+
return command;
|
|
412
|
+
}
|
|
413
|
+
//#endregion
|
|
414
|
+
export { formatStatusSummary as i, createMigrationStatusCommand as n, formatStatusHumanOutput as r, buildStatusHeadline as t };
|
|
415
|
+
|
|
416
|
+
//# sourceMappingURL=migration-status-CCwqA-vi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-status-CCwqA-vi.mjs","names":[],"sources":["../src/commands/migration-status-overlay.ts","../src/commands/migration-status.ts"],"sourcesContent":["import type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport { findPath } from '@prisma-next/migration-tools/migration-graph';\nimport type { MigrationEdgeAnnotation } from '../utils/formatters/migration-graph-tree-render';\n\nexport interface DeriveStatusEdgeAnnotationsInput {\n readonly graph: MigrationGraph;\n readonly targetHash: string;\n readonly originHash: string;\n readonly appliedMigrationHashes: ReadonlySet<string>;\n readonly showAppliedOverlay: boolean;\n}\n\nexport function deriveStatusEdgeAnnotations(\n input: DeriveStatusEdgeAnnotationsInput,\n): ReadonlyMap<string, MigrationEdgeAnnotation> {\n const annotations = new Map<string, MigrationEdgeAnnotation>();\n\n if (input.showAppliedOverlay) {\n for (const edge of input.graph.migrationByHash.values()) {\n if (input.appliedMigrationHashes.has(edge.migrationHash)) {\n annotations.set(edge.migrationHash, { status: 'applied' });\n }\n }\n }\n\n if (!input.graph.nodes.has(input.originHash)) {\n return annotations;\n }\n\n const pendingPath = findPath(input.graph, input.originHash, input.targetHash);\n if (!pendingPath) {\n return annotations;\n }\n\n for (const edge of pendingPath) {\n if (input.appliedMigrationHashes.has(edge.migrationHash)) {\n continue;\n }\n const existing = annotations.get(edge.migrationHash);\n if (existing?.status === 'applied') {\n continue;\n }\n annotations.set(edge.migrationHash, { status: 'pending' });\n }\n\n return annotations;\n}\n\nexport function appliedHashesFromLedger(\n ledgerEntries: ReadonlyArray<{ readonly migrationHash: string }>,\n): ReadonlySet<string> {\n return new Set(ledgerEntries.map((entry) => entry.migrationHash));\n}\n\nexport function statusForMigrationHash(\n migrationHash: string,\n annotations: ReadonlyMap<string, MigrationEdgeAnnotation>,\n): 'applied' | 'pending' | null {\n const status = annotations.get(migrationHash)?.status;\n return status ?? null;\n}\n","import type { LedgerEntryRecord } from '@prisma-next/contract/types';\nimport type {\n ContractMarkerRecordLike,\n ContractSpaceMember,\n} from '@prisma-next/migration-tools/aggregate';\nimport { requireHeadRef } from '@prisma-next/migration-tools/aggregate';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport {\n errorNoInvariantPath,\n errorUnknownInvariant,\n MigrationToolsError,\n} from '@prisma-next/migration-tools/errors';\nimport {\n findPath,\n findPathWithDecision,\n findReachableLeaves,\n} from '@prisma-next/migration-tools/migration-graph';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport type { RefEntry, Refs } from '@prisma-next/migration-tools/refs';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { dim, yellow } from 'colorette';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorDatabaseConnectionRequired,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n collectDeclaredInvariants,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n toStructuralEdge,\n} from '../utils/command-helpers';\nimport {\n buildReadAggregate,\n loadContractRawSafely,\n refusePackageCorruptionOnAggregate,\n} from '../utils/contract-space-aggregate-loader';\nimport { buildMigrationGraphLayout } from '../utils/formatters/migration-graph-layout';\nimport { buildMigrationGraphRows } from '../utils/formatters/migration-graph-rows';\nimport {\n type MigrationEdgeAnnotation,\n renderMigrationGraphTree,\n} from '../utils/formatters/migration-graph-tree-render';\nimport type { MigrationListEntry } from '../utils/formatters/migration-list-types';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport type { StatusDiagnostic } from '../utils/migration-types';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\nimport {\n listRefsByContractHash,\n migrationSpaceListEntriesFromAggregate,\n runMigrationList,\n} from './migration-list';\nimport {\n appliedHashesFromLedger,\n deriveStatusEdgeAnnotations,\n statusForMigrationHash,\n} from './migration-status-overlay';\n\ninterface MigrationStatusOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly to?: string;\n readonly from?: string;\n readonly space?: string;\n}\n\nexport interface MigrationStatusMigrationEntry extends MigrationListEntry {\n readonly status: 'applied' | 'pending' | null;\n}\n\nexport interface MigrationStatusSpaceResult {\n readonly spaceId: string;\n readonly markerHash: string | null;\n readonly targetHash: string;\n readonly migrations: readonly MigrationStatusMigrationEntry[];\n}\n\nexport interface MigrationStatusResult {\n readonly ok: true;\n readonly spaces: readonly MigrationStatusSpaceResult[];\n readonly summary: string;\n readonly missingInvariantsLine?: string;\n readonly diagnostics: readonly StatusDiagnostic[];\n readonly treeSections: readonly MigrationStatusTreeSection[];\n}\n\nexport interface MigrationStatusTreeSection {\n readonly spaceId: string;\n readonly tree: string;\n readonly showHeading: boolean;\n}\n\nexport type { StatusDiagnostic, StatusRef } from '../utils/migration-types';\n\nfunction shortDisplayHash(hash: string): string {\n const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;\n return stripped.slice(0, 12);\n}\n\nfunction resolveTargetHashForSpace(\n member: ContractSpaceMember,\n contractHash: string,\n activeRefHash: string | undefined,\n): string | undefined {\n const graph = member.graph();\n if (activeRefHash !== undefined && graph.nodes.has(activeRefHash)) {\n return activeRefHash;\n }\n if (graph.nodes.has(contractHash)) {\n return contractHash;\n }\n if (graph.nodes.size === 0) {\n return requireHeadRef(member).hash;\n }\n const leaves = findReachableLeaves(graph, EMPTY_CONTRACT_HASH);\n if (leaves.length === 1) {\n return leaves[0];\n }\n return undefined;\n}\n\nfunction buildStatusMigrations(\n listMigrations: readonly MigrationListEntry[],\n annotations: ReadonlyMap<string, MigrationEdgeAnnotation>,\n): readonly MigrationStatusMigrationEntry[] {\n return listMigrations.map((migration) => ({\n ...migration,\n status: statusForMigrationHash(migration.migrationHash, annotations),\n }));\n}\n\nfunction renderSpaceTree(args: {\n readonly member: ContractSpaceMember;\n readonly contractHash: string;\n readonly markerHash: string | undefined;\n readonly showDbMarker: boolean;\n readonly targetHash: string;\n readonly edgeAnnotations: ReadonlyMap<string, MigrationEdgeAnnotation>;\n readonly colorize: boolean;\n readonly glyphMode: 'unicode' | 'ascii';\n}): string {\n const graph = args.member.graph();\n if (graph.nodes.size === 0) {\n return '';\n }\n const refsByHash = listRefsByContractHash(args.member);\n const rowModel = buildMigrationGraphRows(graph, { contractHash: args.contractHash });\n const layout = buildMigrationGraphLayout(rowModel);\n return renderMigrationGraphTree(layout, {\n refsByHash,\n ...(args.showDbMarker && args.markerHash !== undefined ? { dbHash: args.markerHash } : {}),\n contractHash: args.contractHash,\n edgeAnnotationsByHash: args.edgeAnnotations,\n colorize: args.colorize,\n glyphMode: args.glyphMode,\n });\n}\n\nfunction countPending(migrations: readonly MigrationStatusMigrationEntry[]): number {\n return migrations.filter((m) => m.status === 'pending').length;\n}\n\nexport function buildStatusHeadline(args: {\n readonly pendingCount: number;\n readonly targetHash: string;\n readonly markerDiverged: boolean;\n readonly markerHash: string | undefined;\n}): string {\n if (args.markerDiverged && args.markerHash !== undefined) {\n return `Database marker ${shortDisplayHash(args.markerHash)} is not in the on-disk migration graph`;\n }\n if (args.pendingCount === 0) {\n return 'up to date';\n }\n return `${args.pendingCount} pending — run \\`prisma-next migrate --to ${shortDisplayHash(args.targetHash)}\\``;\n}\n\nexport function formatStatusSummary(result: MigrationStatusResult, colorize: boolean): string {\n const c = (fn: (s: string) => string, s: string) => (colorize ? fn(s) : s);\n const lines: string[] = [];\n const pendingTotal = result.spaces.reduce(\n (sum, space) => sum + countPending(space.migrations),\n 0,\n );\n const hasDivergence = result.diagnostics.some(\n (d) => d.code === 'MIGRATION.MARKER_NOT_IN_HISTORY',\n );\n if (hasDivergence || pendingTotal > 0) {\n lines.push(c(yellow, result.summary));\n } else {\n lines.push(result.summary);\n }\n if (result.missingInvariantsLine !== undefined) {\n lines.push(c(dim, result.missingInvariantsLine));\n }\n return lines.join('\\n');\n}\n\nexport function formatStatusHumanOutput(result: MigrationStatusResult, colorize: boolean): string {\n const sections: string[] = [];\n for (const section of result.treeSections) {\n if (section.showHeading) {\n sections.push(`${section.spaceId}:`);\n }\n if (section.tree.length > 0) {\n sections.push(section.tree);\n } else {\n sections.push('(no migrations)');\n }\n sections.push('');\n }\n sections.push(formatStatusSummary(result, colorize));\n return sections.join('\\n').trimEnd();\n}\n\nasync function readMarkersAndLedgers(args: {\n readonly client: ReturnType<typeof createControlClient>;\n readonly spaceIds: readonly string[];\n}): Promise<{\n readonly markersBySpace: ReadonlyMap<string, ContractMarkerRecordLike>;\n readonly ledgersBySpace: ReadonlyMap<string, readonly LedgerEntryRecord[]>;\n}> {\n const markersBySpace = new Map<string, ContractMarkerRecordLike>();\n const all = await args.client.readAllMarkers();\n for (const [spaceId, marker] of all) {\n markersBySpace.set(spaceId, marker);\n }\n const ledgersBySpace = new Map<string, readonly LedgerEntryRecord[]>();\n for (const spaceId of args.spaceIds) {\n ledgersBySpace.set(spaceId, await args.client.readLedger(spaceId));\n }\n return { markersBySpace, ledgersBySpace };\n}\n\nasync function executeMigrationStatusCommand(\n options: MigrationStatusOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationStatusResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const dbConnection = options.db ?? config.db?.connection;\n const hasDriver = !!config.driver;\n const usingFromOverride = options.from !== undefined;\n\n if (!usingFromOverride && (!dbConnection || !hasDriver)) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: 'migration status needs a database connection to read the marker and ledger (or pass --from for offline path preview)',\n retryCommand: 'prisma-next migration status --from <contract>',\n }),\n );\n }\n\n let allRefs: Refs = {};\n try {\n allRefs = await readRefs(refsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n const diagnostics: StatusDiagnostic[] = [];\n let contractHash: string = EMPTY_CONTRACT_HASH;\n try {\n const envelope = await readContractEnvelope(config);\n contractHash = envelope.storageHash;\n } catch (error) {\n diagnostics.push({\n code: 'CONTRACT.UNREADABLE',\n severity: 'warn',\n message: `Could not read contract: ${error instanceof Error ? error.message : 'unknown error'}`,\n hints: [\"Run 'prisma-next contract emit' to generate a valid contract\"],\n });\n }\n\n const loaded = await buildReadAggregate(config, { migrationsDir });\n if (!loaded.ok) {\n return notOk(loaded.failure);\n }\n\n const { aggregate } = loaded.value;\n const contractRawForAggregate = await loadContractRawSafely(config);\n if (contractRawForAggregate !== null) {\n const corruptionFailure = refusePackageCorruptionOnAggregate(aggregate);\n if (corruptionFailure) {\n return notOk(corruptionFailure);\n }\n }\n const appGraph = aggregate.app.graph();\n\n let activeRefHash: string | undefined;\n let activeRefName: string | undefined;\n let activeRefEntry: RefEntry | undefined;\n let fromOverrideHash: string | undefined;\n\n if (options.to) {\n const refResult = parseContractRef(options.to, { graph: appGraph, refs: allRefs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n activeRefHash = refResult.value.hash;\n if (refResult.value.provenance.kind === 'ref') {\n activeRefName = refResult.value.provenance.refName;\n activeRefEntry = allRefs[activeRefName];\n }\n }\n\n if (options.from) {\n const fromResult = parseContractRef(options.from, { graph: appGraph, refs: allRefs });\n if (!fromResult.ok) {\n return notOk(mapRefResolutionError(fromResult.failure));\n }\n fromOverrideHash = fromResult.value.hash;\n }\n\n const requiredInvariants: readonly string[] = [...(activeRefEntry?.invariants ?? [])].sort();\n\n if (!flags.json && !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 if (activeRefName) {\n details.push({ label: 'ref', value: activeRefName });\n }\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.space) {\n details.push({ label: 'space', value: options.space });\n }\n const header = formatStyledHeader({\n command: 'migration status',\n description: 'Show migration history and applied status',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n const listSpaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);\n const listResult = runMigrationList({\n spaces: listSpaces,\n ...ifDefined('spaceFilter', options.space),\n });\n if (!listResult.ok) {\n return listResult;\n }\n\n const scopedSpaces = listResult.value.spaces;\n const showSpaceHeadings = scopedSpaces.length > 1;\n\n let markersBySpace = new Map<string, ContractMarkerRecordLike>();\n let ledgersBySpace = new Map<string, readonly LedgerEntryRecord[]>();\n let connected = false;\n\n if (dbConnection && hasDriver && !usingFromOverride) {\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 connected = true;\n const read = await readMarkersAndLedgers({\n client,\n spaceIds: scopedSpaces.map((s) => s.spaceId),\n });\n markersBySpace = new Map(read.markersBySpace);\n ledgersBySpace = new Map(read.ledgersBySpace);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read database state: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n }\n\n if (activeRefEntry && activeRefEntry.invariants.length > 0 && connected) {\n const declared = collectDeclaredInvariants(appGraph);\n const markerInvariants = markersBySpace.get(aggregate.app.spaceId)?.invariants ?? [];\n const known = new Set<string>(declared);\n for (const id of markerInvariants) known.add(id);\n const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));\n if (unknown.length > 0) {\n return notOk(\n mapMigrationToolsError(\n errorUnknownInvariant({\n ...ifDefined('refName', activeRefName),\n unknown,\n declared: [...declared].sort(),\n }),\n ),\n );\n }\n }\n\n const showAppliedOverlay = connected && !usingFromOverride;\n const showDbMarker = connected && !usingFromOverride;\n const glyphMode = ui.resolveGlyphMode(false);\n const colorize = flags.color !== false;\n\n const statusSpaces: MigrationStatusSpaceResult[] = [];\n const treeSections: MigrationStatusTreeSection[] = [];\n let markerDiverged = false;\n let markerCannotReachTarget = false;\n let headlineTargetHash = activeRefHash ?? contractHash;\n let totalPending = 0;\n let hasAmbiguousTarget = false;\n\n for (const spaceEntry of scopedSpaces) {\n const member = aggregate.space(spaceEntry.spaceId);\n if (member === undefined) {\n continue;\n }\n const graph = member.graph();\n const spaceContractHash = member.contract().storage.storageHash;\n const targetHash = resolveTargetHashForSpace(member, spaceContractHash, activeRefHash);\n if (targetHash === undefined) {\n hasAmbiguousTarget = true;\n diagnostics.push({\n code: 'MIGRATION.DIVERGED',\n severity: 'warn',\n message: 'There are multiple valid migration paths — you must select a target',\n hints: [\n \"Use '--to <contract>' to select a target\",\n \"Or 'prisma-next ref set <name> <hash>' to create one\",\n ],\n });\n continue;\n }\n if (spaceEntry.spaceId === aggregate.app.spaceId) {\n headlineTargetHash = targetHash;\n }\n\n const markerRecord = markersBySpace.get(spaceEntry.spaceId);\n const markerHash = usingFromOverride\n ? fromOverrideHash\n : (markerRecord?.storageHash ?? undefined);\n const originHash = markerHash ?? EMPTY_CONTRACT_HASH;\n const markerInGraph =\n markerHash === undefined || graph.nodes.has(markerHash) || markerHash === spaceContractHash;\n if (\n connected &&\n !usingFromOverride &&\n markerHash !== undefined &&\n markerInGraph &&\n markerHash !== targetHash &&\n findPath(graph, originHash, targetHash) === null\n ) {\n markerCannotReachTarget = true;\n }\n\n if (connected && !usingFromOverride && markerHash !== undefined && !markerInGraph) {\n markerDiverged = true;\n diagnostics.push({\n code: 'MIGRATION.MARKER_NOT_IN_HISTORY',\n severity: 'warn',\n message:\n 'Database was updated outside the migration system (marker does not match any migration)',\n hints: [\n \"Run 'prisma-next db sign' to overwrite the marker if the database already matches the contract\",\n \"Run 'prisma-next db update' to push the current contract to the database\",\n ],\n });\n }\n\n const ledger = ledgersBySpace.get(spaceEntry.spaceId) ?? [];\n const appliedHashes = showAppliedOverlay ? appliedHashesFromLedger(ledger) : new Set<string>();\n\n const annotations = deriveStatusEdgeAnnotations({\n graph,\n targetHash,\n originHash,\n appliedMigrationHashes: appliedHashes,\n showAppliedOverlay,\n });\n const tree = renderSpaceTree({\n member,\n contractHash: spaceContractHash,\n markerHash,\n showDbMarker,\n targetHash,\n edgeAnnotations: annotations,\n colorize,\n glyphMode,\n });\n const migrations = buildStatusMigrations(spaceEntry.migrations, annotations);\n const pending = countPending(migrations);\n totalPending += pending;\n\n statusSpaces.push({\n spaceId: spaceEntry.spaceId,\n markerHash: markerHash ?? null,\n targetHash,\n migrations,\n });\n treeSections.push({\n spaceId: spaceEntry.spaceId,\n tree,\n showHeading: showSpaceHeadings,\n });\n }\n\n let missingInvariantsLine: string | undefined;\n if (connected && requiredInvariants.length > 0) {\n const markerInvariants = markersBySpace.get(aggregate.app.spaceId)?.invariants ?? [];\n const markerSet = new Set(markerInvariants);\n const missing = requiredInvariants.filter((id) => !markerSet.has(id));\n if (missing.length > 0) {\n missingInvariantsLine = `missing invariant(s): ${missing.join(', ')}`;\n if (activeRefHash !== undefined) {\n const originHash =\n markersBySpace.get(aggregate.app.spaceId)?.storageHash ?? EMPTY_CONTRACT_HASH;\n const outcome = findPathWithDecision(appGraph, originHash, activeRefHash, {\n ...ifDefined('refName', activeRefName),\n required: new Set(missing),\n });\n if (outcome.kind === 'unsatisfiable') {\n return notOk(\n mapMigrationToolsError(\n errorNoInvariantPath({\n ...ifDefined('refName', activeRefName),\n required: [...missing].sort(),\n missing: outcome.missing,\n structuralPath: outcome.structuralPath.map(toStructuralEdge),\n }),\n ),\n );\n }\n }\n }\n }\n\n const appMarkerHash = markersBySpace.get(aggregate.app.spaceId)?.storageHash;\n const summary = hasAmbiguousTarget\n ? 'Multiple valid migration paths — select a target with --to'\n : markerCannotReachTarget\n ? 'Database marker cannot reach the selected target'\n : buildStatusHeadline({\n pendingCount: totalPending,\n targetHash: headlineTargetHash,\n markerDiverged,\n markerHash: appMarkerHash,\n });\n\n if (scopedSpaces.every((s) => s.migrations.length === 0)) {\n return ok({\n ok: true,\n spaces: statusSpaces,\n summary: 'No migrations found',\n diagnostics,\n treeSections,\n ...ifDefined('missingInvariantsLine', missingInvariantsLine),\n });\n }\n\n return ok({\n ok: true,\n spaces: statusSpaces,\n summary,\n diagnostics,\n treeSections,\n ...ifDefined('missingInvariantsLine', missingInvariantsLine),\n });\n}\n\nexport function createMigrationStatusCommand(): Command {\n const command = new Command('status');\n setCommandDescriptions(\n command,\n 'Show migration path and pending status',\n 'Shows which migrations are pending between the database marker and\\n' +\n 'the target contract. Requires a database connection for live status.\\n' +\n 'Use `migration graph` for topology, `migration log` for history,\\n' +\n 'and `migration list` for on-disk enumeration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration status --db $DATABASE_URL',\n 'prisma-next migration status --to production --db $DATABASE_URL',\n 'prisma-next migration status --from sha256:abc --to production',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration log', oneLiner: 'Show executed migration history' },\n { verb: 'migration list', oneLiner: 'List on-disk migrations' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--space <id>', 'Narrow output to a single contract space')\n .option(\n '--to <contract>',\n 'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .option(\n '--from <contract>',\n 'Origin contract reference; same grammar as --to. Supplying --from switches to offline path computation.',\n )\n .action(async (options: MigrationStatusOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n const result = await executeMigrationStatusCommand(options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (statusResult) => {\n if (flags.json) {\n ui.output(\n JSON.stringify(\n {\n ok: true,\n spaces: statusResult.spaces,\n summary: statusResult.summary,\n ...(statusResult.diagnostics.length > 0\n ? { diagnostics: statusResult.diagnostics }\n : {}),\n ...(statusResult.missingInvariantsLine\n ? { missingInvariants: statusResult.missingInvariantsLine }\n : {}),\n },\n null,\n 2,\n ),\n );\n } else if (!flags.quiet) {\n ui.output(formatStatusHumanOutput(statusResult, flags.color !== false));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as createColorFormatter, O as formatDim, k as isVerbose } from "./command-helpers-DlrUCI7s.mjs";
|
|
2
2
|
import { cyan, green, yellow } from "colorette";
|
|
3
3
|
//#region src/utils/formatters/migrations.ts
|
|
4
4
|
/**
|
|
@@ -225,4 +225,4 @@ function formatMigrationJson(result) {
|
|
|
225
225
|
//#endregion
|
|
226
226
|
export { formatMigrationShowOutput as a, formatMigrationPlanOutput as i, formatMigrationApplyOutput as n, formatMigrationJson as r, formatMigrationApplyCommandOutput as t };
|
|
227
227
|
|
|
228
|
-
//# sourceMappingURL=migrations-
|
|
228
|
+
//# sourceMappingURL=migrations-B3H6RTXb.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations-DQ1t3XFL.mjs","names":[],"sources":["../src/utils/formatters/migrations.ts"],"sourcesContent":["import type { OperationPreview } from '@prisma-next/framework-components/control';\nimport { cyan, green, yellow } from 'colorette';\n\nimport type { PerSpaceExecutionEntry } from '../../control-api/types';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Render a single statement of an `OperationPreview` for the human-readable\n * preview block. SQL statements get a trailing `;` if missing so the rendered\n * preview is byte-identical to the legacy `string[]`-based renderer for SQL\n * targets. Other languages (`'mongodb-shell'`) render verbatim.\n */\nfunction renderPreviewStatement(text: string, language: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n if (language === 'sql') {\n return trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n }\n return trimmed;\n}\n\n/**\n * Choose the header label for a preview block. SQL-only previews keep the\n * legacy `DDL preview` label so the rendered output is byte-identical to the\n * pre-aggregate SQL CLI; previews from any other family — or a mix that\n * includes any non-SQL language — use the family-agnostic `Operation preview`\n * label.\n *\n * An empty `statements` array deliberately renders as `Operation preview`\n * rather than `DDL preview`: `Array.prototype.every` is vacuously true for\n * empty arrays, but we have no evidence the preview is SQL-only when no\n * statements are present, so the family-agnostic label is the safer default.\n */\nexport function previewBlockHeader(preview: OperationPreview): string {\n const allSql =\n preview.statements.length > 0 && preview.statements.every((s) => s.language === 'sql');\n return allSql ? 'DDL preview' : 'Operation preview';\n}\n\n// ============================================================================\n// Migration Command Output Formatters (shared by db init and db update)\n// ============================================================================\n\n/**\n * Shared CLI output type for migration commands (db init, db update).\n */\nexport interface MigrationCommandResult {\n readonly ok: true;\n readonly mode: 'plan' | 'apply';\n readonly plan: {\n readonly targetId: string;\n readonly destination: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the planned operations. Replaces the\n * previous `sql?: readonly string[]`. Consumers should read\n * `plan.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n };\n readonly execution?: {\n readonly operationsPlanned: number;\n readonly operationsExecuted: number;\n };\n readonly marker?: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n /**\n * Per-space execution breakdown in canonical schedule order\n * (extensions alphabetically, then app). Surfaces per-space markers\n * and the ops grouped by space, so the CLI summary can name which\n * space each op and marker belongs to instead of flattening them\n * into a single ambiguous list. See {@link PerSpaceExecutionEntry}.\n */\n readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;\n readonly advancedRef?: { readonly name: string; readonly hash: string } | null;\n readonly plannedAdvanceRef?: { readonly name: string; readonly hash: string } | null;\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\n/**\n * Render the shared per-space execution block consumed by the `db init`\n * / `db update` / `migrate` summaries. Always shows: space\n * label (`Extension space: <id>` or `App space`) → per-op lines under\n * each space → per-space marker hash (when known).\n *\n * `mode` controls the marker label phrasing — `'apply'` shows\n * `marker → <hash>` (post-apply), `'plan'` omits the marker line\n * entirely (no marker has been written yet).\n */\nexport function formatPerSpaceBlock(\n perSpace: ReadonlyArray<PerSpaceExecutionEntry>,\n mode: 'plan' | 'apply',\n useColor: boolean,\n): readonly string[] {\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatCyan = createColorFormatter(useColor, cyan);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n for (let s = 0; s < perSpace.length; s++) {\n const space = perSpace[s]!;\n if (s > 0) lines.push('');\n const header =\n space.kind === 'app'\n ? formatCyan('App space')\n : formatCyan(`Extension space: ${space.spaceId}`);\n lines.push(header);\n if (space.operations.length === 0) {\n lines.push(` ${formatDimText('(no operations)')}`);\n } else {\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(` ${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n }\n if (mode === 'apply' && space.marker) {\n lines.push(` ${formatDimText(`marker: ${space.marker.storageHash}`)}`);\n }\n }\n return lines;\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in plan mode.\n */\nexport function formatMigrationPlanOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Plan summary\n const operationCount = result.plan?.operations.length ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Planned ${operationCount} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Planned ${operationCount} operation(s)`);\n }\n\n const formatYellow = createColorFormatter(useColor, yellow);\n\n // Per-space breakdown takes precedence over the flat ops tree when\n // the aggregate flow surfaced one.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'plan', useColor));\n const hasDestructive = result.perSpace.some((s) =>\n s.operations.some((op) => op.operationClass === 'destructive'),\n );\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n } else if (result.plan?.operations && result.plan.operations.length > 0) {\n // App-only / no-aggregate-breakdown fallback. Same flat tree\n // we've always rendered.\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < result.plan.operations.length; i++) {\n const op = result.plan.operations[i];\n if (!op) continue;\n const isLast = i === result.plan.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.plan.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n // Destination hash\n if (result.plan?.destination) {\n lines.push('');\n lines.push(`${formatDimText(`Destination hash: ${result.plan.destination.storageHash}`)}`);\n }\n\n if (result.plannedAdvanceRef) {\n lines.push('');\n lines.push(\n formatDimText(\n `Would advance ref \"${result.plannedAdvanceRef.name}\" → ${result.plannedAdvanceRef.hash}`,\n ),\n );\n }\n\n // Statement preview (any family that implements OperationPreviewCapable)\n const preview = result.plan?.preview;\n if (preview) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(preview))}`);\n if (preview.statements.length === 0) {\n lines.push(`${formatDimText('No operations.')}`);\n } else {\n lines.push('');\n for (const statement of preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(`Total time: ${result.timings.total}ms`)}`);\n }\n\n // Note about dry run\n lines.push('');\n lines.push(`${formatDimText('This is a dry run. No changes were applied.')}`);\n lines.push(`${formatDimText('Run without --dry-run to apply changes.')}`);\n\n return lines.join('\\n');\n}\n\nexport interface MigrationApplyCommandOutputResult {\n readonly migrationsApplied: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly spaceId: string;\n readonly dirName?: string;\n readonly migrationHash?: string;\n readonly from?: string;\n readonly to?: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n /**\n * Per-space breakdown in canonical schedule order (extensions\n * alphabetically, then app). Always present for the aggregate-walking\n * `migrate` command.\n */\n readonly perSpace: readonly PerSpaceExecutionEntry[];\n readonly timings?: {\n readonly total: number;\n };\n readonly advancedRef?: { readonly name: string; readonly hash: string } | null;\n}\n\nexport function formatMigrationApplyCommandOutput(\n result: MigrationApplyCommandOutputResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatGreen('✔')} ${result.summary}`);\n\n if (result.perSpace.length > 0) {\n lines.push('');\n for (const line of formatPerSpaceBlock(result.perSpace, 'apply', useColor)) {\n lines.push(line);\n }\n }\n\n if (result.advancedRef) {\n lines.push('');\n lines.push(\n formatDimText(`Advanced ref \"${result.advancedRef.name}\" → ${result.advancedRef.hash}`),\n );\n }\n\n lines.push('');\n lines.push(formatDimText('Next: prisma-next migration status'));\n\n if (isVerbose(flags, 1) && result.timings) {\n lines.push('');\n lines.push(formatDimText(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\ninterface MigrationShowPresent {\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\ninterface MigrationShowResult {\n readonly migration: MigrationShowPresent;\n}\n\nfunction formatSpaceShowBlock(space: MigrationShowPresent, useColor: boolean): readonly string[] {\n const formatGreen = createColorFormatter(useColor, green);\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n lines.push(`${formatGreen('✔')} ${space.dirName}`);\n lines.push(`${formatDimText(` from: ${space.from ?? '(baseline)'}`)}`);\n lines.push(`${formatDimText(` to: ${space.to}`)}`);\n lines.push(`${formatDimText(` migrationHash: ${space.migrationHash}`)}`);\n lines.push(`${formatDimText(` created: ${space.createdAt}`)}`);\n\n lines.push('');\n lines.push(`${space.operations.length} operation(s)`);\n\n if (space.operations.length > 0) {\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = space.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n if (space.preview.statements.length > 0) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(space.preview))}`);\n lines.push('');\n for (const statement of space.preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n\n return lines;\n}\n\nexport function formatMigrationShowOutput(result: MigrationShowResult, flags: GlobalFlags): string {\n if (flags.quiet) {\n return '';\n }\n\n const useColor = flags.color !== false;\n return formatSpaceShowBlock(result.migration, useColor).join('\\n');\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in apply mode.\n */\nexport function formatMigrationApplyOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n if (result.ok) {\n // Success summary\n const executed = result.execution?.operationsExecuted ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n\n if (executed === 0) {\n const acrossClause =\n spaceCount > 0 ? ` across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}` : '';\n lines.push(`${formatGreen('✔')} Database already matches contract${acrossClause}`);\n } else if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Applied ${executed} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Applied ${executed} operation(s)`);\n }\n\n // Per-space breakdown — replaces the single ambiguous `Signature:`\n // line with a per-space marker + ops listing.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'apply', useColor));\n lines.push('');\n lines.push(\n formatDimText(\n `Run 'prisma-next migration status' to confirm ${\n spaceCount === 1 ? 'the space is' : 'all spaces are'\n } up to date.`,\n ),\n );\n } else if (result.marker) {\n // App-only / no-aggregate-breakdown fallback (e.g. older callers\n // / non-aggregate code paths). The label is\n // `App-space marker` (not `Signature`) so that when only one\n // marker is observable we still name what it covers explicitly.\n lines.push(`${formatDimText(` App-space marker: ${result.marker.storageHash}`)}`);\n if (result.marker.profileHash) {\n lines.push(`${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(` Total time: ${result.timings.total}ms`)}`);\n }\n\n if (result.advancedRef) {\n lines.push(\n formatDimText(`Advanced ref \"${result.advancedRef.name}\" → ${result.advancedRef.hash}`),\n );\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output for migration commands (db init, db update).\n */\nexport function formatMigrationJson(result: MigrationCommandResult): string {\n return JSON.stringify(result, null, 2);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"migrations-B3H6RTXb.mjs","names":[],"sources":["../src/utils/formatters/migrations.ts"],"sourcesContent":["import type { OperationPreview } from '@prisma-next/framework-components/control';\nimport { cyan, green, yellow } from 'colorette';\n\nimport type { PerSpaceExecutionEntry } from '../../control-api/types';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Render a single statement of an `OperationPreview` for the human-readable\n * preview block. SQL statements get a trailing `;` if missing so the rendered\n * preview is byte-identical to the legacy `string[]`-based renderer for SQL\n * targets. Other languages (`'mongodb-shell'`) render verbatim.\n */\nfunction renderPreviewStatement(text: string, language: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n if (language === 'sql') {\n return trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n }\n return trimmed;\n}\n\n/**\n * Choose the header label for a preview block. SQL-only previews keep the\n * legacy `DDL preview` label so the rendered output is byte-identical to the\n * pre-aggregate SQL CLI; previews from any other family — or a mix that\n * includes any non-SQL language — use the family-agnostic `Operation preview`\n * label.\n *\n * An empty `statements` array deliberately renders as `Operation preview`\n * rather than `DDL preview`: `Array.prototype.every` is vacuously true for\n * empty arrays, but we have no evidence the preview is SQL-only when no\n * statements are present, so the family-agnostic label is the safer default.\n */\nexport function previewBlockHeader(preview: OperationPreview): string {\n const allSql =\n preview.statements.length > 0 && preview.statements.every((s) => s.language === 'sql');\n return allSql ? 'DDL preview' : 'Operation preview';\n}\n\n// ============================================================================\n// Migration Command Output Formatters (shared by db init and db update)\n// ============================================================================\n\n/**\n * Shared CLI output type for migration commands (db init, db update).\n */\nexport interface MigrationCommandResult {\n readonly ok: true;\n readonly mode: 'plan' | 'apply';\n readonly plan: {\n readonly targetId: string;\n readonly destination: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the planned operations. Replaces the\n * previous `sql?: readonly string[]`. Consumers should read\n * `plan.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n };\n readonly execution?: {\n readonly operationsPlanned: number;\n readonly operationsExecuted: number;\n };\n readonly marker?: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n /**\n * Per-space execution breakdown in canonical schedule order\n * (extensions alphabetically, then app). Surfaces per-space markers\n * and the ops grouped by space, so the CLI summary can name which\n * space each op and marker belongs to instead of flattening them\n * into a single ambiguous list. See {@link PerSpaceExecutionEntry}.\n */\n readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;\n readonly advancedRef?: { readonly name: string; readonly hash: string } | null;\n readonly plannedAdvanceRef?: { readonly name: string; readonly hash: string } | null;\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\n/**\n * Render the shared per-space execution block consumed by the `db init`\n * / `db update` / `migrate` summaries. Always shows: space\n * label (`Extension space: <id>` or `App space`) → per-op lines under\n * each space → per-space marker hash (when known).\n *\n * `mode` controls the marker label phrasing — `'apply'` shows\n * `marker → <hash>` (post-apply), `'plan'` omits the marker line\n * entirely (no marker has been written yet).\n */\nexport function formatPerSpaceBlock(\n perSpace: ReadonlyArray<PerSpaceExecutionEntry>,\n mode: 'plan' | 'apply',\n useColor: boolean,\n): readonly string[] {\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatCyan = createColorFormatter(useColor, cyan);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n for (let s = 0; s < perSpace.length; s++) {\n const space = perSpace[s]!;\n if (s > 0) lines.push('');\n const header =\n space.kind === 'app'\n ? formatCyan('App space')\n : formatCyan(`Extension space: ${space.spaceId}`);\n lines.push(header);\n if (space.operations.length === 0) {\n lines.push(` ${formatDimText('(no operations)')}`);\n } else {\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(` ${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n }\n if (mode === 'apply' && space.marker) {\n lines.push(` ${formatDimText(`marker: ${space.marker.storageHash}`)}`);\n }\n }\n return lines;\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in plan mode.\n */\nexport function formatMigrationPlanOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Plan summary\n const operationCount = result.plan?.operations.length ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Planned ${operationCount} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Planned ${operationCount} operation(s)`);\n }\n\n const formatYellow = createColorFormatter(useColor, yellow);\n\n // Per-space breakdown takes precedence over the flat ops tree when\n // the aggregate flow surfaced one.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'plan', useColor));\n const hasDestructive = result.perSpace.some((s) =>\n s.operations.some((op) => op.operationClass === 'destructive'),\n );\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n } else if (result.plan?.operations && result.plan.operations.length > 0) {\n // App-only / no-aggregate-breakdown fallback. Same flat tree\n // we've always rendered.\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < result.plan.operations.length; i++) {\n const op = result.plan.operations[i];\n if (!op) continue;\n const isLast = i === result.plan.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.plan.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n // Destination hash\n if (result.plan?.destination) {\n lines.push('');\n lines.push(`${formatDimText(`Destination hash: ${result.plan.destination.storageHash}`)}`);\n }\n\n if (result.plannedAdvanceRef) {\n lines.push('');\n lines.push(\n formatDimText(\n `Would advance ref \"${result.plannedAdvanceRef.name}\" → ${result.plannedAdvanceRef.hash}`,\n ),\n );\n }\n\n // Statement preview (any family that implements OperationPreviewCapable)\n const preview = result.plan?.preview;\n if (preview) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(preview))}`);\n if (preview.statements.length === 0) {\n lines.push(`${formatDimText('No operations.')}`);\n } else {\n lines.push('');\n for (const statement of preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(`Total time: ${result.timings.total}ms`)}`);\n }\n\n // Note about dry run\n lines.push('');\n lines.push(`${formatDimText('This is a dry run. No changes were applied.')}`);\n lines.push(`${formatDimText('Run without --dry-run to apply changes.')}`);\n\n return lines.join('\\n');\n}\n\nexport interface MigrationApplyCommandOutputResult {\n readonly migrationsApplied: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly spaceId: string;\n readonly dirName?: string;\n readonly migrationHash?: string;\n readonly from?: string;\n readonly to?: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n /**\n * Per-space breakdown in canonical schedule order (extensions\n * alphabetically, then app). Always present for the aggregate-walking\n * `migrate` command.\n */\n readonly perSpace: readonly PerSpaceExecutionEntry[];\n readonly timings?: {\n readonly total: number;\n };\n readonly advancedRef?: { readonly name: string; readonly hash: string } | null;\n}\n\nexport function formatMigrationApplyCommandOutput(\n result: MigrationApplyCommandOutputResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatGreen('✔')} ${result.summary}`);\n\n if (result.perSpace.length > 0) {\n lines.push('');\n for (const line of formatPerSpaceBlock(result.perSpace, 'apply', useColor)) {\n lines.push(line);\n }\n }\n\n if (result.advancedRef) {\n lines.push('');\n lines.push(\n formatDimText(`Advanced ref \"${result.advancedRef.name}\" → ${result.advancedRef.hash}`),\n );\n }\n\n lines.push('');\n lines.push(formatDimText('Next: prisma-next migration status'));\n\n if (isVerbose(flags, 1) && result.timings) {\n lines.push('');\n lines.push(formatDimText(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\ninterface MigrationShowPresent {\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\ninterface MigrationShowResult {\n readonly migration: MigrationShowPresent;\n}\n\nfunction formatSpaceShowBlock(space: MigrationShowPresent, useColor: boolean): readonly string[] {\n const formatGreen = createColorFormatter(useColor, green);\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n lines.push(`${formatGreen('✔')} ${space.dirName}`);\n lines.push(`${formatDimText(` from: ${space.from ?? '(baseline)'}`)}`);\n lines.push(`${formatDimText(` to: ${space.to}`)}`);\n lines.push(`${formatDimText(` migrationHash: ${space.migrationHash}`)}`);\n lines.push(`${formatDimText(` created: ${space.createdAt}`)}`);\n\n lines.push('');\n lines.push(`${space.operations.length} operation(s)`);\n\n if (space.operations.length > 0) {\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = space.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n if (space.preview.statements.length > 0) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(space.preview))}`);\n lines.push('');\n for (const statement of space.preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n\n return lines;\n}\n\nexport function formatMigrationShowOutput(result: MigrationShowResult, flags: GlobalFlags): string {\n if (flags.quiet) {\n return '';\n }\n\n const useColor = flags.color !== false;\n return formatSpaceShowBlock(result.migration, useColor).join('\\n');\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in apply mode.\n */\nexport function formatMigrationApplyOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n if (result.ok) {\n // Success summary\n const executed = result.execution?.operationsExecuted ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n\n if (executed === 0) {\n const acrossClause =\n spaceCount > 0 ? ` across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}` : '';\n lines.push(`${formatGreen('✔')} Database already matches contract${acrossClause}`);\n } else if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Applied ${executed} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Applied ${executed} operation(s)`);\n }\n\n // Per-space breakdown — replaces the single ambiguous `Signature:`\n // line with a per-space marker + ops listing.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'apply', useColor));\n lines.push('');\n lines.push(\n formatDimText(\n `Run 'prisma-next migration status' to confirm ${\n spaceCount === 1 ? 'the space is' : 'all spaces are'\n } up to date.`,\n ),\n );\n } else if (result.marker) {\n // App-only / no-aggregate-breakdown fallback (e.g. older callers\n // / non-aggregate code paths). The label is\n // `App-space marker` (not `Signature`) so that when only one\n // marker is observable we still name what it covers explicitly.\n lines.push(`${formatDimText(` App-space marker: ${result.marker.storageHash}`)}`);\n if (result.marker.profileHash) {\n lines.push(`${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(` Total time: ${result.timings.total}ms`)}`);\n }\n\n if (result.advancedRef) {\n lines.push(\n formatDimText(`Advanced ref \"${result.advancedRef.name}\" → ${result.advancedRef.hash}`),\n );\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output for migration commands (db init, db update).\n */\nexport function formatMigrationJson(result: MigrationCommandResult): string {\n return JSON.stringify(result, null, 2);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as isCI, _ as
|
|
1
|
+
import { C as formatCommandHelp, S as isCI, _ as createTerminalUI, g as parseGlobalFlagsOrExit, h as parseGlobalFlags, l as setCommandDescriptions, t as addGlobalOptions, u as setCommandExamples } from "./command-helpers-DlrUCI7s.mjs";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { readUserConfig, resolveGating, userConfigPath, writeUserConfig } from "@prisma-next/cli-telemetry";
|
|
4
4
|
//#region src/commands/telemetry/status.ts
|
|
@@ -119,4 +119,4 @@ function createTelemetryCommand() {
|
|
|
119
119
|
//#endregion
|
|
120
120
|
export { createTelemetryCommand as t };
|
|
121
121
|
|
|
122
|
-
//# sourceMappingURL=telemetry-
|
|
122
|
+
//# sourceMappingURL=telemetry-LFFQmqHd.mjs.map
|