prisma-next 0.5.0-dev.7 → 0.5.0-dev.70

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.
Files changed (129) hide show
  1. package/dist/cli-errors-D3_sMh2K.mjs +33 -0
  2. package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
  3. package/dist/cli-errors-QH8kf-C2.d.mts +3 -0
  4. package/dist/cli.mjs +16 -78
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/client-0ZX24FXF.mjs +1398 -0
  7. package/dist/client-0ZX24FXF.mjs.map +1 -0
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +2 -4
  10. package/dist/commands/contract-infer.d.mts.map +1 -1
  11. package/dist/commands/contract-infer.mjs +2 -4
  12. package/dist/commands/db-init.d.mts.map +1 -1
  13. package/dist/commands/db-init.mjs +14 -13
  14. package/dist/commands/db-init.mjs.map +1 -1
  15. package/dist/commands/db-schema.d.mts.map +1 -1
  16. package/dist/commands/db-schema.mjs +5 -7
  17. package/dist/commands/db-schema.mjs.map +1 -1
  18. package/dist/commands/db-sign.d.mts.map +1 -1
  19. package/dist/commands/db-sign.mjs +8 -9
  20. package/dist/commands/db-sign.mjs.map +1 -1
  21. package/dist/commands/db-update.d.mts.map +1 -1
  22. package/dist/commands/db-update.mjs +13 -13
  23. package/dist/commands/db-update.mjs.map +1 -1
  24. package/dist/commands/db-verify.d.mts.map +1 -1
  25. package/dist/commands/db-verify.mjs +1 -321
  26. package/dist/commands/migration-apply.d.mts +5 -2
  27. package/dist/commands/migration-apply.d.mts.map +1 -1
  28. package/dist/commands/migration-apply.mjs +64 -66
  29. package/dist/commands/migration-apply.mjs.map +1 -1
  30. package/dist/commands/migration-new.d.mts +0 -1
  31. package/dist/commands/migration-new.d.mts.map +1 -1
  32. package/dist/commands/migration-new.mjs +33 -40
  33. package/dist/commands/migration-new.mjs.map +1 -1
  34. package/dist/commands/migration-plan.d.mts +14 -5
  35. package/dist/commands/migration-plan.d.mts.map +1 -1
  36. package/dist/commands/migration-plan.mjs +1 -347
  37. package/dist/commands/migration-ref.d.mts +1 -1
  38. package/dist/commands/migration-ref.d.mts.map +1 -1
  39. package/dist/commands/migration-ref.mjs +7 -12
  40. package/dist/commands/migration-ref.mjs.map +1 -1
  41. package/dist/commands/migration-show.d.mts +13 -7
  42. package/dist/commands/migration-show.d.mts.map +1 -1
  43. package/dist/commands/migration-show.mjs +34 -36
  44. package/dist/commands/migration-show.mjs.map +1 -1
  45. package/dist/commands/migration-status.d.mts +23 -5
  46. package/dist/commands/migration-status.d.mts.map +1 -1
  47. package/dist/commands/migration-status.mjs +2 -4
  48. package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
  49. package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
  50. package/dist/config-loader.d.mts +0 -1
  51. package/dist/config-loader.d.mts.map +1 -1
  52. package/dist/config-loader.mjs +2 -3
  53. package/dist/contract-emit-B3ChISB_.mjs +338 -0
  54. package/dist/contract-emit-B3ChISB_.mjs.map +1 -0
  55. package/dist/contract-emit-DkMqO7f2.mjs +148 -0
  56. package/dist/contract-emit-DkMqO7f2.mjs.map +1 -0
  57. package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-CF6ogEJ_.mjs} +4 -6
  58. package/dist/contract-enrichment-CF6ogEJ_.mjs.map +1 -0
  59. package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-BDKAE0B0.mjs} +12 -22
  60. package/dist/contract-infer-BDKAE0B0.mjs.map +1 -0
  61. package/dist/db-verify-B4TdDKOI.mjs +403 -0
  62. package/dist/db-verify-B4TdDKOI.mjs.map +1 -0
  63. package/dist/exports/config-types.mjs +1 -2
  64. package/dist/exports/control-api.d.mts +287 -29
  65. package/dist/exports/control-api.d.mts.map +1 -1
  66. package/dist/exports/control-api.mjs +4 -6
  67. package/dist/exports/index.d.mts.map +1 -1
  68. package/dist/exports/index.mjs +28 -30
  69. package/dist/exports/index.mjs.map +1 -1
  70. package/dist/exports/init-output.d.mts +2 -4
  71. package/dist/exports/init-output.d.mts.map +1 -1
  72. package/dist/exports/init-output.mjs +2 -3
  73. package/dist/{framework-components-Cr--XBKy.mjs → framework-components-gwAHl7ml.mjs} +3 -4
  74. package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-gwAHl7ml.mjs.map} +1 -1
  75. package/dist/{init-C5220SY9.mjs → init-Deo7U8_U.mjs} +26 -35
  76. package/dist/init-Deo7U8_U.mjs.map +1 -0
  77. package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-BAgQMYpD.mjs} +10 -11
  78. package/dist/inspect-live-schema-BAgQMYpD.mjs.map +1 -0
  79. package/dist/migration-cli.d.mts +41 -12
  80. package/dist/migration-cli.d.mts.map +1 -1
  81. package/dist/migration-cli.mjs +309 -86
  82. package/dist/migration-cli.mjs.map +1 -1
  83. package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-B8J702Uh.mjs} +8 -9
  84. package/dist/migration-command-scaffold-B8J702Uh.mjs.map +1 -0
  85. package/dist/migration-plan-BcKNnTM7.mjs +530 -0
  86. package/dist/migration-plan-BcKNnTM7.mjs.map +1 -0
  87. package/dist/{migration-status-DUMiH8_G.mjs → migration-status-CjwB2of-.mjs} +117 -64
  88. package/dist/migration-status-CjwB2of-.mjs.map +1 -0
  89. package/dist/{migrations-Bo5WtTla.mjs → migrations-CIK94AJf.mjs} +43 -23
  90. package/dist/migrations-CIK94AJf.mjs.map +1 -0
  91. package/dist/{output-BpcQrnnq.mjs → output-DnjfCC_u.mjs} +9 -3
  92. package/dist/output-DnjfCC_u.mjs.map +1 -0
  93. package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-xASh41wr.mjs} +2 -2
  94. package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-xASh41wr.mjs.map} +1 -1
  95. package/dist/{result-handler-Ba3zWQsI.mjs → result-handler-DWb1rFS-.mjs} +52 -27
  96. package/dist/result-handler-DWb1rFS-.mjs.map +1 -0
  97. package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-zaRDhJnP.mjs} +2 -6
  98. package/dist/{terminal-ui-C3ZLwQxK.mjs.map → terminal-ui-zaRDhJnP.mjs.map} +1 -1
  99. package/dist/{verify-Bkycc-Tf.mjs → verify-BEIa9638.mjs} +3 -4
  100. package/dist/verify-BEIa9638.mjs.map +1 -0
  101. package/package.json +19 -17
  102. package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
  103. package/dist/cli-errors-Cd79vmTH.mjs +0 -5
  104. package/dist/client-CrsnY58k.mjs +0 -997
  105. package/dist/client-CrsnY58k.mjs.map +0 -1
  106. package/dist/commands/db-verify.mjs.map +0 -1
  107. package/dist/commands/migration-plan.mjs.map +0 -1
  108. package/dist/config-loader-C25b63rJ.mjs.map +0 -1
  109. package/dist/contract-emit--feXyNd7.mjs +0 -4
  110. package/dist/contract-emit-NJ01hiiv.mjs +0 -195
  111. package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
  112. package/dist/contract-emit-V5SSitUT.mjs +0 -122
  113. package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
  114. package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
  115. package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
  116. package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
  117. package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
  118. package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
  119. package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
  120. package/dist/init-C5220SY9.mjs.map +0 -1
  121. package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
  122. package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
  123. package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
  124. package/dist/migrations-Bo5WtTla.mjs.map +0 -1
  125. package/dist/output-BpcQrnnq.mjs.map +0 -1
  126. package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
  127. package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
  128. package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
  129. package/dist/verify-Bkycc-Tf.mjs.map +0 -1
@@ -1,18 +1,17 @@
1
- import { t as loadConfig } from "./config-loader-C25b63rJ.mjs";
2
- import { _ as errorUnexpected, m as errorRuntime } from "./cli-errors-Cd79vmTH.mjs";
3
- import { t as createControlClient } from "./client-CrsnY58k.mjs";
4
- import { t as TerminalUI } from "./terminal-ui-C3ZLwQxK.mjs";
5
- import { _ as formatStyledHeader, a as maskConnectionUrl, c as resolveMigrationPaths, d as setCommandExamples, i as loadAllBundles, m as parseGlobalFlags, n as addGlobalOptions, o as readContractEnvelope, p as toPathDecisionResult, t as handleResult, u as setCommandDescriptions } from "./result-handler-Ba3zWQsI.mjs";
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 { t as TerminalUI } from "./terminal-ui-zaRDhJnP.mjs";
4
+ import { a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, h as toStructuralEdge, l as resolveMigrationPaths, m as toPathDecisionResult, n as addGlobalOptions, o as maskConnectionUrl, r as collectDeclaredInvariants, s as readContractEnvelope, t as handleResult, y as formatStyledHeader } from "./result-handler-DWb1rFS-.mjs";
5
+ import { t as createControlClient } from "./client-0ZX24FXF.mjs";
6
6
  import { Command } from "commander";
7
- import { notOk, ok } from "@prisma-next/utils/result";
8
7
  import { ifDefined } from "@prisma-next/utils/defined";
9
- import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
10
- import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/dag";
8
+ import { notOk, ok } from "@prisma-next/utils/result";
9
+ import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/migration-graph";
11
10
  import { bold, cyan, dim, magenta, yellow } from "colorette";
11
+ import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
12
+ import { MigrationToolsError, errorNoInvariantPath, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
12
13
  import { readRefs, resolveRef } from "@prisma-next/migration-tools/refs";
13
- import { MigrationToolsError } from "@prisma-next/migration-tools/types";
14
14
  import dagre from "@dagrejs/dagre";
15
-
16
15
  //#region src/utils/formatters/graph-types.ts
17
16
  /**
18
17
  * Immutable directed graph with adjacency-list indexing.
@@ -52,7 +51,6 @@ var RenderGraph = class {
52
51
  return this.forward.get(nodeId) ?? [];
53
52
  }
54
53
  };
55
-
56
54
  //#endregion
57
55
  //#region src/utils/formatters/graph-migration-mapper.ts
58
56
  /**
@@ -100,7 +98,8 @@ function migrationGraphToRenderInput(input) {
100
98
  for (const [, entries] of graph.forwardChain) for (const entry of entries) {
101
99
  const status = statusByDirName.get(entry.dirName);
102
100
  const icon = status ? STATUS_ICON[status] : "";
103
- const label = `${entry.dirName}${icon}`;
101
+ const invariantsSuffix = entry.invariants.length > 0 ? ` provides [${entry.invariants.map((id) => JSON.stringify(id)).join(", ")}]` : "";
102
+ const label = `${entry.dirName}${icon}${invariantsSuffix}`;
104
103
  edgeList.push({
105
104
  from: toShortId(entry.from),
106
105
  to: toShortId(entry.to),
@@ -171,7 +170,6 @@ function migrationGraphToRenderInput(input) {
171
170
  relevantPaths
172
171
  };
173
172
  }
174
-
175
173
  //#endregion
176
174
  //#region src/utils/formatters/graph-render.ts
177
175
  /**
@@ -1086,7 +1084,6 @@ function isLinearGraph(graph) {
1086
1084
  for (const node of graph.nodes) if (graph.outgoing(node.id).filter((e) => e.style !== "dashed").length > 1) return false;
1087
1085
  return true;
1088
1086
  }
1089
-
1090
1087
  //#endregion
1091
1088
  //#region src/commands/migration-status.ts
1092
1089
  function summarizeOps(ops) {
@@ -1194,7 +1191,7 @@ function buildMigrationEntries(chain, packages, mode, markerHash, edgeStatuses)
1194
1191
  dirName: migration.dirName,
1195
1192
  from: migration.from,
1196
1193
  to: migration.to,
1197
- migrationId: migration.migrationId,
1194
+ migrationHash: migration.migrationHash,
1198
1195
  operationCount: ops.length,
1199
1196
  operationSummary: summary,
1200
1197
  hasDestructive,
@@ -1241,35 +1238,30 @@ function determineLimit(opts) {
1241
1238
  }
1242
1239
  async function executeMigrationStatusCommand(options, flags, ui) {
1243
1240
  const config = await loadConfig(options.config);
1244
- const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
1241
+ const { configPath, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
1245
1242
  const dbConnection = options.db ?? config.db?.connection;
1246
1243
  const hasDriver = !!config.driver;
1247
1244
  let activeRefName;
1248
1245
  let activeRefHash;
1246
+ let activeRefEntry;
1249
1247
  let allRefs = {};
1250
1248
  try {
1251
1249
  allRefs = await readRefs(refsDir);
1252
1250
  } catch (error) {
1253
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1254
- why: error.why,
1255
- fix: error.fix,
1256
- meta: { code: error.code }
1257
- }));
1251
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1258
1252
  throw error;
1259
1253
  }
1260
1254
  if (options.ref) {
1261
1255
  activeRefName = options.ref;
1262
1256
  try {
1263
- activeRefHash = resolveRef(allRefs, activeRefName).hash;
1257
+ activeRefEntry = resolveRef(allRefs, activeRefName);
1258
+ activeRefHash = activeRefEntry.hash;
1264
1259
  } catch (error) {
1265
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1266
- why: error.why,
1267
- fix: error.fix,
1268
- meta: { code: error.code }
1269
- }));
1260
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1270
1261
  throw error;
1271
1262
  }
1272
1263
  }
1264
+ const requiredInvariants = [...activeRefEntry?.invariants ?? []].sort();
1273
1265
  const statusRefs = Object.entries(allRefs).map(([name, entry]) => ({
1274
1266
  name,
1275
1267
  hash: entry.hash,
@@ -1281,7 +1273,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1281
1273
  value: configPath
1282
1274
  }, {
1283
1275
  label: "migrations",
1284
- value: migrationsRelative
1276
+ value: appMigrationsRelative
1285
1277
  }];
1286
1278
  if (dbConnection && hasDriver) details.push({
1287
1279
  label: "database",
@@ -1291,6 +1283,10 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1291
1283
  label: "ref",
1292
1284
  value: activeRefName
1293
1285
  });
1286
+ if (activeRefEntry && activeRefEntry.invariants.length > 0) details.push({
1287
+ label: "required",
1288
+ value: formatInvariantList(activeRefEntry.invariants)
1289
+ });
1294
1290
  const header = formatStyledHeader({
1295
1291
  command: "migration status",
1296
1292
  description: "Show migration history and applied status",
@@ -1314,13 +1310,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1314
1310
  let bundles;
1315
1311
  let graph;
1316
1312
  try {
1317
- ({bundles, graph} = await loadAllBundles(migrationsDir));
1313
+ ({bundles, graph} = await loadMigrationPackages(appMigrationsDir));
1318
1314
  } catch (error) {
1319
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1320
- why: error.why,
1321
- fix: error.fix,
1322
- meta: { code: error.code }
1323
- }));
1315
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1324
1316
  return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}` }));
1325
1317
  }
1326
1318
  if (bundles.length === 0) {
@@ -1337,7 +1329,8 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1337
1329
  targetHash: EMPTY_CONTRACT_HASH,
1338
1330
  contractHash,
1339
1331
  summary: "No migrations found",
1340
- diagnostics
1332
+ diagnostics,
1333
+ requiredInvariants
1341
1334
  });
1342
1335
  }
1343
1336
  let targetHash;
@@ -1354,6 +1347,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1354
1347
  });
1355
1348
  }
1356
1349
  let markerHash;
1350
+ let markerInvariants = [];
1357
1351
  let mode = "offline";
1358
1352
  if (dbConnection && hasDriver) {
1359
1353
  const client = createControlClient({
@@ -1365,7 +1359,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1365
1359
  });
1366
1360
  try {
1367
1361
  await client.connect(dbConnection);
1368
- markerHash = (await client.readMarker())?.storageHash;
1362
+ const marker = await client.readMarker();
1363
+ markerHash = marker?.storageHash;
1364
+ markerInvariants = marker?.invariants ?? [];
1369
1365
  mode = "online";
1370
1366
  } catch {
1371
1367
  if (!flags.json && !flags.quiet) ui.warn("Could not connect to database — showing offline status");
@@ -1373,6 +1369,17 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1373
1369
  await client.close();
1374
1370
  }
1375
1371
  }
1372
+ if (activeRefEntry && activeRefEntry.invariants.length > 0) {
1373
+ const declared = collectDeclaredInvariants(graph);
1374
+ const known = new Set(declared);
1375
+ if (mode === "online") for (const id of markerInvariants) known.add(id);
1376
+ const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));
1377
+ if (unknown.length > 0) return notOk(mapMigrationToolsError(errorUnknownInvariant({
1378
+ ...ifDefined("refName", activeRefName),
1379
+ unknown,
1380
+ declared: [...declared].sort()
1381
+ })));
1382
+ }
1376
1383
  if (mode === "online" && markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash !== contractHash) {
1377
1384
  const hints = [];
1378
1385
  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 +1399,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1392
1399
  summary: `${bundles.length} migration(s) on disk`,
1393
1400
  diagnostics,
1394
1401
  markerHash,
1402
+ requiredInvariants,
1395
1403
  ...statusRefs.length > 0 ? { refs: statusRefs } : {}
1396
1404
  });
1397
1405
  }
@@ -1416,6 +1424,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1416
1424
  summary: `${bundles.length} migration(s) on disk`,
1417
1425
  diagnostics,
1418
1426
  ...ifDefined("markerHash", markerHash),
1427
+ requiredInvariants,
1419
1428
  ...statusRefs.length > 0 ? { refs: statusRefs } : {},
1420
1429
  graph,
1421
1430
  bundles,
@@ -1430,35 +1439,68 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1430
1439
  const entries = buildMigrationEntries(chain, bundles, mode, markerHash, edgeStatuses);
1431
1440
  const pendingCount = edgeStatuses.filter((e) => e.status === "pending").length;
1432
1441
  const appliedCount = edgeStatuses.filter((e) => e.status === "applied").length;
1442
+ let appliedInvariants;
1443
+ let missingInvariants;
1444
+ let effectiveRequired = /* @__PURE__ */ new Set();
1445
+ if (mode === "online") {
1446
+ const markerSet = new Set(markerInvariants);
1447
+ effectiveRequired = new Set(requiredInvariants.filter((id) => !markerSet.has(id)));
1448
+ appliedInvariants = requiredInvariants.filter((id) => markerSet.has(id));
1449
+ missingInvariants = [...effectiveRequired].sort();
1450
+ }
1451
+ const hasInvariantWork = effectiveRequired.size > 0;
1452
+ const missingList = [...effectiveRequired].sort().join(", ");
1433
1453
  let summary;
1434
1454
  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) summary = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);
1436
- else if (pendingCount === 0) summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? "s" : ""} applied)`;
1455
+ else if (activeRefHash && markerHash !== void 0) {
1456
+ const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);
1457
+ summary = hasInvariantWork ? `${distance} — missing invariant(s): ${missingList}` : distance;
1458
+ } else if (pendingCount === 0 && !hasInvariantWork) summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? "s" : ""} applied)`;
1459
+ else if (pendingCount === 0 && hasInvariantWork) summary = `Missing invariant(s): ${missingList} — run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply`;
1437
1460
  else if (markerHash === void 0) summary = `${pendingCount} pending migration(s) — database has no marker`;
1438
1461
  else summary = `${pendingCount} pending migration(s) — run 'prisma-next migration apply' to apply`;
1439
1462
  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
1463
  let pathDecision;
1459
- if (mode === "online" && markerHash !== void 0) {
1460
- const decision = findPathWithDecision(graph, markerHash, targetHash, activeRefName);
1461
- if (decision) pathDecision = toPathDecisionResult(decision);
1464
+ let routingUnreachable = false;
1465
+ if (mode === "online") {
1466
+ const outcome = findPathWithDecision(graph, markerHash ?? EMPTY_CONTRACT_HASH, targetHash, {
1467
+ ...ifDefined("refName", activeRefName),
1468
+ required: effectiveRequired
1469
+ });
1470
+ if (outcome.kind === "ok") pathDecision = toPathDecisionResult(outcome.decision);
1471
+ else if (outcome.kind === "unsatisfiable") return notOk(mapMigrationToolsError(errorNoInvariantPath({
1472
+ ...ifDefined("refName", activeRefName),
1473
+ required: [...effectiveRequired].sort(),
1474
+ missing: outcome.missing,
1475
+ structuralPath: outcome.structuralPath.map(toStructuralEdge)
1476
+ })));
1477
+ else routingUnreachable = true;
1478
+ }
1479
+ if (mode === "online") {
1480
+ if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) diagnostics.push({
1481
+ code: "MIGRATION.MARKER_NOT_IN_HISTORY",
1482
+ severity: "warn",
1483
+ message: "Database matches the current contract but was updated directly (not via migration apply)",
1484
+ hints: ["Run 'prisma-next migration plan' to plan a migration to your current contract"]
1485
+ });
1486
+ else if (pendingCount > 0) diagnostics.push({
1487
+ code: "MIGRATION.DATABASE_BEHIND",
1488
+ severity: "info",
1489
+ message: `${pendingCount} migration(s) pending`,
1490
+ hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
1491
+ });
1492
+ else if (hasInvariantWork) diagnostics.push({
1493
+ code: "MIGRATION.INVARIANTS_PENDING",
1494
+ severity: "info",
1495
+ message: `Missing required invariant(s): ${missingList}`,
1496
+ hints: [`Run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply a path that covers the required invariants`]
1497
+ });
1498
+ else if (!routingUnreachable) diagnostics.push({
1499
+ code: "MIGRATION.UP_TO_DATE",
1500
+ severity: "info",
1501
+ message: "Database is up to date",
1502
+ hints: []
1503
+ });
1462
1504
  }
1463
1505
  return ok({
1464
1506
  ok: true,
@@ -1469,6 +1511,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1469
1511
  summary,
1470
1512
  diagnostics,
1471
1513
  ...ifDefined("markerHash", markerHash),
1514
+ requiredInvariants,
1515
+ ...ifDefined("appliedInvariants", appliedInvariants),
1516
+ ...ifDefined("missingInvariants", missingInvariants),
1472
1517
  ...statusRefs.length > 0 ? { refs: statusRefs } : {},
1473
1518
  ...ifDefined("pathDecision", pathDecision),
1474
1519
  graph,
@@ -1490,7 +1535,7 @@ function createMigrationStatusCommand() {
1490
1535
  });
1491
1536
  const exitCode = handleResult(await executeMigrationStatusCommand(options, flags, ui), flags, ui, (statusResult) => {
1492
1537
  if (flags.json) {
1493
- const { graph: _g, bundles: _b, edgeStatuses: _es, activeRefHash: _arh, activeRefName: _arn, diverged: _d, ...jsonResult } = statusResult;
1538
+ const { graph: _graph, bundles: _bundles, edgeStatuses: _edgeStatuses, activeRefHash: _activeRefHash, activeRefName: _activeRefName, diverged: _diverged, ...jsonResult } = statusResult;
1494
1539
  ui.output(JSON.stringify(jsonResult, null, 2));
1495
1540
  } else if (!flags.quiet) {
1496
1541
  const colorize = flags.color !== false;
@@ -1540,10 +1585,15 @@ function formatStatusSummary(result, colorize) {
1540
1585
  const hasUnknown = result.migrations.some((e) => e.status === "unknown");
1541
1586
  const pendingCount = result.migrations.filter((e) => e.status === "pending").length;
1542
1587
  const hasWarnings = result.diagnostics?.some((d) => d.severity === "warn") ?? false;
1588
+ const hasInvariantPending = result.diagnostics?.some((d) => d.code === "MIGRATION.INVARIANTS_PENDING") ?? false;
1543
1589
  if (result.mode === "online") if (hasUnknown || hasWarnings) lines.push(`${c(yellow, "⚠")} ${result.summary}`);
1544
- else if (pendingCount === 0) lines.push(`${c(cyan, "✔")} ${result.summary}`);
1590
+ else if (pendingCount === 0 && !hasInvariantPending) lines.push(`${c(cyan, "✔")} ${result.summary}`);
1545
1591
  else lines.push(`${c(yellow, "⧗")} ${result.summary}`);
1546
1592
  else lines.push(result.summary);
1593
+ if (result.requiredInvariants.length > 0) if (result.appliedInvariants !== void 0 && result.missingInvariants !== void 0) {
1594
+ lines.push(`${c(dim, "applied ")}${formatInvariantList(result.appliedInvariants)}`);
1595
+ lines.push(`${c(dim, "missing ")}${formatInvariantList(result.missingInvariants)}`);
1596
+ } else lines.push(`${c(dim, "applied ")}(unknown — connect a database to evaluate)`);
1547
1597
  const warnings = result.diagnostics?.filter((d) => d.severity === "warn") ?? [];
1548
1598
  for (const diag of warnings) {
1549
1599
  lines.push(`${c(yellow, "⚠")} ${diag.message}`);
@@ -1551,6 +1601,9 @@ function formatStatusSummary(result, colorize) {
1551
1601
  }
1552
1602
  return lines.join("\n");
1553
1603
  }
1604
+ function formatInvariantList(ids) {
1605
+ return ids.length === 0 ? "(none)" : ids.join(", ");
1606
+ }
1554
1607
  function summarizeRefDistance(graph, markerHash, refHash, refName) {
1555
1608
  if (markerHash === refHash) return `At ref "${refName}" target`;
1556
1609
  const pathToRef = findPath(graph, markerHash, refHash);
@@ -1559,7 +1612,7 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
1559
1612
  if (pathFromRef) return `${pathFromRef.length} migration(s) ahead of ref "${refName}"`;
1560
1613
  return `No path between database marker and ref "${refName}" target`;
1561
1614
  }
1562
-
1563
1615
  //#endregion
1564
- export { deriveEdgeStatuses as n, createMigrationStatusCommand as t };
1565
- //# sourceMappingURL=migration-status-DUMiH8_G.mjs.map
1616
+ export { deriveEdgeStatuses as n, formatStatusSummary as r, createMigrationStatusCommand as t };
1617
+
1618
+ //# sourceMappingURL=migration-status-CjwB2of-.mjs.map