prisma-next 0.5.0-dev.9 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-errors-B9OBbled.d.mts +3 -0
- package/dist/cli-errors-D3_sMh2K.mjs +33 -0
- package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
- package/dist/cli.mjs +16 -78
- package/dist/cli.mjs.map +1 -1
- package/dist/client-BCnP7cHo.mjs +1485 -0
- package/dist/client-BCnP7cHo.mjs.map +1 -0
- package/dist/{result-handler-Ba3zWQsI.mjs → command-helpers-BeZHkxV8.mjs} +70 -47
- package/dist/command-helpers-BeZHkxV8.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +2 -4
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +2 -4
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +16 -13
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +6 -7
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +9 -9
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +15 -13
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -321
- package/dist/commands/migration-apply.d.mts +28 -13
- package/dist/commands/migration-apply.d.mts.map +1 -1
- package/dist/commands/migration-apply.mjs +55 -151
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts +0 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +34 -40
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +33 -6
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +2 -348
- package/dist/commands/migration-ref.d.mts +1 -1
- package/dist/commands/migration-ref.d.mts.map +1 -1
- package/dist/commands/migration-ref.mjs +8 -12
- package/dist/commands/migration-ref.mjs.map +1 -1
- package/dist/commands/migration-show.d.mts +64 -10
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +166 -60
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +126 -5
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -4
- package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
- package/dist/config-loader.d.mts +0 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/config-loader.mjs +2 -3
- package/dist/contract-emit-9DBda5Ou.mjs +150 -0
- package/dist/contract-emit-9DBda5Ou.mjs.map +1 -0
- package/dist/contract-emit-B77TsJqf.mjs +327 -0
- package/dist/contract-emit-B77TsJqf.mjs.map +1 -0
- package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-Dani0mMW.mjs} +4 -6
- package/dist/contract-enrichment-Dani0mMW.mjs.map +1 -0
- package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-ByxhPjpW.mjs} +13 -22
- package/dist/contract-infer-ByxhPjpW.mjs.map +1 -0
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
- package/dist/db-verify-Czm5T-J4.mjs +404 -0
- package/dist/db-verify-Czm5T-J4.mjs.map +1 -0
- package/dist/exports/config-types.mjs +1 -2
- package/dist/exports/control-api.d.mts +101 -586
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +4 -6
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +28 -30
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts +2 -4
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +2 -3
- package/dist/{framework-components-Cr--XBKy.mjs → framework-components-ChqVUxR-.mjs} +3 -4
- package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-ChqVUxR-.mjs.map} +1 -1
- package/dist/global-flags-Icqpxk23.d.mts +12 -0
- package/dist/global-flags-Icqpxk23.d.mts.map +1 -0
- package/dist/helpers-eqdN8tH6.mjs +25 -0
- package/dist/helpers-eqdN8tH6.mjs.map +1 -0
- package/dist/{init-C5220SY9.mjs → init-DETSgw3h.mjs} +40 -49
- package/dist/init-DETSgw3h.mjs.map +1 -0
- package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-DxdBd4Er.mjs} +10 -11
- package/dist/inspect-live-schema-DxdBd4Er.mjs.map +1 -0
- package/dist/migration-cli.d.mts +41 -12
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +309 -86
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-BdV8JYXV.mjs} +8 -9
- package/dist/migration-command-scaffold-BdV8JYXV.mjs.map +1 -0
- package/dist/migration-plan-mRu5K81L.mjs +494 -0
- package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
- package/dist/{migration-status-DUMiH8_G.mjs → migration-status-By9G5p2H.mjs} +270 -65
- package/dist/migration-status-By9G5p2H.mjs.map +1 -0
- package/dist/migrations-CTsyBXCA.mjs +229 -0
- package/dist/migrations-CTsyBXCA.mjs.map +1 -0
- package/dist/{output-BpcQrnnq.mjs → output-B16Kefzx.mjs} +9 -3
- package/dist/output-B16Kefzx.mjs.map +1 -0
- package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DFfvZcYL.mjs} +2 -2
- package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DFfvZcYL.mjs.map} +1 -1
- package/dist/result-handler-rmPVKIP2.mjs +25 -0
- package/dist/result-handler-rmPVKIP2.mjs.map +1 -0
- package/dist/rolldown-runtime-twds-ZHy.mjs +14 -0
- package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-C_hFNbAn.mjs} +4 -28
- package/dist/terminal-ui-C_hFNbAn.mjs.map +1 -0
- package/dist/types-LItU7E4l.d.mts +856 -0
- package/dist/types-LItU7E4l.d.mts.map +1 -0
- package/dist/{verify-Bkycc-Tf.mjs → verify-CiwNWM9N.mjs} +3 -4
- package/dist/verify-CiwNWM9N.mjs.map +1 -0
- package/package.json +19 -17
- package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
- package/dist/cli-errors-Cd79vmTH.mjs +0 -5
- package/dist/client-CrsnY58k.mjs +0 -997
- package/dist/client-CrsnY58k.mjs.map +0 -1
- package/dist/commands/db-verify.mjs.map +0 -1
- package/dist/commands/migration-plan.mjs.map +0 -1
- package/dist/config-loader-C25b63rJ.mjs.map +0 -1
- package/dist/contract-emit--feXyNd7.mjs +0 -4
- package/dist/contract-emit-NJ01hiiv.mjs +0 -195
- package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
- package/dist/contract-emit-V5SSitUT.mjs +0 -122
- package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
- package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
- package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
- package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
- package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
- package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
- package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
- package/dist/init-C5220SY9.mjs.map +0 -1
- package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
- package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
- package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
- package/dist/migrations-Bo5WtTla.mjs +0 -153
- package/dist/migrations-Bo5WtTla.mjs.map +0 -1
- package/dist/output-BpcQrnnq.mjs.map +0 -1
- package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
- package/dist/terminal-ui-C3ZLwQxK.mjs.map +0 -1
- package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
- package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
- package/dist/verify-Bkycc-Tf.mjs.map +0 -1
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { t as loadConfig } from "./config-loader-
|
|
2
|
-
import { _ as errorUnexpected, m as errorRuntime } from "./cli-errors-
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as TerminalUI } from "./terminal-ui-
|
|
5
|
-
import {
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
import { _ as errorUnexpected, m as errorRuntime, v as mapMigrationToolsError } from "./cli-errors-D3_sMh2K.mjs";
|
|
3
|
+
import { a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, h as toStructuralEdge, l as resolveMigrationPaths, m as toPathDecisionResult, n as collectDeclaredInvariants, o as maskConnectionUrl, s as readContractEnvelope, t as addGlobalOptions, y as formatStyledHeader } from "./command-helpers-BeZHkxV8.mjs";
|
|
4
|
+
import { t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
|
|
5
|
+
import { t as handleResult } from "./result-handler-rmPVKIP2.mjs";
|
|
6
|
+
import { t as createControlClient } from "./client-BCnP7cHo.mjs";
|
|
7
|
+
import { t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-BrwKK6Q6.mjs";
|
|
6
8
|
import { Command } from "commander";
|
|
7
|
-
import { notOk, ok } from "@prisma-next/utils/result";
|
|
8
9
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
11
|
+
import { createControlStack } from "@prisma-next/framework-components/control";
|
|
12
|
+
import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/migration-graph";
|
|
11
13
|
import { bold, cyan, dim, magenta, yellow } from "colorette";
|
|
14
|
+
import { graphWalkStrategy } from "@prisma-next/migration-tools/aggregate";
|
|
15
|
+
import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
|
|
16
|
+
import { MigrationToolsError, errorNoInvariantPath, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
|
|
12
17
|
import { readRefs, resolveRef } from "@prisma-next/migration-tools/refs";
|
|
13
|
-
import { MigrationToolsError } from "@prisma-next/migration-tools/types";
|
|
14
18
|
import dagre from "@dagrejs/dagre";
|
|
15
|
-
|
|
16
19
|
//#region src/utils/formatters/graph-types.ts
|
|
17
20
|
/**
|
|
18
21
|
* Immutable directed graph with adjacency-list indexing.
|
|
@@ -52,7 +55,6 @@ var RenderGraph = class {
|
|
|
52
55
|
return this.forward.get(nodeId) ?? [];
|
|
53
56
|
}
|
|
54
57
|
};
|
|
55
|
-
|
|
56
58
|
//#endregion
|
|
57
59
|
//#region src/utils/formatters/graph-migration-mapper.ts
|
|
58
60
|
/**
|
|
@@ -100,7 +102,8 @@ function migrationGraphToRenderInput(input) {
|
|
|
100
102
|
for (const [, entries] of graph.forwardChain) for (const entry of entries) {
|
|
101
103
|
const status = statusByDirName.get(entry.dirName);
|
|
102
104
|
const icon = status ? STATUS_ICON[status] : "";
|
|
103
|
-
const
|
|
105
|
+
const invariantsSuffix = entry.invariants.length > 0 ? ` provides [${entry.invariants.map((id) => JSON.stringify(id)).join(", ")}]` : "";
|
|
106
|
+
const label = `${entry.dirName}${icon}${invariantsSuffix}`;
|
|
104
107
|
edgeList.push({
|
|
105
108
|
from: toShortId(entry.from),
|
|
106
109
|
to: toShortId(entry.to),
|
|
@@ -171,7 +174,6 @@ function migrationGraphToRenderInput(input) {
|
|
|
171
174
|
relevantPaths
|
|
172
175
|
};
|
|
173
176
|
}
|
|
174
|
-
|
|
175
177
|
//#endregion
|
|
176
178
|
//#region src/utils/formatters/graph-render.ts
|
|
177
179
|
/**
|
|
@@ -1086,9 +1088,24 @@ function isLinearGraph(graph) {
|
|
|
1086
1088
|
for (const node of graph.nodes) if (graph.outgoing(node.id).filter((e) => e.style !== "dashed").length > 1) return false;
|
|
1087
1089
|
return true;
|
|
1088
1090
|
}
|
|
1089
|
-
|
|
1090
1091
|
//#endregion
|
|
1091
1092
|
//#region src/commands/migration-status.ts
|
|
1093
|
+
/**
|
|
1094
|
+
* Sum per-space `pendingCount` into a cross-space total, but only when
|
|
1095
|
+
* every loaded space reports a defined `pendingCount`. Returns
|
|
1096
|
+
* `undefined` if any space is on the marker-unknown / offline path
|
|
1097
|
+
* (where `pendingCount` is intentionally absent), so JSON consumers can
|
|
1098
|
+
* distinguish "no pending" from "unknown".
|
|
1099
|
+
*/
|
|
1100
|
+
function computeTotalPendingAcrossSpaces(spaces) {
|
|
1101
|
+
if (spaces.length === 0) return void 0;
|
|
1102
|
+
let total = 0;
|
|
1103
|
+
for (const s of spaces) {
|
|
1104
|
+
if (s.pendingCount === void 0) return void 0;
|
|
1105
|
+
total += s.pendingCount;
|
|
1106
|
+
}
|
|
1107
|
+
return total;
|
|
1108
|
+
}
|
|
1092
1109
|
function summarizeOps(ops) {
|
|
1093
1110
|
if (ops.length === 0) return {
|
|
1094
1111
|
summary: "0 ops",
|
|
@@ -1194,7 +1211,7 @@ function buildMigrationEntries(chain, packages, mode, markerHash, edgeStatuses)
|
|
|
1194
1211
|
dirName: migration.dirName,
|
|
1195
1212
|
from: migration.from,
|
|
1196
1213
|
to: migration.to,
|
|
1197
|
-
|
|
1214
|
+
migrationHash: migration.migrationHash,
|
|
1198
1215
|
operationCount: ops.length,
|
|
1199
1216
|
operationSummary: summary,
|
|
1200
1217
|
hasDestructive,
|
|
@@ -1239,37 +1256,117 @@ function determineLimit(opts) {
|
|
|
1239
1256
|
if (Number.isNaN(parsed)) return DEFAULT_LIMIT;
|
|
1240
1257
|
return parsed;
|
|
1241
1258
|
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Build the aggregate enumeration of contract spaces for the status
|
|
1261
|
+
* output. Loads the aggregate from disk (lossy on failure — extension
|
|
1262
|
+
* spaces are simply omitted, the existing single-space app behaviour
|
|
1263
|
+
* keeps working), reads per-space marker rows when online, and uses
|
|
1264
|
+
* {@link graphWalkStrategy} to compute each space's pending count.
|
|
1265
|
+
*
|
|
1266
|
+
* Sub-spec § `migration status` semantics — the aggregate-walking
|
|
1267
|
+
* version reports per-space marker + pending state alongside the
|
|
1268
|
+
* cross-space totals.
|
|
1269
|
+
*/
|
|
1270
|
+
async function loadAggregateStatusSpaces(args) {
|
|
1271
|
+
const loaded = await buildContractSpaceAggregate({
|
|
1272
|
+
targetId: args.targetId,
|
|
1273
|
+
migrationsDir: args.migrationsDir,
|
|
1274
|
+
appContract: args.validateContract(args.appContractRaw),
|
|
1275
|
+
extensionPacks: args.extensionPacks,
|
|
1276
|
+
validateContract: args.validateContract
|
|
1277
|
+
});
|
|
1278
|
+
if (!loaded.ok) return [];
|
|
1279
|
+
const aggregate = loaded.value;
|
|
1280
|
+
const orderedMembers = [...aggregate.extensions, aggregate.app];
|
|
1281
|
+
const rows = [];
|
|
1282
|
+
for (const member of orderedMembers) {
|
|
1283
|
+
const liveMarker = args.markersBySpace?.get(member.spaceId) ?? null;
|
|
1284
|
+
const isApp = member.spaceId === aggregate.app.spaceId;
|
|
1285
|
+
if (member.migrations.graph.nodes.size === 0) {
|
|
1286
|
+
rows.push({
|
|
1287
|
+
spaceId: member.spaceId,
|
|
1288
|
+
kind: isApp ? "app" : "extension",
|
|
1289
|
+
headHash: member.headRef.hash,
|
|
1290
|
+
...args.markersBySpace !== null ? {
|
|
1291
|
+
markerHash: liveMarker?.storageHash ?? null,
|
|
1292
|
+
status: member.headRef.hash === EMPTY_CONTRACT_HASH ? "up-to-date" : "never-planned",
|
|
1293
|
+
pendingCount: 0
|
|
1294
|
+
} : {}
|
|
1295
|
+
});
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1298
|
+
if (args.markersBySpace === null) {
|
|
1299
|
+
rows.push({
|
|
1300
|
+
spaceId: member.spaceId,
|
|
1301
|
+
kind: isApp ? "app" : "extension",
|
|
1302
|
+
headHash: member.headRef.hash
|
|
1303
|
+
});
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1306
|
+
const walked = graphWalkStrategy({
|
|
1307
|
+
aggregateTargetId: aggregate.targetId,
|
|
1308
|
+
member,
|
|
1309
|
+
currentMarker: liveMarker
|
|
1310
|
+
});
|
|
1311
|
+
let pendingCount = 0;
|
|
1312
|
+
let status;
|
|
1313
|
+
if (walked.kind === "ok") {
|
|
1314
|
+
pendingCount = walked.result.migrationEdges?.length ?? 0;
|
|
1315
|
+
if (liveMarker === null) status = pendingCount === 0 ? "no-marker" : "pending";
|
|
1316
|
+
else status = pendingCount === 0 ? "up-to-date" : "pending";
|
|
1317
|
+
} else status = "unreachable";
|
|
1318
|
+
rows.push({
|
|
1319
|
+
spaceId: member.spaceId,
|
|
1320
|
+
kind: isApp ? "app" : "extension",
|
|
1321
|
+
headHash: member.headRef.hash,
|
|
1322
|
+
markerHash: liveMarker?.storageHash ?? null,
|
|
1323
|
+
pendingCount,
|
|
1324
|
+
...status ? { status } : {}
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
return rows;
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Read the raw contract.json bytes from disk for the aggregate
|
|
1331
|
+
* loader. Returns `null` if the file is missing or unparseable —
|
|
1332
|
+
* the existing `readContractEnvelope` path will report the same
|
|
1333
|
+
* problem via a status diagnostic, no need to double-surface.
|
|
1334
|
+
*/
|
|
1335
|
+
async function loadContractRawSafely(config) {
|
|
1336
|
+
try {
|
|
1337
|
+
const path = (await import("./command-helpers-BeZHkxV8.mjs").then((n) => n.r)).resolveContractPath(config);
|
|
1338
|
+
const raw = await (await import("node:fs/promises")).readFile(path, "utf-8");
|
|
1339
|
+
return JSON.parse(raw);
|
|
1340
|
+
} catch {
|
|
1341
|
+
return null;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1242
1344
|
async function executeMigrationStatusCommand(options, flags, ui) {
|
|
1243
1345
|
const config = await loadConfig(options.config);
|
|
1244
|
-
const { configPath,
|
|
1346
|
+
const { configPath, appMigrationsDir, appMigrationsRelative, migrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
|
|
1245
1347
|
const dbConnection = options.db ?? config.db?.connection;
|
|
1246
1348
|
const hasDriver = !!config.driver;
|
|
1247
1349
|
let activeRefName;
|
|
1248
1350
|
let activeRefHash;
|
|
1351
|
+
let activeRefEntry;
|
|
1249
1352
|
let allRefs = {};
|
|
1250
1353
|
try {
|
|
1251
1354
|
allRefs = await readRefs(refsDir);
|
|
1252
1355
|
} catch (error) {
|
|
1253
|
-
if (MigrationToolsError.is(error)) return notOk(
|
|
1254
|
-
why: error.why,
|
|
1255
|
-
fix: error.fix,
|
|
1256
|
-
meta: { code: error.code }
|
|
1257
|
-
}));
|
|
1356
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
1258
1357
|
throw error;
|
|
1259
1358
|
}
|
|
1260
1359
|
if (options.ref) {
|
|
1261
1360
|
activeRefName = options.ref;
|
|
1262
1361
|
try {
|
|
1263
|
-
|
|
1362
|
+
activeRefEntry = resolveRef(allRefs, activeRefName);
|
|
1363
|
+
activeRefHash = activeRefEntry.hash;
|
|
1264
1364
|
} catch (error) {
|
|
1265
|
-
if (MigrationToolsError.is(error)) return notOk(
|
|
1266
|
-
why: error.why,
|
|
1267
|
-
fix: error.fix,
|
|
1268
|
-
meta: { code: error.code }
|
|
1269
|
-
}));
|
|
1365
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
1270
1366
|
throw error;
|
|
1271
1367
|
}
|
|
1272
1368
|
}
|
|
1369
|
+
const requiredInvariants = [...activeRefEntry?.invariants ?? []].sort();
|
|
1273
1370
|
const statusRefs = Object.entries(allRefs).map(([name, entry]) => ({
|
|
1274
1371
|
name,
|
|
1275
1372
|
hash: entry.hash,
|
|
@@ -1281,7 +1378,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1281
1378
|
value: configPath
|
|
1282
1379
|
}, {
|
|
1283
1380
|
label: "migrations",
|
|
1284
|
-
value:
|
|
1381
|
+
value: appMigrationsRelative
|
|
1285
1382
|
}];
|
|
1286
1383
|
if (dbConnection && hasDriver) details.push({
|
|
1287
1384
|
label: "database",
|
|
@@ -1291,6 +1388,10 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1291
1388
|
label: "ref",
|
|
1292
1389
|
value: activeRefName
|
|
1293
1390
|
});
|
|
1391
|
+
if (activeRefEntry && activeRefEntry.invariants.length > 0) details.push({
|
|
1392
|
+
label: "required",
|
|
1393
|
+
value: formatInvariantList(activeRefEntry.invariants)
|
|
1394
|
+
});
|
|
1294
1395
|
const header = formatStyledHeader({
|
|
1295
1396
|
command: "migration status",
|
|
1296
1397
|
description: "Show migration history and applied status",
|
|
@@ -1314,13 +1415,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1314
1415
|
let bundles;
|
|
1315
1416
|
let graph;
|
|
1316
1417
|
try {
|
|
1317
|
-
({bundles, graph} = await
|
|
1418
|
+
({bundles, graph} = await loadMigrationPackages(appMigrationsDir));
|
|
1318
1419
|
} catch (error) {
|
|
1319
|
-
if (MigrationToolsError.is(error)) return notOk(
|
|
1320
|
-
why: error.why,
|
|
1321
|
-
fix: error.fix,
|
|
1322
|
-
meta: { code: error.code }
|
|
1323
|
-
}));
|
|
1420
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
1324
1421
|
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}` }));
|
|
1325
1422
|
}
|
|
1326
1423
|
if (bundles.length === 0) {
|
|
@@ -1337,7 +1434,8 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1337
1434
|
targetHash: EMPTY_CONTRACT_HASH,
|
|
1338
1435
|
contractHash,
|
|
1339
1436
|
summary: "No migrations found",
|
|
1340
|
-
diagnostics
|
|
1437
|
+
diagnostics,
|
|
1438
|
+
requiredInvariants
|
|
1341
1439
|
});
|
|
1342
1440
|
}
|
|
1343
1441
|
let targetHash;
|
|
@@ -1354,7 +1452,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1354
1452
|
});
|
|
1355
1453
|
}
|
|
1356
1454
|
let markerHash;
|
|
1455
|
+
let markerInvariants = [];
|
|
1357
1456
|
let mode = "offline";
|
|
1457
|
+
let allMarkers = null;
|
|
1358
1458
|
if (dbConnection && hasDriver) {
|
|
1359
1459
|
const client = createControlClient({
|
|
1360
1460
|
family: config.family,
|
|
@@ -1365,14 +1465,48 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1365
1465
|
});
|
|
1366
1466
|
try {
|
|
1367
1467
|
await client.connect(dbConnection);
|
|
1368
|
-
|
|
1468
|
+
const marker = await client.readMarker();
|
|
1469
|
+
markerHash = marker?.storageHash;
|
|
1470
|
+
markerInvariants = marker?.invariants ?? [];
|
|
1369
1471
|
mode = "online";
|
|
1472
|
+
if (typeof client.readAllMarkers === "function") allMarkers = await client.readAllMarkers();
|
|
1473
|
+
else allMarkers = null;
|
|
1370
1474
|
} catch {
|
|
1371
1475
|
if (!flags.json && !flags.quiet) ui.warn("Could not connect to database — showing offline status");
|
|
1372
1476
|
} finally {
|
|
1373
1477
|
await client.close();
|
|
1374
1478
|
}
|
|
1375
1479
|
}
|
|
1480
|
+
const contractRawForAggregate = await loadContractRawSafely(config);
|
|
1481
|
+
let aggregateSpaces = [];
|
|
1482
|
+
if (contractRawForAggregate !== null) {
|
|
1483
|
+
const stack = createControlStack(config);
|
|
1484
|
+
const familyInstance = config.family.create(stack);
|
|
1485
|
+
try {
|
|
1486
|
+
aggregateSpaces = await loadAggregateStatusSpaces({
|
|
1487
|
+
targetId: config.target.targetId,
|
|
1488
|
+
migrationsDir,
|
|
1489
|
+
appContractRaw: contractRawForAggregate,
|
|
1490
|
+
extensionPacks: config.extensionPacks ?? [],
|
|
1491
|
+
validateContract: (json) => familyInstance.validateContract(json),
|
|
1492
|
+
markersBySpace: allMarkers
|
|
1493
|
+
});
|
|
1494
|
+
} catch {
|
|
1495
|
+
aggregateSpaces = [];
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
const totalPendingAcrossSpaces = computeTotalPendingAcrossSpaces(aggregateSpaces);
|
|
1499
|
+
if (activeRefEntry && activeRefEntry.invariants.length > 0) {
|
|
1500
|
+
const declared = collectDeclaredInvariants(graph);
|
|
1501
|
+
const known = new Set(declared);
|
|
1502
|
+
if (mode === "online") for (const id of markerInvariants) known.add(id);
|
|
1503
|
+
const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));
|
|
1504
|
+
if (unknown.length > 0) return notOk(mapMigrationToolsError(errorUnknownInvariant({
|
|
1505
|
+
...ifDefined("refName", activeRefName),
|
|
1506
|
+
unknown,
|
|
1507
|
+
declared: [...declared].sort()
|
|
1508
|
+
})));
|
|
1509
|
+
}
|
|
1376
1510
|
if (mode === "online" && markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash !== contractHash) {
|
|
1377
1511
|
const hints = [];
|
|
1378
1512
|
if (graph.nodes.has(contractHash)) hints.push("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", "Run 'prisma-next contract infer' to make your contract match the database", "Run 'prisma-next db verify' to inspect the database state");
|
|
@@ -1392,6 +1526,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1392
1526
|
summary: `${bundles.length} migration(s) on disk`,
|
|
1393
1527
|
diagnostics,
|
|
1394
1528
|
markerHash,
|
|
1529
|
+
requiredInvariants,
|
|
1395
1530
|
...statusRefs.length > 0 ? { refs: statusRefs } : {}
|
|
1396
1531
|
});
|
|
1397
1532
|
}
|
|
@@ -1416,6 +1551,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1416
1551
|
summary: `${bundles.length} migration(s) on disk`,
|
|
1417
1552
|
diagnostics,
|
|
1418
1553
|
...ifDefined("markerHash", markerHash),
|
|
1554
|
+
requiredInvariants,
|
|
1419
1555
|
...statusRefs.length > 0 ? { refs: statusRefs } : {},
|
|
1420
1556
|
graph,
|
|
1421
1557
|
bundles,
|
|
@@ -1430,35 +1566,68 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1430
1566
|
const entries = buildMigrationEntries(chain, bundles, mode, markerHash, edgeStatuses);
|
|
1431
1567
|
const pendingCount = edgeStatuses.filter((e) => e.status === "pending").length;
|
|
1432
1568
|
const appliedCount = edgeStatuses.filter((e) => e.status === "applied").length;
|
|
1569
|
+
let appliedInvariants;
|
|
1570
|
+
let missingInvariants;
|
|
1571
|
+
let effectiveRequired = /* @__PURE__ */ new Set();
|
|
1572
|
+
if (mode === "online") {
|
|
1573
|
+
const markerSet = new Set(markerInvariants);
|
|
1574
|
+
effectiveRequired = new Set(requiredInvariants.filter((id) => !markerSet.has(id)));
|
|
1575
|
+
appliedInvariants = requiredInvariants.filter((id) => markerSet.has(id));
|
|
1576
|
+
missingInvariants = [...effectiveRequired].sort();
|
|
1577
|
+
}
|
|
1578
|
+
const hasInvariantWork = effectiveRequired.size > 0;
|
|
1579
|
+
const missingList = [...effectiveRequired].sort().join(", ");
|
|
1433
1580
|
let summary;
|
|
1434
1581
|
if (mode === "online") if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) summary = `${bundles.length} migration(s) on disk`;
|
|
1435
|
-
else if (activeRefHash && markerHash !== void 0)
|
|
1436
|
-
|
|
1582
|
+
else if (activeRefHash && markerHash !== void 0) {
|
|
1583
|
+
const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);
|
|
1584
|
+
summary = hasInvariantWork ? `${distance} — missing invariant(s): ${missingList}` : distance;
|
|
1585
|
+
} else if (pendingCount === 0 && !hasInvariantWork) summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? "s" : ""} applied)`;
|
|
1586
|
+
else if (pendingCount === 0 && hasInvariantWork) summary = `Missing invariant(s): ${missingList} — run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply`;
|
|
1437
1587
|
else if (markerHash === void 0) summary = `${pendingCount} pending migration(s) — database has no marker`;
|
|
1438
1588
|
else summary = `${pendingCount} pending migration(s) — run 'prisma-next migration apply' to apply`;
|
|
1439
1589
|
else summary = `${entries.length} migration(s) on disk`;
|
|
1440
|
-
if (mode === "online") if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) diagnostics.push({
|
|
1441
|
-
code: "MIGRATION.MARKER_NOT_IN_HISTORY",
|
|
1442
|
-
severity: "warn",
|
|
1443
|
-
message: "Database matches the current contract but was updated directly (not via migration apply)",
|
|
1444
|
-
hints: ["Run 'prisma-next migration plan' to plan a migration to your current contract"]
|
|
1445
|
-
});
|
|
1446
|
-
else if (pendingCount > 0) diagnostics.push({
|
|
1447
|
-
code: "MIGRATION.DATABASE_BEHIND",
|
|
1448
|
-
severity: "info",
|
|
1449
|
-
message: `${pendingCount} migration(s) pending`,
|
|
1450
|
-
hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
|
|
1451
|
-
});
|
|
1452
|
-
else diagnostics.push({
|
|
1453
|
-
code: "MIGRATION.UP_TO_DATE",
|
|
1454
|
-
severity: "info",
|
|
1455
|
-
message: "Database is up to date",
|
|
1456
|
-
hints: []
|
|
1457
|
-
});
|
|
1458
1590
|
let pathDecision;
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1591
|
+
let routingUnreachable = false;
|
|
1592
|
+
if (mode === "online") {
|
|
1593
|
+
const outcome = findPathWithDecision(graph, markerHash ?? EMPTY_CONTRACT_HASH, targetHash, {
|
|
1594
|
+
...ifDefined("refName", activeRefName),
|
|
1595
|
+
required: effectiveRequired
|
|
1596
|
+
});
|
|
1597
|
+
if (outcome.kind === "ok") pathDecision = toPathDecisionResult(outcome.decision);
|
|
1598
|
+
else if (outcome.kind === "unsatisfiable") return notOk(mapMigrationToolsError(errorNoInvariantPath({
|
|
1599
|
+
...ifDefined("refName", activeRefName),
|
|
1600
|
+
required: [...effectiveRequired].sort(),
|
|
1601
|
+
missing: outcome.missing,
|
|
1602
|
+
structuralPath: outcome.structuralPath.map(toStructuralEdge)
|
|
1603
|
+
})));
|
|
1604
|
+
else routingUnreachable = true;
|
|
1605
|
+
}
|
|
1606
|
+
if (mode === "online") {
|
|
1607
|
+
if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) diagnostics.push({
|
|
1608
|
+
code: "MIGRATION.MARKER_NOT_IN_HISTORY",
|
|
1609
|
+
severity: "warn",
|
|
1610
|
+
message: "Database matches the current contract but was updated directly (not via migration apply)",
|
|
1611
|
+
hints: ["Run 'prisma-next migration plan' to plan a migration to your current contract"]
|
|
1612
|
+
});
|
|
1613
|
+
else if (pendingCount > 0) diagnostics.push({
|
|
1614
|
+
code: "MIGRATION.DATABASE_BEHIND",
|
|
1615
|
+
severity: "info",
|
|
1616
|
+
message: `${pendingCount} migration(s) pending`,
|
|
1617
|
+
hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
|
|
1618
|
+
});
|
|
1619
|
+
else if (hasInvariantWork) diagnostics.push({
|
|
1620
|
+
code: "MIGRATION.INVARIANTS_PENDING",
|
|
1621
|
+
severity: "info",
|
|
1622
|
+
message: `Missing required invariant(s): ${missingList}`,
|
|
1623
|
+
hints: [`Run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply a path that covers the required invariants`]
|
|
1624
|
+
});
|
|
1625
|
+
else if (!routingUnreachable) diagnostics.push({
|
|
1626
|
+
code: "MIGRATION.UP_TO_DATE",
|
|
1627
|
+
severity: "info",
|
|
1628
|
+
message: "Database is up to date",
|
|
1629
|
+
hints: []
|
|
1630
|
+
});
|
|
1462
1631
|
}
|
|
1463
1632
|
return ok({
|
|
1464
1633
|
ok: true,
|
|
@@ -1469,13 +1638,18 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1469
1638
|
summary,
|
|
1470
1639
|
diagnostics,
|
|
1471
1640
|
...ifDefined("markerHash", markerHash),
|
|
1641
|
+
requiredInvariants,
|
|
1642
|
+
...ifDefined("appliedInvariants", appliedInvariants),
|
|
1643
|
+
...ifDefined("missingInvariants", missingInvariants),
|
|
1472
1644
|
...statusRefs.length > 0 ? { refs: statusRefs } : {},
|
|
1473
1645
|
...ifDefined("pathDecision", pathDecision),
|
|
1474
1646
|
graph,
|
|
1475
1647
|
bundles,
|
|
1476
1648
|
edgeStatuses,
|
|
1477
1649
|
...ifDefined("activeRefHash", activeRefHash),
|
|
1478
|
-
...ifDefined("activeRefName", activeRefName)
|
|
1650
|
+
...ifDefined("activeRefName", activeRefName),
|
|
1651
|
+
spaces: aggregateSpaces,
|
|
1652
|
+
...ifDefined("totalPendingAcrossSpaces", totalPendingAcrossSpaces)
|
|
1479
1653
|
});
|
|
1480
1654
|
}
|
|
1481
1655
|
function createMigrationStatusCommand() {
|
|
@@ -1490,7 +1664,7 @@ function createMigrationStatusCommand() {
|
|
|
1490
1664
|
});
|
|
1491
1665
|
const exitCode = handleResult(await executeMigrationStatusCommand(options, flags, ui), flags, ui, (statusResult) => {
|
|
1492
1666
|
if (flags.json) {
|
|
1493
|
-
const { graph:
|
|
1667
|
+
const { graph: _graph, bundles: _bundles, edgeStatuses: _edgeStatuses, activeRefHash: _activeRefHash, activeRefName: _activeRefName, diverged: _diverged, ...jsonResult } = statusResult;
|
|
1494
1668
|
ui.output(JSON.stringify(jsonResult, null, 2));
|
|
1495
1669
|
} else if (!flags.quiet) {
|
|
1496
1670
|
const colorize = flags.color !== false;
|
|
@@ -1540,17 +1714,48 @@ function formatStatusSummary(result, colorize) {
|
|
|
1540
1714
|
const hasUnknown = result.migrations.some((e) => e.status === "unknown");
|
|
1541
1715
|
const pendingCount = result.migrations.filter((e) => e.status === "pending").length;
|
|
1542
1716
|
const hasWarnings = result.diagnostics?.some((d) => d.severity === "warn") ?? false;
|
|
1717
|
+
const hasInvariantPending = result.diagnostics?.some((d) => d.code === "MIGRATION.INVARIANTS_PENDING") ?? false;
|
|
1543
1718
|
if (result.mode === "online") if (hasUnknown || hasWarnings) lines.push(`${c(yellow, "⚠")} ${result.summary}`);
|
|
1544
|
-
else if (pendingCount === 0) lines.push(`${c(cyan, "✔")} ${result.summary}`);
|
|
1719
|
+
else if (pendingCount === 0 && !hasInvariantPending) lines.push(`${c(cyan, "✔")} ${result.summary}`);
|
|
1545
1720
|
else lines.push(`${c(yellow, "⧗")} ${result.summary}`);
|
|
1546
1721
|
else lines.push(result.summary);
|
|
1722
|
+
if (result.requiredInvariants.length > 0) if (result.appliedInvariants !== void 0 && result.missingInvariants !== void 0) {
|
|
1723
|
+
lines.push(`${c(dim, "applied ")}${formatInvariantList(result.appliedInvariants)}`);
|
|
1724
|
+
lines.push(`${c(dim, "missing ")}${formatInvariantList(result.missingInvariants)}`);
|
|
1725
|
+
} else lines.push(`${c(dim, "applied ")}(unknown — connect a database to evaluate)`);
|
|
1547
1726
|
const warnings = result.diagnostics?.filter((d) => d.severity === "warn") ?? [];
|
|
1548
1727
|
for (const diag of warnings) {
|
|
1549
1728
|
lines.push(`${c(yellow, "⚠")} ${diag.message}`);
|
|
1550
1729
|
for (const hint of diag.hints) lines.push(` ${c(dim, hint)}`);
|
|
1551
1730
|
}
|
|
1731
|
+
if (result.spaces?.some((s) => s.kind === "extension")) {
|
|
1732
|
+
const total = result.totalPendingAcrossSpaces ?? 0;
|
|
1733
|
+
lines.push("");
|
|
1734
|
+
lines.push(c(dim, "spaces"));
|
|
1735
|
+
for (const space of result.spaces) lines.push(formatSpaceLine(space, c));
|
|
1736
|
+
if (total > 0) {
|
|
1737
|
+
lines.push("");
|
|
1738
|
+
lines.push(`${c(yellow, "⧗")} ${total} pending migration(s) across ${result.spaces.length} space(s) — run 'prisma-next migration apply' to apply`);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1552
1741
|
return lines.join("\n");
|
|
1553
1742
|
}
|
|
1743
|
+
function formatSpaceLine(space, c) {
|
|
1744
|
+
const glyph = (() => {
|
|
1745
|
+
if (space.status === "up-to-date" || space.status === "no-marker") return c(cyan, "✓");
|
|
1746
|
+
if (space.status === "pending") return c(yellow, "⧗");
|
|
1747
|
+
if (space.status === "unreachable" || space.status === "never-planned") return c(magenta, "✗");
|
|
1748
|
+
return " ";
|
|
1749
|
+
})();
|
|
1750
|
+
const tag = space.kind === "app" ? "[app]" : "[ext]";
|
|
1751
|
+
const head = space.headHash.slice(0, 8);
|
|
1752
|
+
const marker = space.markerHash === void 0 ? "(unknown)" : space.markerHash === null ? "(no marker)" : space.markerHash.slice(0, 8);
|
|
1753
|
+
const pending = space.pendingCount === void 0 ? "" : space.pendingCount === 0 ? c(dim, " (up to date)") : c(yellow, ` (${space.pendingCount} pending)`);
|
|
1754
|
+
return ` ${glyph} ${c(dim, tag)} ${space.spaceId} → head ${c(dim, head)}, marker ${c(dim, marker)}${pending}`;
|
|
1755
|
+
}
|
|
1756
|
+
function formatInvariantList(ids) {
|
|
1757
|
+
return ids.length === 0 ? "(none)" : ids.join(", ");
|
|
1758
|
+
}
|
|
1554
1759
|
function summarizeRefDistance(graph, markerHash, refHash, refName) {
|
|
1555
1760
|
if (markerHash === refHash) return `At ref "${refName}" target`;
|
|
1556
1761
|
const pathToRef = findPath(graph, markerHash, refHash);
|
|
@@ -1559,7 +1764,7 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
|
|
|
1559
1764
|
if (pathFromRef) return `${pathFromRef.length} migration(s) ahead of ref "${refName}"`;
|
|
1560
1765
|
return `No path between database marker and ref "${refName}" target`;
|
|
1561
1766
|
}
|
|
1562
|
-
|
|
1563
1767
|
//#endregion
|
|
1564
|
-
export {
|
|
1565
|
-
|
|
1768
|
+
export { loadAggregateStatusSpaces as a, formatStatusSummary as i, createMigrationStatusCommand as n, deriveEdgeStatuses as r, computeTotalPendingAcrossSpaces as t };
|
|
1769
|
+
|
|
1770
|
+
//# sourceMappingURL=migration-status-By9G5p2H.mjs.map
|