prisma-next 0.11.0-dev.9 → 0.12.0-dev.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.
Files changed (144) hide show
  1. package/dist/cli.mjs +9 -10
  2. package/dist/cli.mjs.map +1 -1
  3. package/dist/{client-UnIveZxZ.mjs → client-KgJorIvG.mjs} +72 -60
  4. package/dist/client-KgJorIvG.mjs.map +1 -0
  5. package/dist/{command-helpers-CRfjbZRz.mjs → command-helpers-Bbw1GbwL.mjs} +642 -45
  6. package/dist/command-helpers-Bbw1GbwL.mjs.map +1 -0
  7. package/dist/commands/contract-emit.d.mts.map +1 -1
  8. package/dist/commands/contract-emit.mjs +1 -1
  9. package/dist/commands/contract-infer.d.mts.map +1 -1
  10. package/dist/commands/contract-infer.mjs +1 -1
  11. package/dist/commands/db-init.d.mts.map +1 -1
  12. package/dist/commands/db-init.mjs +5 -7
  13. package/dist/commands/db-init.mjs.map +1 -1
  14. package/dist/commands/db-schema.d.mts.map +1 -1
  15. package/dist/commands/db-schema.mjs +3 -4
  16. package/dist/commands/db-schema.mjs.map +1 -1
  17. package/dist/commands/db-sign.d.mts.map +1 -1
  18. package/dist/commands/db-sign.mjs +12 -10
  19. package/dist/commands/db-sign.mjs.map +1 -1
  20. package/dist/commands/db-update.d.mts.map +1 -1
  21. package/dist/commands/db-update.mjs +12 -11
  22. package/dist/commands/db-update.mjs.map +1 -1
  23. package/dist/commands/db-verify.d.mts.map +1 -1
  24. package/dist/commands/db-verify.mjs +1 -1
  25. package/dist/commands/migrate.d.mts +2 -2
  26. package/dist/commands/migrate.d.mts.map +1 -1
  27. package/dist/commands/migrate.mjs +68 -69
  28. package/dist/commands/migrate.mjs.map +1 -1
  29. package/dist/commands/migration-check.d.mts +4 -3
  30. package/dist/commands/migration-check.d.mts.map +1 -1
  31. package/dist/commands/migration-check.mjs +1 -280
  32. package/dist/commands/migration-graph.d.mts +13 -2
  33. package/dist/commands/migration-graph.d.mts.map +1 -1
  34. package/dist/commands/migration-graph.mjs +2 -137
  35. package/dist/commands/migration-list.d.mts +64 -4
  36. package/dist/commands/migration-list.d.mts.map +1 -1
  37. package/dist/commands/migration-list.mjs +143 -56
  38. package/dist/commands/migration-list.mjs.map +1 -1
  39. package/dist/commands/migration-log.d.mts +10 -1
  40. package/dist/commands/migration-log.d.mts.map +1 -1
  41. package/dist/commands/migration-log.mjs +10 -15
  42. package/dist/commands/migration-log.mjs.map +1 -1
  43. package/dist/commands/migration-new.d.mts.map +1 -1
  44. package/dist/commands/migration-new.mjs +32 -38
  45. package/dist/commands/migration-new.mjs.map +1 -1
  46. package/dist/commands/migration-plan.d.mts +2 -2
  47. package/dist/commands/migration-plan.d.mts.map +1 -1
  48. package/dist/commands/migration-plan.mjs +1 -1
  49. package/dist/commands/migration-show.d.mts +4 -55
  50. package/dist/commands/migration-show.d.mts.map +1 -1
  51. package/dist/commands/migration-show.mjs +61 -153
  52. package/dist/commands/migration-show.mjs.map +1 -1
  53. package/dist/commands/migration-status.d.mts +12 -49
  54. package/dist/commands/migration-status.d.mts.map +1 -1
  55. package/dist/commands/migration-status.mjs +84 -80
  56. package/dist/commands/migration-status.mjs.map +1 -1
  57. package/dist/commands/ref.d.mts +1 -1
  58. package/dist/commands/ref.d.mts.map +1 -1
  59. package/dist/commands/ref.mjs +10 -8
  60. package/dist/commands/ref.mjs.map +1 -1
  61. package/dist/config-loader-B6sJjXTv.mjs.map +1 -1
  62. package/dist/config-loader.d.mts.map +1 -1
  63. package/dist/contract-at-errors-BxP-TOMl.mjs +42 -0
  64. package/dist/contract-at-errors-BxP-TOMl.mjs.map +1 -0
  65. package/dist/{contract-emit-C6rlsljO.mjs → contract-emit-D-4jrNve.mjs} +21 -7
  66. package/dist/{contract-emit-C6rlsljO.mjs.map → contract-emit-D-4jrNve.mjs.map} +1 -1
  67. package/dist/{contract-emit-mqXmapxB.mjs → contract-emit-DxcGl4Uq.mjs} +4 -6
  68. package/dist/{contract-emit-mqXmapxB.mjs.map → contract-emit-DxcGl4Uq.mjs.map} +1 -1
  69. package/dist/{contract-enrichment-Dani0mMW.mjs → contract-enrichment-a0V5Y_mL.mjs} +4 -25
  70. package/dist/contract-enrichment-a0V5Y_mL.mjs.map +1 -0
  71. package/dist/{contract-infer-C4jxc1aZ.mjs → contract-infer-D8uEbJuu.mjs} +3 -4
  72. package/dist/{contract-infer-C4jxc1aZ.mjs.map → contract-infer-D8uEbJuu.mjs.map} +1 -1
  73. package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs +247 -0
  74. package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs.map +1 -0
  75. package/dist/{db-verify-1d8tDoFN.mjs → db-verify-v_vUKXTU.mjs} +5 -7
  76. package/dist/{db-verify-1d8tDoFN.mjs.map → db-verify-v_vUKXTU.mjs.map} +1 -1
  77. package/dist/exports/control-api.d.mts +3 -3
  78. package/dist/exports/control-api.d.mts.map +1 -1
  79. package/dist/exports/control-api.mjs +3 -3
  80. package/dist/exports/index.d.mts.map +1 -1
  81. package/dist/exports/index.mjs +1 -1
  82. package/dist/exports/index.mjs.map +1 -1
  83. package/dist/exports/init-output.d.mts.map +1 -1
  84. package/dist/exports/init-output.mjs +1 -1
  85. package/dist/extension-pack-inputs-IDvjRCi3.mjs +62 -0
  86. package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +1 -0
  87. package/dist/{framework-components-Bexd0f4E.mjs → framework-components-fYXjz_in.mjs} +2 -2
  88. package/dist/{framework-components-Bexd0f4E.mjs.map → framework-components-fYXjz_in.mjs.map} +1 -1
  89. package/dist/global-flags-DEHjV8_s.d.mts +34 -0
  90. package/dist/global-flags-DEHjV8_s.d.mts.map +1 -0
  91. package/dist/{graph-render-BE8vmJ_7.mjs → graph-render-rFAqZujX.mjs} +2 -2
  92. package/dist/{graph-render-BE8vmJ_7.mjs.map → graph-render-rFAqZujX.mjs.map} +1 -1
  93. package/dist/{init-ByoeQphC.mjs → init-Cv9UzWL5.mjs} +17 -19
  94. package/dist/init-Cv9UzWL5.mjs.map +1 -0
  95. package/dist/{inspect-live-schema-B1Q49RF0.mjs → inspect-live-schema-C6ohV_oQ.mjs} +4 -5
  96. package/dist/{inspect-live-schema-B1Q49RF0.mjs.map → inspect-live-schema-C6ohV_oQ.mjs.map} +1 -1
  97. package/dist/migration-check-BiBJoYYW.mjs +341 -0
  98. package/dist/migration-check-BiBJoYYW.mjs.map +1 -0
  99. package/dist/migration-cli.d.mts.map +1 -1
  100. package/dist/migration-cli.mjs +4 -4
  101. package/dist/migration-cli.mjs.map +1 -1
  102. package/dist/{migration-command-scaffold-oY4P1Qto.mjs → migration-command-scaffold-CjvwO6at.mjs} +4 -5
  103. package/dist/{migration-command-scaffold-oY4P1Qto.mjs.map → migration-command-scaffold-CjvwO6at.mjs.map} +1 -1
  104. package/dist/migration-graph-D7DVUElV.mjs +1232 -0
  105. package/dist/migration-graph-D7DVUElV.mjs.map +1 -0
  106. package/dist/migration-list-styler-BRwF4-gy.mjs +399 -0
  107. package/dist/migration-list-styler-BRwF4-gy.mjs.map +1 -0
  108. package/dist/{migration-plan-jdAHg_gK.mjs → migration-plan-9DJ7q7_z.mjs} +169 -189
  109. package/dist/migration-plan-9DJ7q7_z.mjs.map +1 -0
  110. package/dist/{migration-types-BXWvz12q.d.mts → migration-types-D2FW63pr.d.mts} +1 -1
  111. package/dist/{migration-types-BXWvz12q.d.mts.map → migration-types-D2FW63pr.d.mts.map} +1 -1
  112. package/dist/{migrations-B7n518mT.mjs → migrations-Cv2jxNNK.mjs} +3 -13
  113. package/dist/migrations-Cv2jxNNK.mjs.map +1 -0
  114. package/dist/{output-CUIdfYo5.mjs → output-B60Gw5fu.mjs} +1 -1
  115. package/dist/{output-CUIdfYo5.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
  116. package/dist/{progress-adapter-DFfvZcYL.mjs → progress-adapter-C644QK8l.mjs} +1 -1
  117. package/dist/{progress-adapter-DFfvZcYL.mjs.map → progress-adapter-C644QK8l.mjs.map} +1 -1
  118. package/dist/{ref-advancement-DRh5Nquq.mjs → ref-advancement-DUZqsue6.mjs} +1 -1
  119. package/dist/{ref-advancement-DRh5Nquq.mjs.map → ref-advancement-DUZqsue6.mjs.map} +1 -1
  120. package/dist/terminal-ui-5Y6mrg93.d.mts +133 -0
  121. package/dist/terminal-ui-5Y6mrg93.d.mts.map +1 -0
  122. package/dist/{types-UWB2-rrw.d.mts → types-Dt_SfqFm.d.mts} +18 -26
  123. package/dist/types-Dt_SfqFm.d.mts.map +1 -0
  124. package/dist/{verify-C5UvbrF1.mjs → verify-DCA9Sldu.mjs} +2 -2
  125. package/dist/{verify-C5UvbrF1.mjs.map → verify-DCA9Sldu.mjs.map} +1 -1
  126. package/package.json +27 -16
  127. package/dist/cli-errors-Bw2GlweY.mjs +0 -175
  128. package/dist/cli-errors-Bw2GlweY.mjs.map +0 -1
  129. package/dist/client-UnIveZxZ.mjs.map +0 -1
  130. package/dist/command-helpers-CRfjbZRz.mjs.map +0 -1
  131. package/dist/commands/migration-check.mjs.map +0 -1
  132. package/dist/commands/migration-graph.mjs.map +0 -1
  133. package/dist/contract-enrichment-Dani0mMW.mjs.map +0 -1
  134. package/dist/contract-space-aggregate-loader-CGakRlKM.mjs +0 -160
  135. package/dist/contract-space-aggregate-loader-CGakRlKM.mjs.map +0 -1
  136. package/dist/global-flags-CdE7M0d9.d.mts +0 -15
  137. package/dist/global-flags-CdE7M0d9.d.mts.map +0 -1
  138. package/dist/init-ByoeQphC.mjs.map +0 -1
  139. package/dist/migration-plan-jdAHg_gK.mjs.map +0 -1
  140. package/dist/migrations-B7n518mT.mjs.map +0 -1
  141. package/dist/rolldown-runtime-twds-ZHy.mjs +0 -14
  142. package/dist/terminal-ui-BiB_8KNo.mjs +0 -379
  143. package/dist/terminal-ui-BiB_8KNo.mjs.map +0 -1
  144. package/dist/types-UWB2-rrw.d.mts.map +0 -1
@@ -1,22 +1,21 @@
1
1
  import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
2
- import { C as errorSnapshotMissing, D as mapMigrationToolsError, E as errorUnexpected, O as mapRefResolutionError, _ as errorPlanForgotTheFlag, a as errorContractValidationFailed, l as errorFileNotFound, m as errorMigrationPlanningFailed, t as CliStructuredError, w as errorTargetMigrationNotSupported } from "./cli-errors-Bw2GlweY.mjs";
3
- import { t as assertFrameworkComponentsCompatible } from "./framework-components-Bexd0f4E.mjs";
4
- import { t as createTerminalUI } from "./terminal-ui-BiB_8KNo.mjs";
5
- import { S as formatStyledHeader, a as loadMigrationPackages, c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, i as getTargetMigrations, l as resolveMigrationPaths, t as addGlobalOptions, v as parseGlobalFlagsOrExit, y as handleResult } from "./command-helpers-CRfjbZRz.mjs";
6
- import { n as toExtensionInputs, t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-CGakRlKM.mjs";
2
+ import { $ as errorTargetMigrationNotSupported, A as CliStructuredError, G as errorPlanForgotTheFlag, P as errorContractValidationFailed, R as errorFileNotFound, T as formatStyledHeader, U as errorMigrationPlanningFailed, Z as errorSnapshotMissing, _ as createTerminalUI, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, nt as mapMigrationToolsError, o as resolveContractPath, r as getTargetMigrations, rt as mapRefResolutionError, s as resolveMigrationPaths, t as addGlobalOptions, tt as errorUnexpected, u as setCommandExamples, y as handleResult } from "./command-helpers-Bbw1GbwL.mjs";
3
+ import { t as assertFrameworkComponentsCompatible } from "./framework-components-fYXjz_in.mjs";
4
+ import { n as toExtensionInputs } from "./extension-pack-inputs-IDvjRCi3.mjs";
5
+ import { a as loadContractSpaceAggregateForCli, n as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-DvZwdkrr.mjs";
6
+ import { t as mapContractAtError } from "./contract-at-errors-BxP-TOMl.mjs";
7
7
  import { Command } from "commander";
8
8
  import { getEmittedArtifactPaths } from "@prisma-next/emitter";
9
9
  import { notOk, ok } from "@prisma-next/utils/result";
10
10
  import { join, relative } from "pathe";
11
11
  import { mkdir, readFile, writeFile } from "node:fs/promises";
12
12
  import { createControlStack, hasOperationPreview } from "@prisma-next/framework-components/control";
13
- import { copyFilesWithRename, formatMigrationDirName, materialiseExtensionMigrationPackageIfMissing, writeMigrationPackage } from "@prisma-next/migration-tools/io";
14
- import { assertHashIsGraphNode, findLatestMigration, isGraphNode } from "@prisma-next/migration-tools/migration-graph";
15
13
  import { emitContractSpaceArtefacts, planAllSpaces, readContractSpaceHeadRef, spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
16
14
  import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
17
- import { readRefSnapshot, readRefs } from "@prisma-next/migration-tools/refs";
15
+ import { assertHashIsGraphNode, findLatestMigration, isGraphNode } from "@prisma-next/migration-tools/migration-graph";
18
16
  import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
19
17
  import { computeMigrationHash } from "@prisma-next/migration-tools/hash";
18
+ import { copyFilesWithRename, formatMigrationDirName, materialiseExtensionMigrationPackageIfMissing, writeMigrationPackage } from "@prisma-next/migration-tools/io";
20
19
  import { writeMigrationTs } from "@prisma-next/migration-tools/migration-ts";
21
20
  import { canonicalizeJson } from "@prisma-next/framework-components/utils";
22
21
  import { deriveProvidedInvariants } from "@prisma-next/migration-tools/invariants";
@@ -115,8 +114,8 @@ const FULL_HASH_PATTERN = /^sha256:([0-9a-f]{64}|empty)$/;
115
114
  function looksLikeFullHash(input) {
116
115
  return FULL_HASH_PATTERN.test(input);
117
116
  }
118
- function graphIsEmpty(bundles) {
119
- return bundles.length === 0;
117
+ function graphIsEmpty(member) {
118
+ return member.packages.length === 0;
120
119
  }
121
120
  function getReachableRefs(refs, graph) {
122
121
  return Object.entries(refs).flatMap(([name, entry]) => entry && isGraphNode(entry.hash, graph) ? [{
@@ -132,86 +131,70 @@ function assertFromIsGraphNode(fromHash, graph, refs, graphTipHash) {
132
131
  throw error;
133
132
  }
134
133
  }
135
- async function deserializeSnapshotContract(familyInstance, contract) {
136
- try {
137
- return ok(familyInstance.deserializeContract(contract));
138
- } catch (error) {
139
- if (CliStructuredError.is(error)) return notOk(error);
140
- return notOk(errorContractValidationFailed(`Ref snapshot contract failed to deserialize: ${error instanceof Error ? error.message : String(error)}`, { where: { path: "ref-snapshot" } }));
141
- }
142
- }
143
- async function resolveGraphNodeFromBundle(fromHash, bundles, readBundleEndContract, explicitFromLabel) {
144
- const matchingBundle = bundles.find((pkg) => pkg.metadata.to === fromHash);
145
- if (!matchingBundle) return notOk(errorUnexpected(explicitFromLabel ? `No migration bundle found for --from "${explicitFromLabel}" (resolved hash: ${fromHash})` : `No migration bundle found for graph node ${fromHash}`, {
146
- why: `The hash ${fromHash} is a graph node but no on-disk migration package has an end-contract hash matching it.`,
147
- fix: "Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations."
148
- }));
134
+ async function resolveContractRef(parsed, member, options) {
135
+ const { hash, provenance } = parsed;
136
+ const refName = provenance.kind === "ref" ? provenance.refName : void 0;
149
137
  try {
138
+ const at = await member.contractAt(hash, refName !== void 0 ? { refName } : void 0);
139
+ if (at.provenance === "snapshot") return ok({
140
+ kind: "snapshot",
141
+ hash: at.hash,
142
+ contract: at.contract,
143
+ contractJson: at.contractJson,
144
+ contractDts: at.contractDts
145
+ });
150
146
  return ok({
151
147
  kind: "graph-node",
152
- fromHash,
153
- fromContract: await readBundleEndContract(matchingBundle.dirPath),
154
- sourceDir: matchingBundle.dirPath
148
+ hash: at.hash,
149
+ contract: at.contract,
150
+ contractJson: at.contractJson,
151
+ contractDts: at.contractDts,
152
+ sourceDir: at.sourceDir
155
153
  });
156
154
  } catch (error) {
157
- if (CliStructuredError.is(error)) return notOk(error);
158
- throw error;
155
+ return mapContractAtError(error, options?.artifactRole !== void 0 ? { artifactRole: options.artifactRole } : void 0);
159
156
  }
160
157
  }
161
- async function resolveFromRefName(refName, fromHash, input, refs) {
162
- const { refsDir, bundles, graph, familyInstance, readBundleEndContract } = input;
163
- const empty = graphIsEmpty(bundles);
158
+ async function resolveFromPolicy(parsed, input, refs, explicitFromLabel) {
159
+ const resolution = await resolveContractRef(parsed, input.member, {
160
+ ...explicitFromLabel !== void 0 ? { explicitLabel: explicitFromLabel } : {},
161
+ artifactRole: "from"
162
+ });
163
+ if (!resolution.ok) return resolution;
164
+ if (resolution.value.kind === "graph-node") return ok({
165
+ kind: "graph-node",
166
+ fromHash: resolution.value.hash,
167
+ fromContract: resolution.value.contract,
168
+ sourceDir: resolution.value.sourceDir
169
+ });
170
+ const { hash, contract, contractJson, contractDts } = resolution.value;
171
+ if (graphIsEmpty(input.member)) return ok({
172
+ kind: "auto-baseline",
173
+ fromHash: hash,
174
+ fromContract: contract,
175
+ contractDts,
176
+ contractJson
177
+ });
178
+ const graph = input.member.graph();
164
179
  const graphTip = findLatestMigration(graph)?.to ?? null;
165
- let snapshot;
166
180
  try {
167
- snapshot = await readRefSnapshot(refsDir, refName);
181
+ assertFromIsGraphNode(hash, graph, refs, graphTip);
168
182
  } catch (error) {
169
- if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
183
+ if (CliStructuredError.is(error)) return notOk(error);
170
184
  throw error;
171
185
  }
172
- if (snapshot) {
173
- const contractResult = await deserializeSnapshotContract(familyInstance, snapshot.contract);
174
- if (!contractResult.ok) return contractResult;
175
- const fromContract = contractResult.value;
176
- const { contractDts, contract: contractJson } = snapshot;
177
- if (empty) return ok({
178
- kind: "auto-baseline",
179
- fromHash,
180
- fromContract,
181
- contractDts,
182
- contractJson
183
- });
184
- try {
185
- assertFromIsGraphNode(fromHash, graph, refs, graphTip);
186
- } catch (error) {
187
- if (CliStructuredError.is(error)) return notOk(error);
188
- throw error;
189
- }
190
- return ok({
191
- kind: "snapshot",
192
- fromHash,
193
- fromContract,
194
- contractDts,
195
- contractJson
196
- });
197
- }
198
- if (isGraphNode(fromHash, graph)) return resolveGraphNodeFromBundle(fromHash, bundles, readBundleEndContract);
199
- return notOk(errorSnapshotMissing(refName));
200
- }
201
- async function resolveFromHashProvenance(fromHash, input, _refs, explicitFromLabel) {
202
- const { bundles, graph } = input;
203
- if (isGraphNode(fromHash, graph)) return resolveGraphNodeFromBundle(fromHash, bundles, input.readBundleEndContract, explicitFromLabel);
204
- throw new Error(`resolveFromHashProvenance: non-graph-node hash ${fromHash} should be refused via looksLikeFullHash before this helper is called`);
186
+ return ok({
187
+ kind: "snapshot",
188
+ fromHash: hash,
189
+ fromContract: contract,
190
+ contractDts,
191
+ contractJson
192
+ });
205
193
  }
206
194
  async function resolveFromForPlan(input) {
207
- const { optionsFrom, refsDir, graph } = input;
208
- let refs;
209
- try {
210
- refs = await readRefs(refsDir);
211
- } catch (error) {
212
- if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
213
- throw error;
214
- }
195
+ const { optionsFrom, member } = input;
196
+ const graph = member.graph();
197
+ const refs = member.refs;
215
198
  if (optionsFrom === void 0) {
216
199
  const dbRef = refs["db"];
217
200
  if (!dbRef) return ok({
@@ -219,7 +202,13 @@ async function resolveFromForPlan(input) {
219
202
  fromHash: null,
220
203
  fromContract: null
221
204
  });
222
- return resolveFromRefName("db", dbRef.hash, input, refs);
205
+ return resolveFromPolicy({
206
+ hash: dbRef.hash,
207
+ provenance: {
208
+ kind: "ref",
209
+ refName: "db"
210
+ }
211
+ }, input, refs);
223
212
  }
224
213
  const refResult = parseContractRef(optionsFrom, {
225
214
  graph,
@@ -227,57 +216,39 @@ async function resolveFromForPlan(input) {
227
216
  });
228
217
  if (!refResult.ok) {
229
218
  if (looksLikeFullHash(optionsFrom)) {
230
- const empty = graphIsEmpty(input.bundles);
219
+ const empty = graphIsEmpty(member);
231
220
  const graphTip = findLatestMigration(graph)?.to ?? null;
232
221
  if (empty) return notOk(errorSnapshotMissing(optionsFrom, { viaRef: false }));
233
222
  return notOk(errorPlanForgotTheFlag(optionsFrom, getReachableRefs(refs, graph), graphTip));
234
223
  }
235
224
  return notOk(mapRefResolutionError(refResult.failure));
236
225
  }
237
- const { hash: fromHash, provenance } = refResult.value;
238
- if (provenance.kind === "ref") return resolveFromRefName(provenance.refName, fromHash, input, refs);
239
- return resolveFromHashProvenance(fromHash, input, refs, optionsFrom);
226
+ return resolveFromPolicy(refResult.value, input, refs, optionsFrom);
227
+ }
228
+ async function resolveToForPlan(optionsTo, input) {
229
+ const { member } = input;
230
+ const graph = member.graph();
231
+ const refs = member.refs;
232
+ const refResult = parseContractRef(optionsTo, {
233
+ graph,
234
+ refs
235
+ });
236
+ if (!refResult.ok) return notOk(mapRefResolutionError(refResult.failure));
237
+ const resolution = await resolveContractRef(refResult.value, member, {
238
+ explicitLabel: optionsTo,
239
+ artifactRole: "to"
240
+ });
241
+ if (!resolution.ok) return resolution;
242
+ const { hash, contract, contractJson, contractDts } = resolution.value;
243
+ return ok({
244
+ hash,
245
+ contract,
246
+ contractJson,
247
+ contractDts
248
+ });
240
249
  }
241
250
  //#endregion
242
251
  //#region src/commands/migration-plan.ts
243
- /**
244
- * Load a predecessor migration's destination contract from its sibling
245
- * `end-contract.json` on disk and route it through the family's
246
- * `ContractSerializer` (via `deserializeContract`) so the in-memory shape
247
- * is the hydrated `Contract` every other caller sees. Bypassing this
248
- * seam was the root cause of TML-2536: a raw `JSON.parse(...) as Contract`
249
- * here let polymorphic `storage.types` entries reach the planner without
250
- * the `kind` discriminator the planner dispatches on.
251
- *
252
- * Throws `CliStructuredError` with:
253
- * - `errorFileNotFound` when the sibling file is missing — the user
254
- * has likely deleted or never authored the snapshot, and the
255
- * message names the file and points them at re-emitting from the
256
- * source.
257
- * - `errorContractValidationFailed` when the JSON parses but the
258
- * family deserializer rejects it (legacy untagged shape, structural
259
- * mismatch, etc.) — the message names the predecessor's path so
260
- * the operator can locate the bad snapshot.
261
- */
262
- async function readPredecessorEndContract(migrationDir, familyInstance) {
263
- const path = join(migrationDir, "end-contract.json");
264
- let raw;
265
- try {
266
- raw = await readFile(path, "utf-8");
267
- } catch (error) {
268
- if (error instanceof Error && error.code === "ENOENT") throw errorFileNotFound(path, {
269
- why: `Predecessor migration is missing its destination contract snapshot at ${path}`,
270
- fix: "Re-emit the predecessor migration (`prisma-next migration plan` from its source) so its sibling `end-contract.json` is restored, then re-run this command."
271
- });
272
- throw error;
273
- }
274
- try {
275
- return familyInstance.deserializeContract(JSON.parse(raw));
276
- } catch (error) {
277
- if (CliStructuredError.is(error)) throw error;
278
- throw errorContractValidationFailed(`Predecessor contract at ${path} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`, { where: { path } });
279
- }
280
- }
281
252
  async function writeSnapshotContractArtifacts(packageDir, contractJson, contractDts, artifactBasename) {
282
253
  await mkdir(packageDir, { recursive: true });
283
254
  const jsonContent = `${canonicalizeJson(contractJson)}\n`;
@@ -327,12 +298,6 @@ async function writePlannedMigrationPackage(packageDir, fromHash, toHash, create
327
298
  const metadataWithInvariants = {
328
299
  from: fromHash,
329
300
  to: toHash,
330
- hints: {
331
- used: [],
332
- applied: [],
333
- plannerVersion: "2.0.0"
334
- },
335
- labels: [],
336
301
  providedInvariants: deriveProvidedInvariants(opsForWrite),
337
302
  createdAt: createdAt.toISOString()
338
303
  };
@@ -366,6 +331,10 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
366
331
  label: "from",
367
332
  value: options.from
368
333
  });
334
+ if (options.to) details.push({
335
+ label: "to",
336
+ value: options.to
337
+ });
369
338
  if (options.name) details.push({
370
339
  label: "name",
371
340
  value: options.name
@@ -399,54 +368,61 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
399
368
  }
400
369
  const rawStorageHash = toContract.storage?.storageHash;
401
370
  if (typeof rawStorageHash !== "string") return notOk(errorContractValidationFailed("Contract is missing storageHash", { where: { path: contractPathAbsolute } }));
402
- const toStorageHash = rawStorageHash;
403
- const { refsDir } = resolveMigrationPaths(options.config, config);
371
+ let toStorageHash = rawStorageHash;
372
+ let toArtifacts = null;
404
373
  let fromContract = null;
405
374
  let fromHash = null;
406
375
  let fromContractSourceDir = null;
407
376
  let snapshotStartContract = null;
408
377
  let isAutoBaseline = false;
409
- try {
410
- const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);
411
- const resolutionResult = await resolveFromForPlan({
412
- optionsFrom: options.from,
413
- refsDir,
414
- bundles,
415
- graph,
416
- familyInstance,
417
- readBundleEndContract: (migrationDir) => readPredecessorEndContract(migrationDir, familyInstance)
418
- });
419
- if (!resolutionResult.ok) return notOk(resolutionResult.failure);
420
- switch (resolutionResult.value.kind) {
421
- case "greenfield": break;
422
- case "graph-node":
423
- fromHash = resolutionResult.value.fromHash;
424
- fromContract = resolutionResult.value.fromContract;
425
- fromContractSourceDir = resolutionResult.value.sourceDir;
426
- break;
427
- case "snapshot":
428
- fromHash = resolutionResult.value.fromHash;
429
- fromContract = resolutionResult.value.fromContract;
430
- snapshotStartContract = {
431
- contractJson: resolutionResult.value.contractJson,
432
- contractDts: resolutionResult.value.contractDts
433
- };
434
- break;
435
- case "auto-baseline":
436
- fromHash = resolutionResult.value.fromHash;
437
- fromContract = resolutionResult.value.fromContract;
438
- snapshotStartContract = {
439
- contractJson: resolutionResult.value.contractJson,
440
- contractDts: resolutionResult.value.contractDts
441
- };
442
- isAutoBaseline = true;
443
- break;
444
- }
445
- } catch (error) {
446
- if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
447
- if (CliStructuredError.is(error)) return notOk(error);
448
- const message = error instanceof Error ? error.message : String(error);
449
- return notOk(errorUnexpected(message, { why: `Unexpected error while loading migrations: ${message}` }));
378
+ const tolerantAggregateResult = await loadContractSpaceAggregateForCli({
379
+ targetId: config.target.targetId,
380
+ migrationsDir,
381
+ appContract: toContract,
382
+ extensionPacks: config.extensionPacks ?? [],
383
+ deserializeContract: (json) => familyInstance.deserializeContract(json)
384
+ });
385
+ if (!tolerantAggregateResult.ok) return notOk(tolerantAggregateResult.failure);
386
+ const resolutionMember = tolerantAggregateResult.value.app;
387
+ const resolutionResult = await resolveFromForPlan({
388
+ optionsFrom: options.from,
389
+ member: resolutionMember
390
+ });
391
+ if (!resolutionResult.ok) return notOk(resolutionResult.failure);
392
+ switch (resolutionResult.value.kind) {
393
+ case "greenfield": break;
394
+ case "graph-node":
395
+ fromHash = resolutionResult.value.fromHash;
396
+ fromContract = resolutionResult.value.fromContract;
397
+ fromContractSourceDir = resolutionResult.value.sourceDir;
398
+ break;
399
+ case "snapshot":
400
+ fromHash = resolutionResult.value.fromHash;
401
+ fromContract = resolutionResult.value.fromContract;
402
+ snapshotStartContract = {
403
+ contractJson: resolutionResult.value.contractJson,
404
+ contractDts: resolutionResult.value.contractDts
405
+ };
406
+ break;
407
+ case "auto-baseline":
408
+ fromHash = resolutionResult.value.fromHash;
409
+ fromContract = resolutionResult.value.fromContract;
410
+ snapshotStartContract = {
411
+ contractJson: resolutionResult.value.contractJson,
412
+ contractDts: resolutionResult.value.contractDts
413
+ };
414
+ isAutoBaseline = true;
415
+ break;
416
+ }
417
+ if (options.to !== void 0) {
418
+ const toResolution = await resolveToForPlan(options.to, { member: resolutionMember });
419
+ if (!toResolution.ok) return notOk(toResolution.failure);
420
+ toContract = toResolution.value.contract;
421
+ toStorageHash = toResolution.value.hash;
422
+ toArtifacts = {
423
+ contractJson: toResolution.value.contractJson,
424
+ contractDts: toResolution.value.contractDts
425
+ };
450
426
  }
451
427
  const seedResult = await runContractSpaceSeedPhase({
452
428
  migrationsDir,
@@ -488,6 +464,20 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
488
464
  config.adapter,
489
465
  ...config.extensionPacks ?? []
490
466
  ]);
467
+ async function writeDestinationEndContract(packageDir) {
468
+ if (toArtifacts !== null) {
469
+ await writeSnapshotContractArtifacts(packageDir, toArtifacts.contractJson, toArtifacts.contractDts, "end-contract");
470
+ return;
471
+ }
472
+ const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
473
+ await copyFilesWithRename(packageDir, [{
474
+ sourcePath: destinationArtifacts.jsonPath,
475
+ destName: "end-contract.json"
476
+ }, {
477
+ sourcePath: destinationArtifacts.dtsPath,
478
+ destName: "end-contract.d.ts"
479
+ }]);
480
+ }
491
481
  try {
492
482
  const planner = migrations.createPlanner(familyInstance);
493
483
  if (isAutoBaseline && fromHash !== null && fromContract !== null && snapshotStartContract !== null) {
@@ -537,17 +527,10 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
537
527
  timings: { total: Date.now() - startTime }
538
528
  });
539
529
  }
540
- const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract, fromContract, aggregate.app.spaceId);
530
+ const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId);
541
531
  if (!deltaLeg.ok) return notOk(deltaLeg.failure);
542
532
  await writePlannedMigrationPackage(deltaPackageDir, fromHash, toStorageHash, deltaTimestamp, deltaLeg.value);
543
- const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
544
- await copyFilesWithRename(deltaPackageDir, [{
545
- sourcePath: destinationArtifacts.jsonPath,
546
- destName: "end-contract.json"
547
- }, {
548
- sourcePath: destinationArtifacts.dtsPath,
549
- destName: "end-contract.d.ts"
550
- }]);
533
+ await writeDestinationEndContract(deltaPackageDir);
551
534
  await writeSnapshotStartContract(deltaPackageDir, snapshotStartContract.contractJson, snapshotStartContract.contractDts);
552
535
  const deltaOps = deltaLeg.value.hasPlaceholders ? [] : deltaLeg.value.plannedOps;
553
536
  if (deltaLeg.value.hasPlaceholders) return ok({
@@ -584,17 +567,10 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
584
567
  }
585
568
  const timestamp = /* @__PURE__ */ new Date();
586
569
  const packageDir = join(appMigrationsDir, formatMigrationDirName(timestamp, options.name ?? "migration"));
587
- const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract, fromContract, aggregate.app.spaceId);
570
+ const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId);
588
571
  if (!deltaLeg.ok) return notOk(deltaLeg.failure);
589
572
  await writePlannedMigrationPackage(packageDir, fromHash, toStorageHash, timestamp, deltaLeg.value);
590
- const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
591
- await copyFilesWithRename(packageDir, [{
592
- sourcePath: destinationArtifacts.jsonPath,
593
- destName: "end-contract.json"
594
- }, {
595
- sourcePath: destinationArtifacts.dtsPath,
596
- destName: "end-contract.d.ts"
597
- }]);
573
+ await writeDestinationEndContract(packageDir);
598
574
  if (fromContractSourceDir !== null) {
599
575
  const sourceArtifacts = getEmittedArtifactPaths(join(fromContractSourceDir, "end-contract.json"));
600
576
  await copyFilesWithRename(packageDir, [{
@@ -645,8 +621,12 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
645
621
  function createMigrationPlanCommand() {
646
622
  const command = new Command("plan");
647
623
  setCommandDescriptions(command, "Plan a migration from contract changes", "Compares the emitted contract against the latest on-disk migration state and\nproduces a new migration package with the required operations. No database\nconnection is needed — this is a fully offline operation.");
648
- setCommandExamples(command, ["prisma-next migration plan", "prisma-next migration plan --name add-users-table"]);
649
- addGlobalOptions(command).option("--config <path>", "Path to prisma-next.config.ts").option("--name <slug>", "Name slug for the migration directory", "migration").option("--from <contract>", "Starting contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)").action(async (options) => {
624
+ setCommandExamples(command, [
625
+ "prisma-next migration plan",
626
+ "prisma-next migration plan --name add-users-table",
627
+ "prisma-next migration plan --to <migration-dir>^ --name rollback"
628
+ ]);
629
+ addGlobalOptions(command).option("--config <path>", "Path to prisma-next.config.ts").option("--name <slug>", "Name slug for the migration directory", "migration").option("--from <contract>", "Starting contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)").option("--to <contract>", "Destination contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path); defaults to the emitted contract").action(async (options) => {
650
630
  const flags = parseGlobalFlagsOrExit(options);
651
631
  const startTime = Date.now();
652
632
  const ui = createTerminalUI(flags);
@@ -785,4 +765,4 @@ function resolveBundleByPrefix(bundles, needle) {
785
765
  //#endregion
786
766
  export { formatMigrationPlanOutput as n, resolveBundleByPrefix as r, createMigrationPlanCommand as t };
787
767
 
788
- //# sourceMappingURL=migration-plan-jdAHg_gK.mjs.map
768
+ //# sourceMappingURL=migration-plan-9DJ7q7_z.mjs.map