prisma-next 0.12.0-dev.5 → 0.12.0-dev.50
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 +180 -163
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-KgJorIvG.mjs → client-DC-UlBLy.mjs} +83 -58
- package/dist/client-DC-UlBLy.mjs.map +1 -0
- package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-esJGBD4W.mjs} +317 -23
- package/dist/command-helpers-esJGBD4W.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +10 -7
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +2 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +6 -8
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -13
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +3 -2
- package/dist/commands/migration-graph.d.mts +17 -8
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +183 -2
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +25 -27
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +2 -190
- package/dist/commands/migration-log.d.mts +9 -19
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -137
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.d.mts +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +17 -21
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +23 -35
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +42 -144
- 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 +3 -3
- package/dist/commands/telemetry/index.d.mts +7 -0
- package/dist/commands/telemetry/index.d.mts.map +1 -0
- package/dist/commands/telemetry/index.mjs +2 -0
- package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-COZAemUl.mjs} +2 -2
- package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-COZAemUl.mjs.map} +1 -1
- package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-Bv46RAIO.mjs} +3 -3
- package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-Bv46RAIO.mjs.map} +1 -1
- package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-DIWImLqS.mjs} +5 -5
- package/dist/{contract-emit-D-4jrNve.mjs.map → contract-emit-DIWImLqS.mjs.map} +1 -1
- package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-DpGN9SAj.mjs} +3 -3
- package/dist/{contract-infer-D8uEbJuu.mjs.map → contract-infer-DpGN9SAj.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-CpNVrBqW.mjs} +63 -5
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-CpNVrBqW.mjs.map} +1 -1
- package/dist/{db-verify-v_vUKXTU.mjs → db-verify-Cq16Obsw.mjs} +4 -4
- package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-Cq16Obsw.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +2 -2
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-fYXjz_in.mjs → framework-components-BO9VO43s.mjs} +2 -2
- package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-BO9VO43s.mjs.map} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-CV5LhrFg.d.mts} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-CV5LhrFg.d.mts.map} +1 -1
- package/dist/{init-Cv9UzWL5.mjs → init-C0rjiQ9I.mjs} +5 -58
- package/dist/init-C0rjiQ9I.mjs.map +1 -0
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-CRDKTNcf.mjs} +3 -3
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs.map → inspect-live-schema-CRDKTNcf.mjs.map} +1 -1
- package/dist/migration-check-BxWlQBOs.mjs +573 -0
- package/dist/migration-check-BxWlQBOs.mjs.map +1 -0
- package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-BDd9abqW.mjs} +3 -3
- package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-BDd9abqW.mjs.map} +1 -1
- package/dist/migration-graph-space-render-CeNXh_Wy.mjs +1966 -0
- package/dist/migration-graph-space-render-CeNXh_Wy.mjs.map +1 -0
- package/dist/migration-list-vJWFuXca.mjs +228 -0
- package/dist/migration-list-vJWFuXca.mjs.map +1 -0
- package/dist/migration-log-6rcHQSI4.mjs +222 -0
- package/dist/migration-log-6rcHQSI4.mjs.map +1 -0
- package/dist/migration-path-target-UkxkgXnv.mjs +38 -0
- package/dist/migration-path-target-UkxkgXnv.mjs.map +1 -0
- package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-CHu_erQ5.mjs} +5 -6
- package/dist/{migration-plan-9DJ7q7_z.mjs.map → migration-plan-CHu_erQ5.mjs.map} +1 -1
- package/dist/migration-status-Bjv91dE7.mjs +444 -0
- package/dist/migration-status-Bjv91dE7.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-BD61elic.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-BD61elic.mjs.map} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-CJY9zOv7.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-CJY9zOv7.mjs.map} +1 -1
- package/dist/schemas-BL33A3i-.d.mts +193 -0
- package/dist/schemas-BL33A3i-.d.mts.map +1 -0
- package/dist/schemas-DJY2O09F.mjs +112 -0
- package/dist/schemas-DJY2O09F.mjs.map +1 -0
- package/dist/telemetry-CZkgkR_O.mjs +122 -0
- package/dist/telemetry-CZkgkR_O.mjs.map +1 -0
- package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-BgLiAOYi.d.mts} +1 -1
- package/dist/{terminal-ui-5Y6mrg93.d.mts.map → terminal-ui-BgLiAOYi.d.mts.map} +1 -1
- package/dist/{types-Dt_SfqFm.d.mts → types-qV41eEXH.d.mts} +44 -31
- package/dist/types-qV41eEXH.d.mts.map +1 -0
- package/dist/{verify-DCA9Sldu.mjs → verify-IilvIk_E.mjs} +2 -2
- package/dist/{verify-DCA9Sldu.mjs.map → verify-IilvIk_E.mjs.map} +1 -1
- package/package.json +11 -12
- package/dist/client-KgJorIvG.mjs.map +0 -1
- package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/commands/migration-log.mjs.map +0 -1
- package/dist/commands/migration-status.mjs.map +0 -1
- package/dist/extension-pack-inputs-IDvjRCi3.mjs +0 -62
- package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +0 -1
- package/dist/graph-render-rFAqZujX.mjs +0 -1081
- package/dist/graph-render-rFAqZujX.mjs.map +0 -1
- package/dist/init-Cv9UzWL5.mjs.map +0 -1
- package/dist/migration-check-BiBJoYYW.mjs +0 -341
- package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
- package/dist/migration-graph-D7DVUElV.mjs +0 -1232
- package/dist/migration-graph-D7DVUElV.mjs.map +0 -1
- package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
- package/dist/migration-types-D2FW63pr.d.mts +0 -15
- package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
- package/dist/migrations-Cv2jxNNK.mjs +0 -228
- package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
- package/dist/types-Dt_SfqFm.d.mts.map +0 -1
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
import { A as formatStyledHeader, K as errorInvalidSpaceId, L as errorAmbiguousMigrationRef, _ as createTerminalUI, at as errorSpaceNotFound, b as formatErrorJson, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, o as resolveContractPath, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, ut as mapRefResolutionError, x as formatErrorOutput } from "./command-helpers-esJGBD4W.mjs";
|
|
3
|
+
import { n as buildReadAggregate, s as toDeclaredExtensionsFromRaw } from "./contract-space-aggregate-loader-CpNVrBqW.mjs";
|
|
4
|
+
import { i as resolveTargetPathAcrossSpaces, n as looksLikePath, r as resolveAppTargetPath, t as findPackageByDirPath } from "./migration-path-target-UkxkgXnv.mjs";
|
|
5
|
+
import "./schemas-DJY2O09F.mjs";
|
|
6
|
+
import { Command } from "commander";
|
|
7
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
8
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
9
|
+
import { join, relative } from "pathe";
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { createControlStack } from "@prisma-next/framework-components/control";
|
|
12
|
+
import { RESERVED_SPACE_SUBDIR_NAMES, isValidSpaceId, listContractSpaceDirectories, spaceMigrationDirectory, spaceRefsDirectory } from "@prisma-next/migration-tools/spaces";
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
14
|
+
import { loadContractSpaceAggregate } from "@prisma-next/migration-tools/aggregate";
|
|
15
|
+
import { parseMigrationRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
16
|
+
import { verifyMigrationHash } from "@prisma-next/migration-tools/hash";
|
|
17
|
+
//#region src/utils/integrity-violation-to-check-failure.ts
|
|
18
|
+
function migrationPathRelative$1(dirPath) {
|
|
19
|
+
return relative(process.cwd(), dirPath);
|
|
20
|
+
}
|
|
21
|
+
function migrationFileRelative$1(dirPath, fileName) {
|
|
22
|
+
return join(migrationPathRelative$1(dirPath), fileName);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Map one {@link IntegrityViolation} onto a `migration check` failure row.
|
|
26
|
+
* Sole catalogue mapping from integrity violations to `PN-MIG-CHECK-*`.
|
|
27
|
+
*/
|
|
28
|
+
function integrityViolationToCheckFailure(violation, migrationsDir) {
|
|
29
|
+
const spaceRelative = (spaceId) => migrationPathRelative$1(join(migrationsDir, spaceId));
|
|
30
|
+
const packageRelative = (spaceId, dirName) => migrationPathRelative$1(join(migrationsDir, spaceId, dirName));
|
|
31
|
+
const refRelative = (spaceId, refName) => migrationPathRelative$1(join(migrationsDir, spaceId, "refs", `${refName}.json`));
|
|
32
|
+
switch (violation.kind) {
|
|
33
|
+
case "hashMismatch": return {
|
|
34
|
+
space: violation.spaceId,
|
|
35
|
+
code: "PN-MIG-CHECK-001",
|
|
36
|
+
where: migrationFileRelative$1(join(migrationsDir, violation.spaceId, violation.dirName), "migration.json"),
|
|
37
|
+
why: `Stored hash ${violation.stored} does not match recomputed hash ${violation.computed}`,
|
|
38
|
+
fix: "Re-emit the migration package or restore from version control."
|
|
39
|
+
};
|
|
40
|
+
case "providedInvariantsMismatch": return {
|
|
41
|
+
space: violation.spaceId,
|
|
42
|
+
code: "PN-MIG-CHECK-002",
|
|
43
|
+
where: packageRelative(violation.spaceId, violation.dirName),
|
|
44
|
+
why: `Migration "${violation.dirName}" providedInvariants in migration.json disagrees with ops.json.`,
|
|
45
|
+
fix: "Re-emit the migration package so migration.json and ops.json agree."
|
|
46
|
+
};
|
|
47
|
+
case "packageUnloadable": return {
|
|
48
|
+
space: violation.spaceId,
|
|
49
|
+
code: "PN-MIG-CHECK-002",
|
|
50
|
+
where: packageRelative(violation.spaceId, violation.dirName),
|
|
51
|
+
why: `Migration "${violation.dirName}" could not be loaded: ${violation.detail}`,
|
|
52
|
+
fix: "Re-emit the migration package or restore from version control."
|
|
53
|
+
};
|
|
54
|
+
case "sameSourceAndTarget": return {
|
|
55
|
+
space: violation.spaceId,
|
|
56
|
+
code: "PN-MIG-CHECK-007",
|
|
57
|
+
where: packageRelative(violation.spaceId, violation.dirName),
|
|
58
|
+
why: `Migration "${violation.dirName}" in space "${violation.spaceId}" has source equal to target (${violation.hash}) with no data invariant — a true no-op self-edge.`,
|
|
59
|
+
fix: "Add a data operation if this self-edge was meant to carry a data invariant, or delete the migration if it is a true no-op."
|
|
60
|
+
};
|
|
61
|
+
case "orphanSpaceDir": return {
|
|
62
|
+
space: violation.spaceId,
|
|
63
|
+
code: "PN-MIG-CHECK-008",
|
|
64
|
+
where: spaceRelative(violation.spaceId),
|
|
65
|
+
why: `Contract-space directory "${violation.spaceId}" exists on disk but no extension declares it.`,
|
|
66
|
+
fix: "Remove the orphan directory, or declare the extension in `extensionPacks`."
|
|
67
|
+
};
|
|
68
|
+
case "declaredButUnmigrated": return {
|
|
69
|
+
space: violation.spaceId,
|
|
70
|
+
code: "PN-MIG-CHECK-009",
|
|
71
|
+
where: spaceRelative(violation.spaceId),
|
|
72
|
+
why: `Extension "${violation.spaceId}" is declared in \`extensionPacks\` but has no on-disk migrations directory.`,
|
|
73
|
+
fix: "Re-emit the extension contract-space artefacts with `prisma-next contract emit` and migration planning, or remove the extension from `extensionPacks` if it is unused."
|
|
74
|
+
};
|
|
75
|
+
case "headRefMissing": return {
|
|
76
|
+
space: violation.spaceId,
|
|
77
|
+
code: "PN-MIG-CHECK-010",
|
|
78
|
+
where: refRelative(violation.spaceId, "head"),
|
|
79
|
+
why: `Head ref \`refs/head.json\` is missing for contract space "${violation.spaceId}".`,
|
|
80
|
+
fix: "Re-emit the contract-space migrations and head ref artefacts, or restore `refs/head.json` from version control."
|
|
81
|
+
};
|
|
82
|
+
case "headRefNotInGraph": return {
|
|
83
|
+
space: violation.spaceId,
|
|
84
|
+
code: "PN-MIG-CHECK-011",
|
|
85
|
+
where: refRelative(violation.spaceId, "head"),
|
|
86
|
+
why: `Head ref ${violation.hash} for contract space "${violation.spaceId}" is not present in its migration graph.`,
|
|
87
|
+
fix: "Re-emit the contract space migrations, or restore the missing migration package."
|
|
88
|
+
};
|
|
89
|
+
case "refUnreadable": return {
|
|
90
|
+
space: violation.spaceId,
|
|
91
|
+
code: "PN-MIG-CHECK-012",
|
|
92
|
+
where: refRelative(violation.spaceId, violation.refName),
|
|
93
|
+
why: `Ref "${violation.refName}" for contract space "${violation.spaceId}" is unreadable: ${violation.detail}`,
|
|
94
|
+
fix: "Repair or remove the corrupt ref file."
|
|
95
|
+
};
|
|
96
|
+
case "targetMismatch": return {
|
|
97
|
+
space: violation.spaceId,
|
|
98
|
+
code: "PN-MIG-CHECK-013",
|
|
99
|
+
where: spaceRelative(violation.spaceId),
|
|
100
|
+
why: `Contract space "${violation.spaceId}" targets "${violation.actual}" but the project targets "${violation.expected}".`,
|
|
101
|
+
fix: "Update the extension to target the configured database, or change the project target."
|
|
102
|
+
};
|
|
103
|
+
case "disjointness": return {
|
|
104
|
+
space: "app",
|
|
105
|
+
code: "PN-MIG-CHECK-014",
|
|
106
|
+
where: migrationPathRelative$1(migrationsDir),
|
|
107
|
+
why: `Storage element "${violation.element}" is claimed by multiple contract spaces: ${violation.claimedBy.join(", ")}.`,
|
|
108
|
+
fix: "Update the contracts so each storage element is owned by exactly one contract space."
|
|
109
|
+
};
|
|
110
|
+
case "contractUnreadable": return {
|
|
111
|
+
space: violation.spaceId,
|
|
112
|
+
code: "PN-MIG-CHECK-015",
|
|
113
|
+
where: migrationFileRelative$1(join(migrationsDir, violation.spaceId), "contract.json"),
|
|
114
|
+
why: `Contract for space "${violation.spaceId}" is unreadable: ${violation.detail}`,
|
|
115
|
+
fix: "Re-emit the extension contract artefacts, or fix the descriptor producing the invalid contract."
|
|
116
|
+
};
|
|
117
|
+
case "duplicateMigrationHash": return {
|
|
118
|
+
space: violation.spaceId,
|
|
119
|
+
code: "PN-MIG-CHECK-016",
|
|
120
|
+
where: spaceRelative(violation.spaceId),
|
|
121
|
+
why: `Multiple migrations in space "${violation.spaceId}" share migrationHash "${violation.migrationHash}" (${violation.dirNames.join(", ")}).`,
|
|
122
|
+
fix: "Re-emit one of the conflicting packages so each migrationHash is unique."
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/commands/migration-check.ts
|
|
128
|
+
function migrationPathRelative(dirPath) {
|
|
129
|
+
return relative(process.cwd(), dirPath);
|
|
130
|
+
}
|
|
131
|
+
function migrationFileRelative(dirPath, fileName) {
|
|
132
|
+
return join(migrationPathRelative(dirPath), fileName);
|
|
133
|
+
}
|
|
134
|
+
function checkFileExists(spaceId, dirPath, dirName, fileName) {
|
|
135
|
+
if (!existsSync(join(dirPath, fileName))) return {
|
|
136
|
+
space: spaceId,
|
|
137
|
+
code: "PN-MIG-CHECK-002",
|
|
138
|
+
where: migrationFileRelative(dirPath, fileName),
|
|
139
|
+
why: `${fileName} is missing from ${dirName}`,
|
|
140
|
+
fix: "Re-emit the migration package or restore from version control."
|
|
141
|
+
};
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
function checkSnapshotConsistency(spaceId, pkg) {
|
|
145
|
+
const endContractPath = join(pkg.dirPath, "end-contract.json");
|
|
146
|
+
if (!existsSync(endContractPath)) return null;
|
|
147
|
+
try {
|
|
148
|
+
const snapshotHash = JSON.parse(readFileSync(endContractPath, "utf-8"))["storage"]?.["storageHash"];
|
|
149
|
+
if (typeof snapshotHash === "string" && snapshotHash !== pkg.metadata.to) return {
|
|
150
|
+
space: spaceId,
|
|
151
|
+
code: "PN-MIG-CHECK-005",
|
|
152
|
+
where: migrationPathRelative(pkg.dirPath),
|
|
153
|
+
why: `Migration "${pkg.dirName}" declares to=${pkg.metadata.to} but end-contract.json has storageHash=${snapshotHash}`,
|
|
154
|
+
fix: "Re-emit the migration package so migration.json and end-contract.json agree."
|
|
155
|
+
};
|
|
156
|
+
} catch {
|
|
157
|
+
return {
|
|
158
|
+
space: spaceId,
|
|
159
|
+
code: "PN-MIG-CHECK-006",
|
|
160
|
+
where: migrationPathRelative(pkg.dirPath),
|
|
161
|
+
why: `Migration "${pkg.dirName}" has an unparseable end-contract.json.`,
|
|
162
|
+
fix: "Re-emit the migration package to repair the snapshot file."
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Project the loaded {@link ContractSpaceAggregate} into the
|
|
169
|
+
* {@link CheckSpace} rows the multi-space check iterates — one per on-disk
|
|
170
|
+
* contract-space directory, in the aggregate's `app`-first ordering. Mirrors
|
|
171
|
+
* `migration list`'s `migrationSpaceListEntriesFromAggregate`: space
|
|
172
|
+
* membership matches the on-disk directories, package / ref / graph data come
|
|
173
|
+
* from `aggregate.space(id)`.
|
|
174
|
+
*/
|
|
175
|
+
async function enumerateCheckSpaces(aggregate, projectMigrationsDir) {
|
|
176
|
+
const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);
|
|
177
|
+
const onDiskSpaceIds = new Set(candidateDirs.filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name)).filter(isValidSpaceId));
|
|
178
|
+
const spaces = [];
|
|
179
|
+
for (const member of aggregate.spaces()) {
|
|
180
|
+
const spaceId = member.spaceId;
|
|
181
|
+
if (!isValidSpaceId(spaceId)) continue;
|
|
182
|
+
if (!onDiskSpaceIds.has(spaceId)) continue;
|
|
183
|
+
const migrationsDir = spaceMigrationDirectory(projectMigrationsDir, spaceId);
|
|
184
|
+
spaces.push({
|
|
185
|
+
spaceId,
|
|
186
|
+
packages: member.packages,
|
|
187
|
+
refs: member.refs,
|
|
188
|
+
graph: member.graph(),
|
|
189
|
+
migrationsDir,
|
|
190
|
+
refsDir: spaceRefsDirectory(migrationsDir)
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return spaces;
|
|
194
|
+
}
|
|
195
|
+
function checkManifestFilesPresent(space) {
|
|
196
|
+
if (!existsSync(space.migrationsDir)) return [];
|
|
197
|
+
const loadedDirNames = new Set(space.packages.map((p) => p.dirName));
|
|
198
|
+
const failures = [];
|
|
199
|
+
let entries;
|
|
200
|
+
try {
|
|
201
|
+
entries = readdirSync(space.migrationsDir);
|
|
202
|
+
} catch {
|
|
203
|
+
return failures;
|
|
204
|
+
}
|
|
205
|
+
for (const entry of entries) {
|
|
206
|
+
if (entry.startsWith(".") || entry.startsWith("_") || entry === "refs") continue;
|
|
207
|
+
const entryPath = join(space.migrationsDir, entry);
|
|
208
|
+
try {
|
|
209
|
+
if (!statSync(entryPath).isDirectory()) continue;
|
|
210
|
+
} catch {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (!loadedDirNames.has(entry)) for (const f of ["migration.json", "ops.json"]) {
|
|
214
|
+
const fail = checkFileExists(space.spaceId, entryPath, entry, f);
|
|
215
|
+
if (fail) failures.push(fail);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return failures;
|
|
219
|
+
}
|
|
220
|
+
function checkReachability(space) {
|
|
221
|
+
const allToHashes = new Set(space.packages.map((p) => p.metadata.to));
|
|
222
|
+
const failures = [];
|
|
223
|
+
for (const pkg of space.packages) if (!(pkg.metadata.from === null || allToHashes.has(pkg.metadata.from) || pkg.metadata.from === "sha256:empty")) failures.push({
|
|
224
|
+
space: space.spaceId,
|
|
225
|
+
code: "PN-MIG-CHECK-003",
|
|
226
|
+
where: migrationPathRelative(pkg.dirPath),
|
|
227
|
+
why: `Migration "${pkg.dirName}" starts from ${pkg.metadata.from} which no other migration produces`,
|
|
228
|
+
fix: "This migration is unreachable in the graph. Delete it or re-emit a connecting migration."
|
|
229
|
+
});
|
|
230
|
+
return failures;
|
|
231
|
+
}
|
|
232
|
+
function checkDanglingRefs(space) {
|
|
233
|
+
const failures = [];
|
|
234
|
+
for (const [name, entry] of Object.entries(space.refs)) if (!space.graph.nodes.has(entry.hash)) failures.push({
|
|
235
|
+
space: space.spaceId,
|
|
236
|
+
code: "PN-MIG-CHECK-004",
|
|
237
|
+
where: relative(process.cwd(), join(space.refsDir, `${name}.json`)),
|
|
238
|
+
why: `Ref "${name}" points at ${entry.hash} which does not exist in the migration graph`,
|
|
239
|
+
fix: `Update the ref with \`prisma-next ref set ${name} <valid-hash>\` or delete it.`
|
|
240
|
+
});
|
|
241
|
+
return failures;
|
|
242
|
+
}
|
|
243
|
+
function checkSpace(space) {
|
|
244
|
+
return [
|
|
245
|
+
...checkManifestFilesPresent(space),
|
|
246
|
+
...space.packages.map((pkg) => checkSnapshotConsistency(space.spaceId, pkg)).filter((f) => f !== null),
|
|
247
|
+
...checkReachability(space),
|
|
248
|
+
...checkDanglingRefs(space)
|
|
249
|
+
];
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Policy core of the holistic `migration check`: validates `--space`,
|
|
253
|
+
* narrows the pre-enumerated spaces, and runs the per-space explicit graph
|
|
254
|
+
* checks (file-existence, snapshot consistency, reachability, dangling
|
|
255
|
+
* refs), aggregating every failure into one {@link MigrationCheckResult}.
|
|
256
|
+
*
|
|
257
|
+
* `--space` validation mirrors `migration list`: an invalid id →
|
|
258
|
+
* {@link errorInvalidSpaceId}; an id with no on-disk space →
|
|
259
|
+
* {@link errorSpaceNotFound}. Both map to exit `PRECONDITION` at the shell.
|
|
260
|
+
* Aggregate-integrity violations (which already span every space) are folded
|
|
261
|
+
* in by the caller, not here.
|
|
262
|
+
*/
|
|
263
|
+
function runMigrationCheck(inputs) {
|
|
264
|
+
const { spaces, spaceFilter } = inputs;
|
|
265
|
+
if (spaceFilter !== void 0 && !isValidSpaceId(spaceFilter)) return notOk(errorInvalidSpaceId(spaceFilter));
|
|
266
|
+
if (spaceFilter !== void 0 && !spaces.some((s) => s.spaceId === spaceFilter)) return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));
|
|
267
|
+
const failures = (spaceFilter !== void 0 ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces).flatMap(checkSpace);
|
|
268
|
+
if (failures.length === 0) return ok({
|
|
269
|
+
ok: true,
|
|
270
|
+
failures: [],
|
|
271
|
+
summary: "All checks passed"
|
|
272
|
+
});
|
|
273
|
+
return ok({
|
|
274
|
+
ok: false,
|
|
275
|
+
failures,
|
|
276
|
+
summary: `${failures.length} integrity failure(s)`
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
async function loadAggregateIntegrityViolations(config, migrationsDir) {
|
|
280
|
+
try {
|
|
281
|
+
const contractJsonContent = await readFile(resolveContractPath(config), "utf-8");
|
|
282
|
+
const familyInstance = config.family.create(createControlStack(config));
|
|
283
|
+
const declaredExtensions = toDeclaredExtensionsFromRaw(config.extensionPacks ?? []);
|
|
284
|
+
const parsedAppContract = JSON.parse(contractJsonContent);
|
|
285
|
+
return (await loadContractSpaceAggregate({
|
|
286
|
+
migrationsDir,
|
|
287
|
+
deserializeContract: (json) => familyInstance.deserializeContract(json),
|
|
288
|
+
appContract: familyInstance.deserializeContract(parsedAppContract)
|
|
289
|
+
})).checkIntegrity({
|
|
290
|
+
declaredExtensions,
|
|
291
|
+
checkContracts: true
|
|
292
|
+
});
|
|
293
|
+
} catch {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function executeMigrationCheckCommand(target, options, flags, ui) {
|
|
298
|
+
const config = await loadConfig(options.config);
|
|
299
|
+
const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } = resolveMigrationPaths(options.config, config);
|
|
300
|
+
if (!flags.json && !flags.quiet) {
|
|
301
|
+
const details = [{
|
|
302
|
+
label: "config",
|
|
303
|
+
value: configPath
|
|
304
|
+
}, {
|
|
305
|
+
label: "migrations",
|
|
306
|
+
value: appMigrationsRelative
|
|
307
|
+
}];
|
|
308
|
+
if (target) details.push({
|
|
309
|
+
label: "target",
|
|
310
|
+
value: target
|
|
311
|
+
});
|
|
312
|
+
const header = formatStyledHeader({
|
|
313
|
+
command: "migration check",
|
|
314
|
+
description: "Verify artifact and graph integrity",
|
|
315
|
+
details,
|
|
316
|
+
flags
|
|
317
|
+
});
|
|
318
|
+
ui.stderr(header);
|
|
319
|
+
}
|
|
320
|
+
const loadedAggregate = await buildReadAggregate(config, { migrationsDir });
|
|
321
|
+
if (!loadedAggregate.ok) return {
|
|
322
|
+
error: loadedAggregate.failure,
|
|
323
|
+
exitCode: 2
|
|
324
|
+
};
|
|
325
|
+
const spaces = await enumerateCheckSpaces(loadedAggregate.value.aggregate, migrationsDir);
|
|
326
|
+
if (target) return await checkSingleTarget(target, {
|
|
327
|
+
spaces,
|
|
328
|
+
...options.space !== void 0 ? { spaceFilter: options.space } : {},
|
|
329
|
+
appMigrationsDir,
|
|
330
|
+
appMigrationsRelative
|
|
331
|
+
});
|
|
332
|
+
const checkResult = runMigrationCheck({
|
|
333
|
+
spaces,
|
|
334
|
+
...options.space !== void 0 ? { spaceFilter: options.space } : {}
|
|
335
|
+
});
|
|
336
|
+
if (!checkResult.ok) return {
|
|
337
|
+
error: checkResult.failure,
|
|
338
|
+
exitCode: 2
|
|
339
|
+
};
|
|
340
|
+
const failures = [...checkResult.value.failures];
|
|
341
|
+
const allViolations = await loadAggregateIntegrityViolations(config, migrationsDir);
|
|
342
|
+
const scopedViolations = options.space === void 0 ? allViolations : allViolations.filter((v) => v.kind !== "disjointness" && v.spaceId === options.space);
|
|
343
|
+
for (const violation of scopedViolations) failures.push(integrityViolationToCheckFailure(violation, migrationsDir));
|
|
344
|
+
if (failures.length === 0) return {
|
|
345
|
+
result: {
|
|
346
|
+
ok: true,
|
|
347
|
+
failures: [],
|
|
348
|
+
summary: "All checks passed"
|
|
349
|
+
},
|
|
350
|
+
exitCode: 0
|
|
351
|
+
};
|
|
352
|
+
return {
|
|
353
|
+
result: {
|
|
354
|
+
ok: false,
|
|
355
|
+
failures,
|
|
356
|
+
summary: `${failures.length} integrity failure(s)`
|
|
357
|
+
},
|
|
358
|
+
exitCode: 4
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Ranks ref-resolution failure kinds by how informative they are, so a
|
|
363
|
+
* single-target check surfaces the most useful failure across spaces instead of
|
|
364
|
+
* whichever space failed first. `not-found` (the input matched nothing here)
|
|
365
|
+
* says the least; a malformed input, a wrong grammar, or an in-space ambiguity
|
|
366
|
+
* all say more.
|
|
367
|
+
*/
|
|
368
|
+
function refFailureSpecificity(error) {
|
|
369
|
+
switch (error.kind) {
|
|
370
|
+
case "wrong-grammar": return 3;
|
|
371
|
+
case "ambiguous": return 2;
|
|
372
|
+
case "invalid-format": return 1;
|
|
373
|
+
case "not-found": return 0;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Single-target (`check <ref/path>`) mode — resolves a migration reference
|
|
378
|
+
* across all contract spaces (or the one space narrowed by `--space <id>`).
|
|
379
|
+
*
|
|
380
|
+
* Resolution:
|
|
381
|
+
* - filesystem path → find the owning space by checking which space's
|
|
382
|
+
* `migrationsDir` contains the resolved path; falls back to app-relative
|
|
383
|
+
* validation when the path is outside every space dir.
|
|
384
|
+
* - ref → `parseMigrationRef` against each in-scope space; collect every
|
|
385
|
+
* (space, package) hit; 0 hits = not-found, 1 = check it, >1 = ambiguity
|
|
386
|
+
* error (qualify with `--space`).
|
|
387
|
+
*
|
|
388
|
+
* `--space <id>` is validated the same way the holistic path does it:
|
|
389
|
+
* invalid id → `errorInvalidSpaceId`; no on-disk space → `errorSpaceNotFound`.
|
|
390
|
+
*/
|
|
391
|
+
async function checkSingleTarget(target, inputs) {
|
|
392
|
+
const { spaces, spaceFilter, appMigrationsDir, appMigrationsRelative } = inputs;
|
|
393
|
+
if (spaceFilter !== void 0 && !isValidSpaceId(spaceFilter)) return {
|
|
394
|
+
error: errorInvalidSpaceId(spaceFilter),
|
|
395
|
+
exitCode: 2
|
|
396
|
+
};
|
|
397
|
+
if (spaceFilter !== void 0 && !spaces.some((s) => s.spaceId === spaceFilter)) return {
|
|
398
|
+
error: errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()),
|
|
399
|
+
exitCode: 2
|
|
400
|
+
};
|
|
401
|
+
const scopedSpaces = spaceFilter !== void 0 ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;
|
|
402
|
+
let matchedSpace;
|
|
403
|
+
let matchedPkg;
|
|
404
|
+
if (looksLikePath(target)) {
|
|
405
|
+
const resolvedPath = resolveTargetPathAcrossSpaces(target, scopedSpaces);
|
|
406
|
+
if (resolvedPath !== null) for (const space of scopedSpaces) {
|
|
407
|
+
const found = findPackageByDirPath(space.packages, resolvedPath);
|
|
408
|
+
if (found) {
|
|
409
|
+
matchedSpace = space;
|
|
410
|
+
matchedPkg = found;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);
|
|
416
|
+
if (!resolved.ok) return {
|
|
417
|
+
error: resolved.failure,
|
|
418
|
+
exitCode: 2
|
|
419
|
+
};
|
|
420
|
+
const appSpace = scopedSpaces.find((s) => s.spaceId === "app");
|
|
421
|
+
if (appSpace) {
|
|
422
|
+
matchedSpace = appSpace;
|
|
423
|
+
matchedPkg = findPackageByDirPath(appSpace.packages, resolved.value);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
} else {
|
|
427
|
+
const hits = [];
|
|
428
|
+
let bestParseFailure;
|
|
429
|
+
for (const space of scopedSpaces) {
|
|
430
|
+
const migResult = parseMigrationRef(target, {
|
|
431
|
+
graph: space.graph,
|
|
432
|
+
refs: space.refs
|
|
433
|
+
});
|
|
434
|
+
if (!migResult.ok) {
|
|
435
|
+
if (bestParseFailure === void 0 || refFailureSpecificity(migResult.failure) > refFailureSpecificity(bestParseFailure)) bestParseFailure = migResult.failure;
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
const pkg = space.packages.find((p) => p.metadata.migrationHash === migResult.value.migrationHash);
|
|
439
|
+
if (pkg) hits.push({
|
|
440
|
+
space,
|
|
441
|
+
pkg
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (hits.length > 1) return {
|
|
445
|
+
error: errorAmbiguousMigrationRef(target, hits.map((h) => h.space.spaceId)),
|
|
446
|
+
exitCode: 2
|
|
447
|
+
};
|
|
448
|
+
if (hits.length === 1) {
|
|
449
|
+
matchedSpace = hits[0].space;
|
|
450
|
+
matchedPkg = hits[0].pkg;
|
|
451
|
+
} else if (bestParseFailure !== void 0) return {
|
|
452
|
+
error: mapRefResolutionError(bestParseFailure),
|
|
453
|
+
exitCode: 2
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
if (!matchedPkg || !matchedSpace) return {
|
|
457
|
+
result: {
|
|
458
|
+
ok: false,
|
|
459
|
+
failures: [],
|
|
460
|
+
summary: `Migration package for "${target}" not found on disk`
|
|
461
|
+
},
|
|
462
|
+
exitCode: 2
|
|
463
|
+
};
|
|
464
|
+
const failures = [...checkManifestFilesPresent(matchedSpace)];
|
|
465
|
+
for (const f of ["migration.json", "ops.json"]) {
|
|
466
|
+
const fail = checkFileExists(matchedSpace.spaceId, matchedPkg.dirPath, matchedPkg.dirName, f);
|
|
467
|
+
if (fail) failures.push(fail);
|
|
468
|
+
}
|
|
469
|
+
const verification = verifyMigrationHash(matchedPkg);
|
|
470
|
+
if (!verification.ok) failures.push({
|
|
471
|
+
space: matchedSpace.spaceId,
|
|
472
|
+
code: "PN-MIG-CHECK-001",
|
|
473
|
+
where: migrationFileRelative(matchedPkg.dirPath, "migration.json"),
|
|
474
|
+
why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,
|
|
475
|
+
fix: "Re-emit the migration package or restore from version control."
|
|
476
|
+
});
|
|
477
|
+
const snapshotFailure = checkSnapshotConsistency(matchedSpace.spaceId, matchedPkg);
|
|
478
|
+
if (snapshotFailure) failures.push(snapshotFailure);
|
|
479
|
+
const resolvedSpaceId = matchedSpace.spaceId !== "app" ? matchedSpace.spaceId : void 0;
|
|
480
|
+
if (failures.length === 0) return {
|
|
481
|
+
result: {
|
|
482
|
+
ok: true,
|
|
483
|
+
failures: [],
|
|
484
|
+
summary: "All checks passed"
|
|
485
|
+
},
|
|
486
|
+
exitCode: 0,
|
|
487
|
+
...ifDefined("resolvedSpaceId", resolvedSpaceId)
|
|
488
|
+
};
|
|
489
|
+
return {
|
|
490
|
+
result: {
|
|
491
|
+
ok: false,
|
|
492
|
+
failures,
|
|
493
|
+
summary: `${failures.length} integrity failure(s)`
|
|
494
|
+
},
|
|
495
|
+
exitCode: 4,
|
|
496
|
+
...ifDefined("resolvedSpaceId", resolvedSpaceId)
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function createMigrationCheckCommand() {
|
|
500
|
+
const command = new Command("check");
|
|
501
|
+
setCommandDescriptions(command, "Verify artifact and graph integrity", "Validates that on-disk migration packages are internally consistent\n(hashes match, manifests are complete) and that the graph is well-formed\n(edges connect, refs point at valid nodes). The whole-graph check spans\nevery contract space by default; pass --space <id> to narrow to one. A\nmigration reference checks a single package, resolved across all contract\nspaces (narrow with --space; an ambiguous reference is a precondition failure).\nOffline — does not consult the database.\nExit codes: 0 = all checks passed, 2 = precondition failed\n(unresolved target or unknown --space), 4 = integrity failure(s) found.");
|
|
502
|
+
setCommandExamples(command, [
|
|
503
|
+
"prisma-next migration check",
|
|
504
|
+
"prisma-next migration check --space app",
|
|
505
|
+
"prisma-next migration check 20260101-add-users",
|
|
506
|
+
"prisma-next migration check 20260101-add-users --space app",
|
|
507
|
+
"prisma-next migration check --json"
|
|
508
|
+
]);
|
|
509
|
+
setCommandSeeAlso(command, [
|
|
510
|
+
{
|
|
511
|
+
verb: "migration status",
|
|
512
|
+
oneLiner: "Show migration path and pending status"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
verb: "migration list",
|
|
516
|
+
oneLiner: "List on-disk migrations"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
verb: "migration graph",
|
|
520
|
+
oneLiner: "Show the migration graph topology"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
verb: "migration show",
|
|
524
|
+
oneLiner: "Display migration package contents"
|
|
525
|
+
}
|
|
526
|
+
]);
|
|
527
|
+
command.exitOverride();
|
|
528
|
+
addGlobalOptions(command).argument("[target]", "Migration reference: directory name, hash/prefix, ref, or path").option("--config <path>", "Path to prisma-next.config.ts").option("--space <id>", "Narrow output to a single contract space").action(async (target, options) => {
|
|
529
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
530
|
+
const ui = createTerminalUI(flags);
|
|
531
|
+
let outcome;
|
|
532
|
+
try {
|
|
533
|
+
outcome = await executeMigrationCheckCommand(target, options, flags, ui);
|
|
534
|
+
} catch (error) {
|
|
535
|
+
outcome = {
|
|
536
|
+
result: {
|
|
537
|
+
ok: false,
|
|
538
|
+
failures: [],
|
|
539
|
+
summary: error instanceof Error ? error.message : String(error)
|
|
540
|
+
},
|
|
541
|
+
exitCode: 2
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
if (outcome.error) {
|
|
545
|
+
const envelope = outcome.error.toEnvelope();
|
|
546
|
+
if (flags.json) ui.output(formatErrorJson(envelope));
|
|
547
|
+
else if (!flags.quiet) ui.error(formatErrorOutput(envelope, flags));
|
|
548
|
+
process.exit(outcome.exitCode);
|
|
549
|
+
}
|
|
550
|
+
const result = outcome.result ?? {
|
|
551
|
+
ok: false,
|
|
552
|
+
failures: [],
|
|
553
|
+
summary: "No check result produced"
|
|
554
|
+
};
|
|
555
|
+
if (flags.json) ui.output(JSON.stringify(result, null, 2));
|
|
556
|
+
else if (!flags.quiet) if (result.ok) {
|
|
557
|
+
const spaceSuffix = outcome.resolvedSpaceId !== void 0 ? ` (space: ${outcome.resolvedSpaceId})` : "";
|
|
558
|
+
ui.log(`✔ ${result.summary}${spaceSuffix}`);
|
|
559
|
+
} else {
|
|
560
|
+
for (const f of result.failures) {
|
|
561
|
+
ui.log(`✗ [${f.code}] ${f.where}: ${f.why}`);
|
|
562
|
+
ui.log(` fix: ${f.fix}`);
|
|
563
|
+
}
|
|
564
|
+
ui.log(`\n${result.summary}`);
|
|
565
|
+
}
|
|
566
|
+
process.exit(outcome.exitCode);
|
|
567
|
+
});
|
|
568
|
+
return command;
|
|
569
|
+
}
|
|
570
|
+
//#endregion
|
|
571
|
+
export { enumerateCheckSpaces as n, runMigrationCheck as r, createMigrationCheckCommand as t };
|
|
572
|
+
|
|
573
|
+
//# sourceMappingURL=migration-check-BxWlQBOs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-check-BxWlQBOs.mjs","names":["migrationPathRelative","migrationFileRelative"],"sources":["../src/utils/integrity-violation-to-check-failure.ts","../src/commands/migration-check.ts"],"sourcesContent":["import type { IntegrityViolation } from '@prisma-next/migration-tools/aggregate';\nimport { join, relative } from 'pathe';\nimport type { CheckFailure } from '../commands/json/schemas';\n\nexport type { CheckFailure } from '../commands/json/schemas';\n\nfunction migrationPathRelative(dirPath: string): string {\n return relative(process.cwd(), dirPath);\n}\n\nfunction migrationFileRelative(dirPath: string, fileName: string): string {\n return join(migrationPathRelative(dirPath), fileName);\n}\n\n/**\n * Map one {@link IntegrityViolation} onto a `migration check` failure row.\n * Sole catalogue mapping from integrity violations to `PN-MIG-CHECK-*`.\n */\nexport function integrityViolationToCheckFailure(\n violation: IntegrityViolation,\n migrationsDir: string,\n): CheckFailure {\n const spaceRelative = (spaceId: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId));\n const packageRelative = (spaceId: string, dirName: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId, dirName));\n const refRelative = (spaceId: string, refName: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId, 'refs', `${refName}.json`));\n\n switch (violation.kind) {\n case 'hashMismatch':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-001',\n where: migrationFileRelative(\n join(migrationsDir, violation.spaceId, violation.dirName),\n 'migration.json',\n ),\n why: `Stored hash ${violation.stored} does not match recomputed hash ${violation.computed}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n case 'providedInvariantsMismatch':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-002',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" providedInvariants in migration.json disagrees with ops.json.`,\n fix: 'Re-emit the migration package so migration.json and ops.json agree.',\n };\n case 'packageUnloadable':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-002',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" could not be loaded: ${violation.detail}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n case 'sameSourceAndTarget':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-007',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" in space \"${violation.spaceId}\" has source equal to target (${violation.hash}) with no data invariant — a true no-op self-edge.`,\n fix: 'Add a data operation if this self-edge was meant to carry a data invariant, or delete the migration if it is a true no-op.',\n };\n case 'orphanSpaceDir':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-008',\n where: spaceRelative(violation.spaceId),\n why: `Contract-space directory \"${violation.spaceId}\" exists on disk but no extension declares it.`,\n fix: 'Remove the orphan directory, or declare the extension in `extensionPacks`.',\n };\n case 'declaredButUnmigrated':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-009',\n where: spaceRelative(violation.spaceId),\n why: `Extension \"${violation.spaceId}\" is declared in \\`extensionPacks\\` but has no on-disk migrations directory.`,\n fix: 'Re-emit the extension contract-space artefacts with `prisma-next contract emit` and migration planning, or remove the extension from `extensionPacks` if it is unused.',\n };\n case 'headRefMissing':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-010',\n where: refRelative(violation.spaceId, 'head'),\n why: `Head ref \\`refs/head.json\\` is missing for contract space \"${violation.spaceId}\".`,\n fix: 'Re-emit the contract-space migrations and head ref artefacts, or restore `refs/head.json` from version control.',\n };\n case 'headRefNotInGraph':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-011',\n where: refRelative(violation.spaceId, 'head'),\n why: `Head ref ${violation.hash} for contract space \"${violation.spaceId}\" is not present in its migration graph.`,\n fix: 'Re-emit the contract space migrations, or restore the missing migration package.',\n };\n case 'refUnreadable':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-012',\n where: refRelative(violation.spaceId, violation.refName),\n why: `Ref \"${violation.refName}\" for contract space \"${violation.spaceId}\" is unreadable: ${violation.detail}`,\n fix: 'Repair or remove the corrupt ref file.',\n };\n case 'targetMismatch':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-013',\n where: spaceRelative(violation.spaceId),\n why: `Contract space \"${violation.spaceId}\" targets \"${violation.actual}\" but the project targets \"${violation.expected}\".`,\n fix: 'Update the extension to target the configured database, or change the project target.',\n };\n case 'disjointness':\n return {\n space: 'app',\n code: 'PN-MIG-CHECK-014',\n where: migrationPathRelative(migrationsDir),\n why: `Storage element \"${violation.element}\" is claimed by multiple contract spaces: ${violation.claimedBy.join(', ')}.`,\n fix: 'Update the contracts so each storage element is owned by exactly one contract space.',\n };\n case 'contractUnreadable':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-015',\n where: migrationFileRelative(join(migrationsDir, violation.spaceId), 'contract.json'),\n why: `Contract for space \"${violation.spaceId}\" is unreadable: ${violation.detail}`,\n fix: 'Re-emit the extension contract artefacts, or fix the descriptor producing the invalid contract.',\n };\n case 'duplicateMigrationHash':\n return {\n space: violation.spaceId,\n code: 'PN-MIG-CHECK-016',\n where: spaceRelative(violation.spaceId),\n why: `Multiple migrations in space \"${violation.spaceId}\" share migrationHash \"${violation.migrationHash}\" (${violation.dirNames.join(', ')}).`,\n fix: 'Re-emit one of the conflicting packages so each migrationHash is unique.',\n };\n }\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport type {\n ContractSpaceAggregate,\n IntegrityViolation,\n} from '@prisma-next/migration-tools/aggregate';\nimport { loadContractSpaceAggregate } from '@prisma-next/migration-tools/aggregate';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport { verifyMigrationHash } from '@prisma-next/migration-tools/hash';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport {\n parseMigrationRef,\n type RefResolutionError,\n} from '@prisma-next/migration-tools/ref-resolution';\nimport type { Refs } from '@prisma-next/migration-tools/refs';\nimport {\n isValidSpaceId,\n listContractSpaceDirectories,\n RESERVED_SPACE_SUBDIR_NAMES,\n spaceMigrationDirectory,\n spaceRefsDirectory,\n} from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorAmbiguousMigrationRef,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { toDeclaredExtensionsFromRaw } from '../utils/extension-pack-inputs';\nimport { formatErrorJson, formatErrorOutput } from '../utils/formatters/errors';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { integrityViolationToCheckFailure } from '../utils/integrity-violation-to-check-failure';\nimport {\n findPackageByDirPath,\n looksLikePath,\n resolveAppTargetPath,\n resolveTargetPathAcrossSpaces,\n} from '../utils/migration-path-target';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\nimport type { CheckFailure, MigrationCheckResult } from './json/schemas';\nimport { INTEGRITY_FAILED, OK, PRECONDITION } from './migration-check/exit-codes';\n\ninterface MigrationCheckOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n}\n\nexport type { CheckFailure, MigrationCheckResult } from './json/schemas';\nexport { migrationCheckResultSchema } from './json/schemas';\n\nfunction migrationPathRelative(dirPath: string): string {\n return relative(process.cwd(), dirPath);\n}\n\nfunction migrationFileRelative(dirPath: string, fileName: string): string {\n return join(migrationPathRelative(dirPath), fileName);\n}\n\nfunction checkFileExists(\n spaceId: string,\n dirPath: string,\n dirName: string,\n fileName: string,\n): CheckFailure | null {\n if (!existsSync(join(dirPath, fileName))) {\n return {\n space: spaceId,\n code: 'PN-MIG-CHECK-002',\n where: migrationFileRelative(dirPath, fileName),\n why: `${fileName} is missing from ${dirName}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n }\n return null;\n}\n\nfunction checkSnapshotConsistency(\n spaceId: string,\n pkg: OnDiskMigrationPackage,\n): CheckFailure | null {\n const endContractPath = join(pkg.dirPath, 'end-contract.json');\n if (!existsSync(endContractPath)) return null;\n try {\n const raw = JSON.parse(readFileSync(endContractPath, 'utf-8')) as Record<string, unknown>;\n const storage = raw['storage'] as Record<string, unknown> | undefined;\n const snapshotHash = storage?.['storageHash'];\n if (typeof snapshotHash === 'string' && snapshotHash !== pkg.metadata.to) {\n return {\n space: spaceId,\n code: 'PN-MIG-CHECK-005',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" declares to=${pkg.metadata.to} but end-contract.json has storageHash=${snapshotHash}`,\n fix: 'Re-emit the migration package so migration.json and end-contract.json agree.',\n };\n }\n } catch {\n return {\n space: spaceId,\n code: 'PN-MIG-CHECK-006',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" has an unparseable end-contract.json.`,\n fix: 'Re-emit the migration package to repair the snapshot file.',\n };\n }\n return null;\n}\n\n/**\n * One contract space's on-disk state, resolved for the explicit graph\n * checks `runMigrationCheck` runs per space: the space's migration\n * packages, its user-authored refs, its induced graph, and the absolute\n * `migrations/<space>/` + `migrations/<space>/refs/` directories the\n * file-existence and dangling-ref `where` paths are derived from.\n */\nexport interface CheckSpace {\n readonly spaceId: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly refs: Refs;\n readonly graph: MigrationGraph;\n readonly migrationsDir: string;\n readonly refsDir: string;\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the\n * {@link CheckSpace} rows the multi-space check iterates — one per on-disk\n * contract-space directory, in the aggregate's `app`-first ordering. Mirrors\n * `migration list`'s `migrationSpaceListEntriesFromAggregate`: space\n * membership matches the on-disk directories, package / ref / graph data come\n * from `aggregate.space(id)`.\n */\nexport async function enumerateCheckSpaces(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly CheckSpace[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n const onDiskSpaceIds = new Set(\n candidateDirs.filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name)).filter(isValidSpaceId),\n );\n const spaces: CheckSpace[] = [];\n for (const member of aggregate.spaces()) {\n const spaceId = member.spaceId;\n if (!isValidSpaceId(spaceId)) continue;\n if (!onDiskSpaceIds.has(spaceId)) continue;\n const migrationsDir = spaceMigrationDirectory(projectMigrationsDir, spaceId);\n spaces.push({\n spaceId,\n packages: member.packages,\n refs: member.refs,\n graph: member.graph(),\n migrationsDir,\n refsDir: spaceRefsDirectory(migrationsDir),\n });\n }\n return spaces;\n}\n\nfunction checkManifestFilesPresent(space: CheckSpace): readonly CheckFailure[] {\n if (!existsSync(space.migrationsDir)) return [];\n const loadedDirNames = new Set(space.packages.map((p) => p.dirName));\n const failures: CheckFailure[] = [];\n let entries: string[];\n try {\n entries = readdirSync(space.migrationsDir);\n } catch {\n return failures;\n }\n for (const entry of entries) {\n if (entry.startsWith('.') || entry.startsWith('_') || entry === 'refs') continue;\n const entryPath = join(space.migrationsDir, entry);\n try {\n if (!statSync(entryPath).isDirectory()) continue;\n } catch {\n continue;\n }\n if (!loadedDirNames.has(entry)) {\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(space.spaceId, entryPath, entry, f);\n if (fail) failures.push(fail);\n }\n }\n }\n return failures;\n}\n\nfunction checkReachability(space: CheckSpace): readonly CheckFailure[] {\n const allToHashes = new Set(space.packages.map((p) => p.metadata.to));\n const failures: CheckFailure[] = [];\n for (const pkg of space.packages) {\n const isReachable =\n pkg.metadata.from === null ||\n allToHashes.has(pkg.metadata.from) ||\n pkg.metadata.from === 'sha256:empty';\n if (!isReachable) {\n failures.push({\n space: space.spaceId,\n code: 'PN-MIG-CHECK-003',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" starts from ${pkg.metadata.from} which no other migration produces`,\n fix: 'This migration is unreachable in the graph. Delete it or re-emit a connecting migration.',\n });\n }\n }\n return failures;\n}\n\nfunction checkDanglingRefs(space: CheckSpace): readonly CheckFailure[] {\n const failures: CheckFailure[] = [];\n for (const [name, entry] of Object.entries(space.refs)) {\n if (!space.graph.nodes.has(entry.hash)) {\n failures.push({\n space: space.spaceId,\n code: 'PN-MIG-CHECK-004',\n where: relative(process.cwd(), join(space.refsDir, `${name}.json`)),\n why: `Ref \"${name}\" points at ${entry.hash} which does not exist in the migration graph`,\n fix: `Update the ref with \\`prisma-next ref set ${name} <valid-hash>\\` or delete it.`,\n });\n }\n }\n return failures;\n}\n\nfunction checkSpace(space: CheckSpace): readonly CheckFailure[] {\n return [\n ...checkManifestFilesPresent(space),\n ...space.packages\n .map((pkg) => checkSnapshotConsistency(space.spaceId, pkg))\n .filter((f): f is CheckFailure => f !== null),\n ...checkReachability(space),\n ...checkDanglingRefs(space),\n ];\n}\n\n/**\n * Inputs for {@link runMigrationCheck} — the multi-space policy core of\n * the holistic (no-arg) `migration check`. Enumeration is supplied by the\n * caller (the CLI shell builds it from {@link enumerateCheckSpaces}); the\n * core does not touch config, flags, or streams.\n */\nexport interface RunMigrationCheckInputs {\n readonly spaces: readonly CheckSpace[];\n readonly spaceFilter?: string;\n}\n\n/**\n * Policy core of the holistic `migration check`: validates `--space`,\n * narrows the pre-enumerated spaces, and runs the per-space explicit graph\n * checks (file-existence, snapshot consistency, reachability, dangling\n * refs), aggregating every failure into one {@link MigrationCheckResult}.\n *\n * `--space` validation mirrors `migration list`: an invalid id →\n * {@link errorInvalidSpaceId}; an id with no on-disk space →\n * {@link errorSpaceNotFound}. Both map to exit `PRECONDITION` at the shell.\n * Aggregate-integrity violations (which already span every space) are folded\n * in by the caller, not here.\n */\nexport function runMigrationCheck(\n inputs: RunMigrationCheckInputs,\n): Result<MigrationCheckResult, CliStructuredError> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n const failures = scopedSpaces.flatMap(checkSpace);\n if (failures.length === 0) {\n return ok({ ok: true, failures: [], summary: 'All checks passed' });\n }\n return ok({ ok: false, failures, summary: `${failures.length} integrity failure(s)` });\n}\n\nasync function loadAggregateIntegrityViolations(\n config: Awaited<ReturnType<typeof loadConfig>>,\n migrationsDir: string,\n): Promise<readonly IntegrityViolation[]> {\n try {\n const contractJsonContent = await readFile(resolveContractPath(config), 'utf-8');\n const familyInstance = config.family.create(createControlStack(config));\n const declaredExtensions = toDeclaredExtensionsFromRaw(config.extensionPacks ?? []);\n\n const parsedAppContract: unknown = JSON.parse(contractJsonContent);\n const aggregate = await loadContractSpaceAggregate({\n migrationsDir,\n deserializeContract: (json: unknown) => familyInstance.deserializeContract(json),\n appContract: familyInstance.deserializeContract(parsedAppContract),\n });\n return aggregate.checkIntegrity({ declaredExtensions, checkContracts: true });\n } catch {\n return [];\n }\n}\n\ninterface MigrationCheckOutcome {\n readonly result?: MigrationCheckResult;\n readonly error?: CliStructuredError;\n readonly exitCode: number;\n readonly resolvedSpaceId?: string;\n}\n\nasync function executeMigrationCheckCommand(\n target: string | undefined,\n options: MigrationCheckOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<MigrationCheckOutcome> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration check',\n description: 'Verify artifact and graph integrity',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n const loadedAggregate = await buildReadAggregate(config, { migrationsDir });\n if (!loadedAggregate.ok) {\n return { error: loadedAggregate.failure, exitCode: PRECONDITION };\n }\n\n const spaces = await enumerateCheckSpaces(loadedAggregate.value.aggregate, migrationsDir);\n\n if (target) {\n return await checkSingleTarget(target, {\n spaces,\n ...(options.space !== undefined ? { spaceFilter: options.space } : {}),\n appMigrationsDir,\n appMigrationsRelative,\n });\n }\n\n const checkResult = runMigrationCheck({\n spaces,\n ...(options.space !== undefined ? { spaceFilter: options.space } : {}),\n });\n if (!checkResult.ok) {\n return { error: checkResult.failure, exitCode: PRECONDITION };\n }\n\n const failures: CheckFailure[] = [...checkResult.value.failures];\n const allViolations = await loadAggregateIntegrityViolations(config, migrationsDir);\n const scopedViolations =\n options.space === undefined\n ? allViolations\n : allViolations.filter((v) => v.kind !== 'disjointness' && v.spaceId === options.space);\n for (const violation of scopedViolations) {\n failures.push(integrityViolationToCheckFailure(violation, migrationsDir));\n }\n\n if (failures.length === 0) {\n return {\n result: { ok: true, failures: [], summary: 'All checks passed' },\n exitCode: OK,\n };\n }\n\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n };\n}\n\ninterface SingleTargetInputs {\n readonly spaces: readonly CheckSpace[];\n readonly spaceFilter?: string;\n readonly appMigrationsDir: string;\n readonly appMigrationsRelative: string;\n}\n\n/**\n * Ranks ref-resolution failure kinds by how informative they are, so a\n * single-target check surfaces the most useful failure across spaces instead of\n * whichever space failed first. `not-found` (the input matched nothing here)\n * says the least; a malformed input, a wrong grammar, or an in-space ambiguity\n * all say more.\n */\nfunction refFailureSpecificity(error: RefResolutionError): number {\n switch (error.kind) {\n case 'wrong-grammar':\n return 3;\n case 'ambiguous':\n return 2;\n case 'invalid-format':\n return 1;\n case 'not-found':\n return 0;\n }\n}\n\n/**\n * Single-target (`check <ref/path>`) mode — resolves a migration reference\n * across all contract spaces (or the one space narrowed by `--space <id>`).\n *\n * Resolution:\n * - filesystem path → find the owning space by checking which space's\n * `migrationsDir` contains the resolved path; falls back to app-relative\n * validation when the path is outside every space dir.\n * - ref → `parseMigrationRef` against each in-scope space; collect every\n * (space, package) hit; 0 hits = not-found, 1 = check it, >1 = ambiguity\n * error (qualify with `--space`).\n *\n * `--space <id>` is validated the same way the holistic path does it:\n * invalid id → `errorInvalidSpaceId`; no on-disk space → `errorSpaceNotFound`.\n */\nasync function checkSingleTarget(\n target: string,\n inputs: SingleTargetInputs,\n): Promise<MigrationCheckOutcome> {\n const { spaces, spaceFilter, appMigrationsDir, appMigrationsRelative } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return { error: errorInvalidSpaceId(spaceFilter), exitCode: PRECONDITION };\n }\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return {\n error: errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()),\n exitCode: PRECONDITION,\n };\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n let matchedSpace: CheckSpace | undefined;\n let matchedPkg: OnDiskMigrationPackage | undefined;\n\n if (looksLikePath(target)) {\n const resolvedPath = resolveTargetPathAcrossSpaces(target, scopedSpaces);\n if (resolvedPath !== null) {\n for (const space of scopedSpaces) {\n const found = findPackageByDirPath(space.packages, resolvedPath);\n if (found) {\n matchedSpace = space;\n matchedPkg = found;\n break;\n }\n }\n } else {\n // Path outside every space dir — fall back to app-relative validation\n const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);\n if (!resolved.ok) {\n return { error: resolved.failure, exitCode: PRECONDITION };\n }\n const appSpace = scopedSpaces.find((s) => s.spaceId === 'app');\n if (appSpace) {\n matchedSpace = appSpace;\n matchedPkg = findPackageByDirPath(appSpace.packages, resolved.value);\n }\n }\n } else {\n // Ref resolution: try each in-scope space, collect all hits.\n const hits: Array<{ space: CheckSpace; pkg: OnDiskMigrationPackage }> = [];\n let bestParseFailure: RefResolutionError | undefined;\n for (const space of scopedSpaces) {\n const migResult = parseMigrationRef(target, { graph: space.graph, refs: space.refs });\n if (!migResult.ok) {\n // Keep scanning — a later space may hold a hit that must not be discarded.\n // When no space yields a hit, keep the most informative failure rather than\n // whichever space failed first (the kind is space-dependent).\n if (\n bestParseFailure === undefined ||\n refFailureSpecificity(migResult.failure) > refFailureSpecificity(bestParseFailure)\n ) {\n bestParseFailure = migResult.failure;\n }\n continue;\n }\n const pkg = space.packages.find(\n (p) => p.metadata.migrationHash === migResult.value.migrationHash,\n );\n if (pkg) {\n hits.push({ space, pkg });\n }\n }\n\n if (hits.length > 1) {\n const spaceIds = hits.map((h) => h.space.spaceId);\n return {\n error: errorAmbiguousMigrationRef(target, spaceIds),\n exitCode: PRECONDITION,\n };\n }\n\n if (hits.length === 1) {\n matchedSpace = hits[0]!.space;\n matchedPkg = hits[0]!.pkg;\n } else if (bestParseFailure !== undefined) {\n // The ref didn't resolve in any in-scope space — surface the most informative\n // parse failure through the shared ref-resolution envelope (PN-RUN-3000) the\n // earlier work established, rather than a bespoke string. (Ref-resolved-but-\n // no-package falls through to the \"not found on disk\" result below.)\n return { error: mapRefResolutionError(bestParseFailure), exitCode: PRECONDITION };\n }\n }\n\n if (!matchedPkg || !matchedSpace) {\n return {\n result: {\n ok: false,\n failures: [],\n summary: `Migration package for \"${target}\" not found on disk`,\n },\n exitCode: PRECONDITION,\n };\n }\n\n const failures: CheckFailure[] = [...checkManifestFilesPresent(matchedSpace)];\n\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(matchedSpace.spaceId, matchedPkg.dirPath, matchedPkg.dirName, f);\n if (fail) failures.push(fail);\n }\n\n const verification = verifyMigrationHash(matchedPkg);\n if (!verification.ok) {\n failures.push({\n space: matchedSpace.spaceId,\n code: 'PN-MIG-CHECK-001',\n where: migrationFileRelative(matchedPkg.dirPath, 'migration.json'),\n why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,\n fix: 'Re-emit the migration package or restore from version control.',\n });\n }\n\n const snapshotFailure = checkSnapshotConsistency(matchedSpace.spaceId, matchedPkg);\n if (snapshotFailure) failures.push(snapshotFailure);\n\n const resolvedSpaceId = matchedSpace.spaceId !== 'app' ? matchedSpace.spaceId : undefined;\n\n if (failures.length === 0) {\n return {\n result: { ok: true, failures: [], summary: 'All checks passed' },\n exitCode: OK,\n ...ifDefined('resolvedSpaceId', resolvedSpaceId),\n };\n }\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n ...ifDefined('resolvedSpaceId', resolvedSpaceId),\n };\n}\n\nexport function createMigrationCheckCommand(): Command {\n const command = new Command('check');\n setCommandDescriptions(\n command,\n 'Verify artifact and graph integrity',\n 'Validates that on-disk migration packages are internally consistent\\n' +\n '(hashes match, manifests are complete) and that the graph is well-formed\\n' +\n '(edges connect, refs point at valid nodes). The whole-graph check spans\\n' +\n 'every contract space by default; pass --space <id> to narrow to one. A\\n' +\n 'migration reference checks a single package, resolved across all contract\\n' +\n 'spaces (narrow with --space; an ambiguous reference is a precondition failure).\\n' +\n 'Offline — does not consult the database.\\n' +\n 'Exit codes: 0 = all checks passed, 2 = precondition failed\\n' +\n '(unresolved target or unknown --space), 4 = integrity failure(s) found.',\n );\n setCommandExamples(command, [\n 'prisma-next migration check',\n 'prisma-next migration check --space app',\n 'prisma-next migration check 20260101-add-users',\n 'prisma-next migration check 20260101-add-users --space app',\n 'prisma-next migration check --json',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\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 command.exitOverride();\n addGlobalOptions(command)\n .argument('[target]', 'Migration reference: directory name, hash/prefix, ref, or path')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--space <id>', 'Narrow output to a single contract space')\n .action(async (target: string | undefined, options: MigrationCheckOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n let outcome: MigrationCheckOutcome;\n try {\n outcome = await executeMigrationCheckCommand(target, options, flags, ui);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n outcome = {\n result: { ok: false, failures: [], summary: msg },\n exitCode: PRECONDITION,\n };\n }\n\n if (outcome.error) {\n const envelope = outcome.error.toEnvelope();\n if (flags.json) {\n ui.output(formatErrorJson(envelope));\n } else if (!flags.quiet) {\n ui.error(formatErrorOutput(envelope, flags));\n }\n process.exit(outcome.exitCode);\n }\n\n const result = outcome.result ?? {\n ok: false,\n failures: [],\n summary: 'No check result produced',\n };\n\n if (flags.json) {\n ui.output(JSON.stringify(result, null, 2));\n } else if (!flags.quiet) {\n if (result.ok) {\n const spaceSuffix =\n outcome.resolvedSpaceId !== undefined ? ` (space: ${outcome.resolvedSpaceId})` : '';\n ui.log(`✔ ${result.summary}${spaceSuffix}`);\n } else {\n for (const f of result.failures) {\n ui.log(`✗ [${f.code}] ${f.where}: ${f.why}`);\n ui.log(` fix: ${f.fix}`);\n }\n ui.log(`\\n${result.summary}`);\n }\n }\n\n process.exit(outcome.exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|