@prisma-next/cli 0.16.0-dev.3 → 0.16.0-dev.30

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 (162) hide show
  1. package/README.md +44 -45
  2. package/dist/cli.mjs +13 -13
  3. package/dist/{client-KuBQftxz.mjs → client-CMusjGV5.mjs} +24 -25
  4. package/dist/client-CMusjGV5.mjs.map +1 -0
  5. package/dist/{command-helpers-Cpq44aVa.mjs → command-helpers-CVn3U9Uz.mjs} +12 -4
  6. package/dist/command-helpers-CVn3U9Uz.mjs.map +1 -0
  7. package/dist/commands/contract-emit.mjs +1 -1
  8. package/dist/commands/contract-infer.mjs +1 -1
  9. package/dist/commands/db-init.d.mts.map +1 -1
  10. package/dist/commands/db-init.mjs +5 -4
  11. package/dist/commands/db-init.mjs.map +1 -1
  12. package/dist/commands/db-schema.mjs +3 -3
  13. package/dist/commands/db-sign.d.mts.map +1 -1
  14. package/dist/commands/db-sign.mjs +9 -11
  15. package/dist/commands/db-sign.mjs.map +1 -1
  16. package/dist/commands/db-update.d.mts.map +1 -1
  17. package/dist/commands/db-update.mjs +11 -13
  18. package/dist/commands/db-update.mjs.map +1 -1
  19. package/dist/commands/db-verify.mjs +1 -1
  20. package/dist/commands/migrate.d.mts +1 -1
  21. package/dist/commands/migrate.d.mts.map +1 -1
  22. package/dist/commands/migrate.mjs +13 -13
  23. package/dist/commands/migrate.mjs.map +1 -1
  24. package/dist/commands/migration-check.d.mts +4 -2
  25. package/dist/commands/migration-check.d.mts.map +1 -1
  26. package/dist/commands/migration-check.mjs +1 -1
  27. package/dist/commands/migration-graph.d.mts +1 -1
  28. package/dist/commands/migration-graph.mjs +4 -4
  29. package/dist/commands/migration-list.d.mts +1 -1
  30. package/dist/commands/migration-list.d.mts.map +1 -1
  31. package/dist/commands/migration-list.mjs +1 -1
  32. package/dist/commands/migration-log.d.mts +1 -1
  33. package/dist/commands/migration-log.mjs +1 -1
  34. package/dist/commands/migration-new.d.mts.map +1 -1
  35. package/dist/commands/migration-new.mjs +16 -40
  36. package/dist/commands/migration-new.mjs.map +1 -1
  37. package/dist/commands/migration-plan.d.mts +3 -4
  38. package/dist/commands/migration-plan.d.mts.map +1 -1
  39. package/dist/commands/migration-plan.mjs +1 -1
  40. package/dist/commands/migration-show.mjs +5 -5
  41. package/dist/commands/migration-show.mjs.map +1 -1
  42. package/dist/commands/migration-status.d.mts +1 -1
  43. package/dist/commands/migration-status.d.mts.map +1 -1
  44. package/dist/commands/migration-status.mjs +1 -1
  45. package/dist/commands/ref.d.mts +1 -1
  46. package/dist/commands/ref.d.mts.map +1 -1
  47. package/dist/commands/ref.mjs +13 -18
  48. package/dist/commands/ref.mjs.map +1 -1
  49. package/dist/commands/telemetry/index.mjs +1 -1
  50. package/dist/contract-at-errors-C-l4-JEY.mjs +36 -0
  51. package/dist/contract-at-errors-C-l4-JEY.mjs.map +1 -0
  52. package/dist/{contract-emit-cJQBlvGb.mjs → contract-emit-CfIbTnsR.mjs} +6 -7
  53. package/dist/{contract-emit-cJQBlvGb.mjs.map → contract-emit-CfIbTnsR.mjs.map} +1 -1
  54. package/dist/{contract-emit-CgnXSANN.mjs → contract-emit-PaY3qRdN.mjs} +3 -3
  55. package/dist/{contract-emit-CgnXSANN.mjs.map → contract-emit-PaY3qRdN.mjs.map} +1 -1
  56. package/dist/{contract-enrichment-gn9sWbPw.mjs → contract-enrichment-JUhLv-BX.mjs} +8 -8
  57. package/dist/{contract-enrichment-gn9sWbPw.mjs.map → contract-enrichment-JUhLv-BX.mjs.map} +1 -1
  58. package/dist/{contract-infer-Cg8evbeg.mjs → contract-infer-DCju2fTk.mjs} +3 -3
  59. package/dist/{contract-infer-Cg8evbeg.mjs.map → contract-infer-DCju2fTk.mjs.map} +1 -1
  60. package/dist/{contract-space-aggregate-loader-D_3VeHVb.mjs → contract-space-aggregate-loader-B6E9LGa6.mjs} +14 -14
  61. package/dist/contract-space-aggregate-loader-B6E9LGa6.mjs.map +1 -0
  62. package/dist/{db-verify-BEclUzki.mjs → db-verify-B_dKu6Yp.mjs} +5 -5
  63. package/dist/db-verify-B_dKu6Yp.mjs.map +1 -0
  64. package/dist/exports/control-api.d.mts +4 -4
  65. package/dist/exports/control-api.d.mts.map +1 -1
  66. package/dist/exports/control-api.mjs +3 -3
  67. package/dist/exports/index.mjs +2 -2
  68. package/dist/exports/init-output.d.mts.map +1 -1
  69. package/dist/exports/init-output.mjs +1 -1
  70. package/dist/{format-DAUAZqPt.mjs → format-cCyDfmRE.mjs} +8 -7
  71. package/dist/format-cCyDfmRE.mjs.map +1 -0
  72. package/dist/{framework-components-CnbUbiJw.mjs → framework-components-DUN-TYDg.mjs} +3 -3
  73. package/dist/framework-components-DUN-TYDg.mjs.map +1 -0
  74. package/dist/{init-C3JhkHg-.mjs → init-C9U3ffHH.mjs} +55 -47
  75. package/dist/init-C9U3ffHH.mjs.map +1 -0
  76. package/dist/{inspect-live-schema-CX7EA5C3.mjs → inspect-live-schema-DHXE7skX.mjs} +4 -4
  77. package/dist/{inspect-live-schema-CX7EA5C3.mjs.map → inspect-live-schema-DHXE7skX.mjs.map} +1 -1
  78. package/dist/{migration-check-MHT3w7_v.mjs → migration-check-W5XEx4d-.mjs} +58 -30
  79. package/dist/migration-check-W5XEx4d-.mjs.map +1 -0
  80. package/dist/{migration-command-scaffold-CRyYrHZ9.mjs → migration-command-scaffold-hI5cnoGe.mjs} +4 -4
  81. package/dist/{migration-command-scaffold-CRyYrHZ9.mjs.map → migration-command-scaffold-hI5cnoGe.mjs.map} +1 -1
  82. package/dist/{migration-graph-command-render-B83xrnNy.mjs → migration-graph-command-render-DgQg5App.mjs} +3 -3
  83. package/dist/migration-graph-command-render-DgQg5App.mjs.map +1 -0
  84. package/dist/{migration-list-BAKujUjh.mjs → migration-list-ClkEaoL8.mjs} +6 -6
  85. package/dist/migration-list-ClkEaoL8.mjs.map +1 -0
  86. package/dist/{migration-log-C_xam2HZ.mjs → migration-log-CjafbZ2Z.mjs} +5 -5
  87. package/dist/{migration-log-C_xam2HZ.mjs.map → migration-log-CjafbZ2Z.mjs.map} +1 -1
  88. package/dist/{migration-path-target-DpPTsRCg.mjs → migration-path-target-C0TQuV5n.mjs} +2 -2
  89. package/dist/{migration-path-target-DpPTsRCg.mjs.map → migration-path-target-C0TQuV5n.mjs.map} +1 -1
  90. package/dist/{migration-plan-CreSVtWZ.mjs → migration-plan-Pc4hCF1H.mjs} +64 -74
  91. package/dist/migration-plan-Pc4hCF1H.mjs.map +1 -0
  92. package/dist/{migration-status-YgEvXf-u.mjs → migration-status-CqAdRzs8.mjs} +13 -12
  93. package/dist/migration-status-CqAdRzs8.mjs.map +1 -0
  94. package/dist/{output-mEQ74_nd.mjs → output-DWNYqZGc.mjs} +5 -6
  95. package/dist/output-DWNYqZGc.mjs.map +1 -0
  96. package/dist/{ref-advancement-BkXlikCA.mjs → ref-advancement-BCz7X7qJ.mjs} +13 -6
  97. package/dist/ref-advancement-BCz7X7qJ.mjs.map +1 -0
  98. package/dist/{telemetry-DVr6RFnq.mjs → telemetry-BEyNMfco.mjs} +2 -2
  99. package/dist/{telemetry-DVr6RFnq.mjs.map → telemetry-BEyNMfco.mjs.map} +1 -1
  100. package/dist/{types-D4r_HI9-.d.mts → types-DgXprE3w.d.mts} +3 -3
  101. package/dist/types-DgXprE3w.d.mts.map +1 -0
  102. package/dist/{verify-CgDVZjhc.mjs → verify-C4RazDE1.mjs} +2 -2
  103. package/dist/{verify-CgDVZjhc.mjs.map → verify-C4RazDE1.mjs.map} +1 -1
  104. package/package.json +21 -21
  105. package/src/commands/db-init.ts +1 -0
  106. package/src/commands/db-sign.ts +7 -5
  107. package/src/commands/db-update.ts +14 -6
  108. package/src/commands/db-verify.ts +1 -1
  109. package/src/commands/format.ts +1 -1
  110. package/src/commands/init/hygiene-gitattributes.ts +37 -21
  111. package/src/commands/init/init.ts +6 -6
  112. package/src/commands/init/output.ts +4 -5
  113. package/src/commands/init/reinit-cleanup.ts +16 -17
  114. package/src/commands/inspect-live-schema.ts +1 -1
  115. package/src/commands/migrate.ts +6 -5
  116. package/src/commands/migration-check.ts +72 -34
  117. package/src/commands/migration-list.ts +1 -5
  118. package/src/commands/migration-log.ts +1 -1
  119. package/src/commands/migration-new.ts +17 -41
  120. package/src/commands/migration-plan.ts +64 -88
  121. package/src/commands/migration-show.ts +2 -2
  122. package/src/commands/migration-status.ts +6 -7
  123. package/src/commands/ref.ts +19 -14
  124. package/src/control-api/client.ts +7 -8
  125. package/src/control-api/contract-enrichment.ts +7 -7
  126. package/src/control-api/operations/contract-emit.ts +2 -3
  127. package/src/control-api/operations/db-init.ts +3 -3
  128. package/src/control-api/operations/db-run.ts +6 -6
  129. package/src/control-api/operations/db-update.ts +2 -2
  130. package/src/control-api/operations/db-verify.ts +4 -4
  131. package/src/control-api/operations/format.ts +5 -4
  132. package/src/control-api/operations/migrate.ts +3 -3
  133. package/src/control-api/types.ts +1 -1
  134. package/src/utils/cli-errors.ts +15 -7
  135. package/src/utils/contract-at-errors.ts +13 -22
  136. package/src/utils/contract-space-aggregate-loader.ts +8 -8
  137. package/src/utils/contract-space-seed-phase.ts +11 -9
  138. package/src/utils/extension-pack-inputs.ts +8 -8
  139. package/src/utils/formatters/migration-graph-labels.ts +1 -2
  140. package/src/utils/formatters/migration-list-data-column.ts +1 -2
  141. package/src/utils/framework-components.ts +9 -9
  142. package/src/utils/integrity-violation-to-check-failure.ts +3 -3
  143. package/src/utils/migration-command-scaffold.ts +1 -1
  144. package/src/utils/plan-resolution.ts +7 -10
  145. package/src/utils/ref-advancement.ts +22 -3
  146. package/dist/client-KuBQftxz.mjs.map +0 -1
  147. package/dist/command-helpers-Cpq44aVa.mjs.map +0 -1
  148. package/dist/contract-at-errors-D9gEjYtg.mjs +0 -42
  149. package/dist/contract-at-errors-D9gEjYtg.mjs.map +0 -1
  150. package/dist/contract-space-aggregate-loader-D_3VeHVb.mjs.map +0 -1
  151. package/dist/db-verify-BEclUzki.mjs.map +0 -1
  152. package/dist/format-DAUAZqPt.mjs.map +0 -1
  153. package/dist/framework-components-CnbUbiJw.mjs.map +0 -1
  154. package/dist/init-C3JhkHg-.mjs.map +0 -1
  155. package/dist/migration-check-MHT3w7_v.mjs.map +0 -1
  156. package/dist/migration-graph-command-render-B83xrnNy.mjs.map +0 -1
  157. package/dist/migration-list-BAKujUjh.mjs.map +0 -1
  158. package/dist/migration-plan-CreSVtWZ.mjs.map +0 -1
  159. package/dist/migration-status-YgEvXf-u.mjs.map +0 -1
  160. package/dist/output-mEQ74_nd.mjs.map +0 -1
  161. package/dist/ref-advancement-BkXlikCA.mjs.map +0 -1
  162. package/dist/types-D4r_HI9-.d.mts.map +0 -1
@@ -2,7 +2,7 @@ import { materialiseExtensionMigrationPackageIfMissing } from '@prisma-next/migr
2
2
  import type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';
3
3
  import type { MigrationOps } from '@prisma-next/migration-tools/package';
4
4
  import {
5
- emitContractSpaceArtefacts,
5
+ emitContractSpaceArtifacts,
6
6
  planAllSpaces,
7
7
  readContractSpaceHeadRef,
8
8
  type SpacePlanOutput,
@@ -39,7 +39,7 @@ export interface SeedPhaseExtensionInput {
39
39
 
40
40
  export interface ContractSpaceSeedPhaseInputs {
41
41
  readonly migrationsDir: string;
42
- readonly extensionPacks: ReadonlyArray<SeedPhaseExtensionInput>;
42
+ readonly extensions: ReadonlyArray<SeedPhaseExtensionInput>;
43
43
  }
44
44
 
45
45
  /**
@@ -53,7 +53,7 @@ export interface ContractSpaceSeedPhaseInputs {
53
53
  * - `action: 'unchanged'` — the on-disk head already matched the
54
54
  * descriptor and no new migration packages needed to be written.
55
55
  *
56
- * Either way, the artefacts (`contract.json`, `contract.d.ts`,
56
+ * Either way, the artifacts (`contract.json`, `contract.d.ts`,
57
57
  * `refs/head.json`) are re-emitted: the framework owns those files and
58
58
  * makes the re-emit observably idempotent at the byte level.
59
59
  */
@@ -75,9 +75,11 @@ export interface ContractSpaceSeedPhaseResult {
75
75
  * For every extension that exposes a `contractSpace`:
76
76
  *
77
77
  * 1. Read the on-disk head ref (returns `null` on first emit).
78
- * 2. Re-emit `contract.json` / `contract.d.ts` / `refs/head.json`
79
- * unconditionally via {@link emitContractSpaceArtefacts}. The
80
- * framework owns these files; re-emit is the contract.
78
+ * 2. Write the head contract into the migrations-root snapshot store
79
+ * (write-if-absent, keyed by hash) and unconditionally re-emit
80
+ * `refs/head.json`, via {@link emitContractSpaceArtifacts}. The
81
+ * framework owns `refs/head.json`; re-emit is the contract for that
82
+ * file. The snapshot itself is only written once per distinct hash.
81
83
  * 3. Materialise any descriptor-shipped migration packages not yet on
82
84
  * disk via {@link materialiseExtensionMigrationPackageIfMissing}.
83
85
  * Existing packages are left untouched (by-existence skip).
@@ -96,7 +98,7 @@ export interface ContractSpaceSeedPhaseResult {
96
98
  export async function runContractSpaceSeedPhase(
97
99
  inputs: ContractSpaceSeedPhaseInputs,
98
100
  ): Promise<ContractSpaceSeedPhaseResult> {
99
- const planInputs = inputs.extensionPacks
101
+ const planInputs = inputs.extensions
100
102
  .filter(
101
103
  (
102
104
  pack,
@@ -132,7 +134,7 @@ export async function runContractSpaceSeedPhase(
132
134
  string,
133
135
  NonNullable<SeedPhaseExtensionInput['contractSpace']>
134
136
  >();
135
- for (const pack of inputs.extensionPacks) {
137
+ for (const pack of inputs.extensions) {
136
138
  if (pack.contractSpace !== undefined) descriptorBySpace.set(pack.id, pack.contractSpace);
137
139
  }
138
140
 
@@ -144,7 +146,7 @@ export async function runContractSpaceSeedPhase(
144
146
  const onDiskHeadRef = await readContractSpaceHeadRef(inputs.migrationsDir, space.spaceId);
145
147
  const priorHash = onDiskHeadRef?.hash ?? null;
146
148
 
147
- await emitContractSpaceArtefacts(inputs.migrationsDir, space.spaceId, {
149
+ await emitContractSpaceArtifacts(inputs.migrationsDir, space.spaceId, {
148
150
  contract: descriptor.contractJson,
149
151
  contractDts: buildPlaceholderContractDts(space.spaceId),
150
152
  headRef: { hash: descriptor.headRef.hash, invariants: descriptor.headRef.invariants },
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Single descriptor-import boundary for CLI consumers of `Config.extensionPacks`.
2
+ * Single descriptor-import boundary for CLI consumers of `Config.extensions`.
3
3
  *
4
4
  * Every CLI command / utility that reads an extension descriptor's
5
5
  * `contractSpace` projection (loader, migrate-pass, extension-migrations
@@ -54,9 +54,9 @@ export interface ExtensionPackInput {
54
54
  }
55
55
 
56
56
  /**
57
- * Structural shape we read off each `Config.extensionPacks` entry.
57
+ * Structural shape we read off each `Config.extensions` entry.
58
58
  *
59
- * The CLI is the descriptor-import boundary; `extensionPacks` is the only
59
+ * The CLI is the descriptor-import boundary; `extensions` is the only
60
60
  * surface where the SQL-family-typed `ControlExtensionDescriptor` flows
61
61
  * into framework-neutral helpers. The structural cast lives here, and
62
62
  * here alone — every other CLI consumer reads the canonical
@@ -76,14 +76,14 @@ type ExtensionPackLike = {
76
76
  };
77
77
 
78
78
  /**
79
- * Project the CLI's `Config.extensionPacks` array into the canonical
79
+ * Project the CLI's `Config.extensions` array into the canonical
80
80
  * {@link ExtensionPackInput} shape. The single `as ExtensionPackLike`
81
81
  * structural cast in the CLI lives inside this function.
82
82
  */
83
83
  export function toExtensionInputs(
84
- extensionPacks: ReadonlyArray<unknown>,
84
+ extensions: ReadonlyArray<unknown>,
85
85
  ): readonly ExtensionPackInput[] {
86
- return extensionPacks.map((raw) => {
86
+ return extensions.map((raw) => {
87
87
  const pack = raw as ExtensionPackLike;
88
88
  if (pack.contractSpace === undefined) {
89
89
  return { id: pack.id, targetId: pack.targetId };
@@ -147,10 +147,10 @@ export function toDeclaredExtensions(
147
147
  * always reads the contract from on-disk artefacts instead.
148
148
  */
149
149
  export function toDeclaredExtensionsFromRaw(
150
- extensionPacks: ReadonlyArray<unknown>,
150
+ extensions: ReadonlyArray<unknown>,
151
151
  ): readonly DeclaredExtensionEntry[] {
152
152
  const entries: DeclaredExtensionEntry[] = [];
153
- for (const raw of extensionPacks) {
153
+ for (const raw of extensions) {
154
154
  if (typeof raw !== 'object' || raw === null) continue;
155
155
  const descriptor = Object.getOwnPropertyDescriptor(raw, 'contractSpace');
156
156
  if (descriptor === undefined) continue;
@@ -104,8 +104,7 @@ function abbreviateHash(hash: string, hashLength: number, emptySource: string):
104
104
  if (hash === EMPTY_CONTRACT_HASH) {
105
105
  return emptySource;
106
106
  }
107
- const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;
108
- return stripped.slice(0, hashLength);
107
+ return hash.slice(0, hashLength);
109
108
  }
110
109
 
111
110
  interface ContractOverlayNames {
@@ -18,8 +18,7 @@ export function migrationListEmptySource(glyphMode: GlyphMode): string {
18
18
  }
19
19
 
20
20
  export function abbreviateContractHash(hash: string): string {
21
- const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;
22
- return stripped.slice(0, MIGRATION_LIST_HASH_WIDTH);
21
+ return hash.slice(0, MIGRATION_LIST_HASH_WIDTH);
23
22
  }
24
23
 
25
24
  export function padFromHashColumn(text: string, width: number): string {
@@ -4,7 +4,7 @@ import {
4
4
  type TargetBoundComponentDescriptor,
5
5
  } from '@prisma-next/framework-components/components';
6
6
  import type { ControlStack } from '@prisma-next/framework-components/control';
7
- import { errorConfigValidation, errorContractMissingExtensionPacks } from './cli-errors';
7
+ import { errorConfigValidation, errorContractMissingExtensions } from './cli-errors';
8
8
 
9
9
  /**
10
10
  * Asserts that all framework components are compatible with the expected family and target.
@@ -27,7 +27,7 @@ import { errorConfigValidation, errorContractMissingExtensionPacks } from './cli
27
27
  * @example
28
28
  * ```ts
29
29
  * const config = await loadConfig();
30
- * const frameworkComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];
30
+ * const frameworkComponents = [config.target, config.adapter, ...(config.extensions ?? [])];
31
31
  *
32
32
  * // Validate and type-narrow components before passing to planner
33
33
  * const typedComponents = assertFrameworkComponentsCompatible(
@@ -114,12 +114,12 @@ export function assertFrameworkComponentsCompatible<
114
114
  * This check ensures the emitted contract matches the CLI config before running
115
115
  * commands that depend on the contract (e.g., db verify, db sign).
116
116
  *
117
- * @param contract - The contract to validate (must include targetFamily, target, extensionPacks).
118
- * @param stack - The control plane stack (target, adapter, driver, extensionPacks).
117
+ * @param contract - The contract to validate (must include targetFamily, target, extensions).
118
+ * @param stack - The control plane stack (target, adapter, driver, extensions).
119
119
  *
120
120
  * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target
121
121
  * doesn't match the configured family/target.
122
- * @throws {CliStructuredError} errorContractMissingExtensionPacks when the contract requires
122
+ * @throws {CliStructuredError} errorContractMissingExtensions when the contract requires
123
123
  * extension packs that are not provided in the config (includes all missing packs in error.meta).
124
124
  *
125
125
  * @example
@@ -141,14 +141,14 @@ export function assertContractRequirementsSatisfied<
141
141
  contract,
142
142
  stack,
143
143
  }: {
144
- readonly contract: Pick<Contract, 'targetFamily' | 'target' | 'extensionPacks'>;
144
+ readonly contract: Pick<Contract, 'targetFamily' | 'target' | 'extensions'>;
145
145
  readonly stack: ControlStack<TFamilyId, TTargetId>;
146
146
  }): void {
147
147
  const providedComponentIds = new Set<string>([
148
148
  stack.target.id,
149
149
  ...(stack.adapter ? [stack.adapter.id] : []),
150
150
  ]);
151
- for (const extension of stack.extensionPacks) {
151
+ for (const extension of stack.extensions) {
152
152
  providedComponentIds.add(extension.id);
153
153
  }
154
154
 
@@ -172,8 +172,8 @@ export function assertContractRequirementsSatisfied<
172
172
  }
173
173
 
174
174
  if (result.missingExtensionPackIds.length > 0) {
175
- throw errorContractMissingExtensionPacks({
176
- missingExtensionPacks: result.missingExtensionPackIds,
175
+ throw errorContractMissingExtensions({
176
+ missingExtensions: result.missingExtensionPackIds,
177
177
  providedComponentIds: [...providedComponentIds],
178
178
  });
179
179
  }
@@ -69,15 +69,15 @@ export function integrityViolationToCheckFailure(
69
69
  code: 'MIGRATION.CHECK_ORPHAN_SPACE_DIR',
70
70
  where: spaceRelative(violation.spaceId),
71
71
  why: `Contract-space directory "${violation.spaceId}" exists on disk but no extension declares it.`,
72
- fix: 'Remove the orphan directory, or declare the extension in `extensionPacks`.',
72
+ fix: 'Remove the orphan directory, or declare the extension in `extensions`.',
73
73
  };
74
74
  case 'declaredButUnmigrated':
75
75
  return {
76
76
  space: violation.spaceId,
77
77
  code: 'MIGRATION.CHECK_DECLARED_BUT_UNMIGRATED',
78
78
  where: spaceRelative(violation.spaceId),
79
- why: `Extension "${violation.spaceId}" is declared in \`extensionPacks\` but has no on-disk migrations directory.`,
80
- fix: 'Re-emit the extension contract-space artefacts with `prisma-next contract emit` and migration planning, or remove the extension from `extensionPacks` if it is unused.',
79
+ why: `Extension "${violation.spaceId}" is declared in \`extensions\` but has no on-disk migrations directory.`,
80
+ fix: 'Re-emit the extension contract-space artefacts with `prisma-next contract emit` and migration planning, or remove the extension from `extensions` if it is unused.',
81
81
  };
82
82
  case 'headRefMissing':
83
83
  return {
@@ -154,7 +154,7 @@ export async function prepareMigrationContext(
154
154
  target: config.target,
155
155
  adapter: config.adapter,
156
156
  driver: config.driver,
157
- extensionPacks: config.extensionPacks ?? [],
157
+ extensions: config.extensions ?? [],
158
158
  });
159
159
 
160
160
  // Create progress adapter
@@ -19,7 +19,7 @@ import {
19
19
  } from './cli-errors';
20
20
  import { mapContractAtError } from './contract-at-errors';
21
21
 
22
- const FULL_HASH_PATTERN = /^sha256:([0-9a-f]{64}|empty)$/;
22
+ const FULL_HASH_PATTERN = /^([0-9a-f]{64}|empty)$/;
23
23
 
24
24
  export function looksLikeFullHash(input: string): boolean {
25
25
  return FULL_HASH_PATTERN.test(input);
@@ -27,9 +27,9 @@ export function looksLikeFullHash(input: string): boolean {
27
27
 
28
28
  export type FromResolution =
29
29
  | { kind: 'greenfield'; fromHash: null; fromContract: null }
30
- | { kind: 'graph-node'; fromHash: string; fromContract: Contract; sourceDir: string }
30
+ | { kind: 'graph-node'; fromHash: string; fromContract: Contract }
31
31
  | {
32
- kind: 'snapshot';
32
+ kind: 'ref';
33
33
  fromHash: string;
34
34
  fromContract: Contract;
35
35
  contractDts: string;
@@ -81,7 +81,7 @@ export function assertFromIsGraphNode(
81
81
 
82
82
  type RefContractResolution =
83
83
  | {
84
- kind: 'snapshot';
84
+ kind: 'ref';
85
85
  hash: string;
86
86
  contract: Contract;
87
87
  contractJson: unknown;
@@ -93,7 +93,6 @@ type RefContractResolution =
93
93
  contract: Contract;
94
94
  contractJson: unknown;
95
95
  contractDts: string;
96
- sourceDir: string;
97
96
  };
98
97
 
99
98
  async function resolveContractRef(
@@ -107,9 +106,9 @@ async function resolveContractRef(
107
106
  try {
108
107
  const at = await space.contractAt(hash, refName !== undefined ? { refName } : undefined);
109
108
 
110
- if (at.provenance === 'snapshot') {
109
+ if (at.provenance === 'ref') {
111
110
  return ok({
112
- kind: 'snapshot',
111
+ kind: 'ref',
113
112
  hash: at.hash,
114
113
  contract: at.contract,
115
114
  contractJson: at.contractJson,
@@ -123,7 +122,6 @@ async function resolveContractRef(
123
122
  contract: at.contract,
124
123
  contractJson: at.contractJson,
125
124
  contractDts: at.contractDts,
126
- sourceDir: at.sourceDir,
127
125
  });
128
126
  } catch (error) {
129
127
  return mapContractAtError(
@@ -152,7 +150,6 @@ async function resolveFromPolicy(
152
150
  kind: 'graph-node',
153
151
  fromHash: resolution.value.hash,
154
152
  fromContract: resolution.value.contract,
155
- sourceDir: resolution.value.sourceDir,
156
153
  });
157
154
  }
158
155
 
@@ -178,7 +175,7 @@ async function resolveFromPolicy(
178
175
  throw error;
179
176
  }
180
177
  return ok({
181
- kind: 'snapshot',
178
+ kind: 'ref',
182
179
  fromHash: hash,
183
180
  fromContract: contract,
184
181
  contractDts,
@@ -1,8 +1,14 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import type { ContractIR } from '@prisma-next/migration-tools/refs';
3
- import { writeRefPaired } from '@prisma-next/migration-tools/refs';
2
+ import { writeContractSnapshot } from '@prisma-next/migration-tools/contract-snapshot-store';
3
+ import { errorInvalidRefName } from '@prisma-next/migration-tools/errors';
4
+ import { validateRefName, writeRef } from '@prisma-next/migration-tools/refs';
4
5
  import { ifDefined } from '@prisma-next/utils/defined';
5
6
 
7
+ export interface ContractIR {
8
+ readonly contract: unknown;
9
+ readonly contractDts: string;
10
+ }
11
+
6
12
  export interface RefAdvancementFields {
7
13
  readonly advancedRef: { readonly name: string; readonly hash: string } | null;
8
14
  readonly plannedAdvanceRef: { readonly name: string; readonly hash: string } | null;
@@ -32,11 +38,22 @@ export async function readContractIR(
32
38
 
33
39
  export async function executeRefAdvancement(
34
40
  refsDir: string,
41
+ migrationsDir: string,
35
42
  name: string,
36
43
  hash: string,
37
44
  contractIR: ContractIR,
38
45
  ): Promise<{ name: string; hash: string }> {
39
- await writeRefPaired(refsDir, name, { hash, invariants: [] }, contractIR);
46
+ // Validate the ref name before writing anything: writeRef validates it too,
47
+ // but only after the store write below, which would otherwise leave a
48
+ // (harmless, but pointless) orphan store entry on an invalid name.
49
+ if (!validateRefName(name)) {
50
+ throw errorInvalidRefName(name);
51
+ }
52
+ await writeContractSnapshot(migrationsDir, hash, {
53
+ contractJson: contractIR.contract,
54
+ contractDts: contractIR.contractDts,
55
+ });
56
+ await writeRef(refsDir, name, { hash, invariants: [] });
40
57
  return { name, hash };
41
58
  }
42
59
 
@@ -44,6 +61,7 @@ export async function buildRefAdvancementFields(options: {
44
61
  readonly advanceRef?: string;
45
62
  readonly db?: string;
46
63
  readonly refsDir: string;
64
+ readonly migrationsDir: string;
47
65
  readonly contractIR: ContractIR;
48
66
  readonly mode: 'plan' | 'apply';
49
67
  readonly hash: string;
@@ -60,6 +78,7 @@ export async function buildRefAdvancementFields(options: {
60
78
  }
61
79
  const advancedRef = await executeRefAdvancement(
62
80
  options.refsDir,
81
+ options.migrationsDir,
63
82
  name,
64
83
  options.hash,
65
84
  options.contractIR,