@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
@@ -119,7 +119,7 @@ async function executeMigrationShowCommand(
119
119
  target: config.target,
120
120
  adapter: config.adapter,
121
121
  ...ifDefined('driver', config.driver),
122
- extensionPacks: config.extensionPacks ?? [],
122
+ extensions: config.extensions ?? [],
123
123
  });
124
124
 
125
125
  let contractJsonContent: string;
@@ -228,7 +228,7 @@ export function createMigrationShowCommand(): Command {
228
228
  );
229
229
  setCommandExamples(command, [
230
230
  'prisma-next migration show 20260101_100000_add_user',
231
- 'prisma-next migration show sha256:a1b2c3',
231
+ 'prisma-next migration show a1b2c3',
232
232
  'prisma-next migration show 20260101_100000_add_user --json',
233
233
  ]);
234
234
  setCommandSeeAlso(command, [
@@ -111,8 +111,7 @@ interface MigrationStatusCommandResult {
111
111
  }
112
112
 
113
113
  function shortDisplayHash(hash: string): string {
114
- const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;
115
- return stripped.slice(0, 12);
114
+ return hash.slice(0, 12);
116
115
  }
117
116
 
118
117
  function resolveTarget(contractHash: string, activeRefHash: string | undefined): string {
@@ -421,7 +420,7 @@ export async function executeMigrationStatusCommand(
421
420
  target: config.target,
422
421
  adapter: config.adapter,
423
422
  driver: config.driver,
424
- extensionPacks: config.extensionPacks ?? [],
423
+ extensions: config.extensions ?? [],
425
424
  });
426
425
  try {
427
426
  await client.connect(dbConnection);
@@ -660,10 +659,10 @@ export function createMigrationStatusCommand(): Command {
660
659
  setCommandExamples(command, [
661
660
  'prisma-next migration status --db $DATABASE_URL',
662
661
  'prisma-next migration status --to production --db $DATABASE_URL',
663
- 'prisma-next migration status --from sha256:abc --to production',
664
- 'prisma-next migration status --from sha256:abc --to production --json',
665
- 'prisma-next migration status --ascii --from sha256:abc --to production',
666
- 'prisma-next migration status --legend --from sha256:abc --to production',
662
+ 'prisma-next migration status --from abc123 --to production',
663
+ 'prisma-next migration status --from abc123 --to production --json',
664
+ 'prisma-next migration status --ascii --from abc123 --to production',
665
+ 'prisma-next migration status --legend --from abc123 --to production',
667
666
  ]);
668
667
  setCommandSeeAlso(command, [
669
668
  { verb: 'migration log', oneLiner: 'Show executed migration history' },
@@ -1,16 +1,19 @@
1
- import { readFile } from 'node:fs/promises';
2
1
  import { loadConfig } from '@prisma-next/config-loader';
3
2
  import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
3
+ import {
4
+ contractSnapshotDir,
5
+ readContractSnapshotJson,
6
+ } from '@prisma-next/migration-tools/contract-snapshot-store';
4
7
  import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
5
8
  import { findLatestMigration, isGraphNode } from '@prisma-next/migration-tools/migration-graph';
6
9
  import { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';
7
10
  import type { RefEntry } from '@prisma-next/migration-tools/refs';
8
11
  import {
9
- deleteRefPaired,
12
+ deleteRef,
10
13
  readRefs,
11
14
  validateRefName,
12
15
  validateRefValue,
13
- writeRefPaired,
16
+ writeRef,
14
17
  } from '@prisma-next/migration-tools/refs';
15
18
  import { notOk, ok, type Result } from '@prisma-next/utils/result';
16
19
  import { Command } from 'commander';
@@ -34,7 +37,6 @@ import {
34
37
  import { buildReadAggregate } from '../utils/contract-space-aggregate-loader';
35
38
  import { formatCommandHelp } from '../utils/formatters/help';
36
39
  import { parseGlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
37
- import { readContractIR } from '../utils/ref-advancement';
38
40
  import { handleResult } from '../utils/result-handler';
39
41
  import { createTerminalUI } from '../utils/terminal-ui';
40
42
 
@@ -114,26 +116,29 @@ export async function executeRefSetCommand(
114
116
  return notOk(errorRefSetBundleNotFound(resolvedHash));
115
117
  }
116
118
 
117
- const contractJsonPath = join(matchingBundle.dirPath, 'end-contract.json');
118
- let contractJson: Record<string, unknown>;
119
+ const contractJsonPath = join(
120
+ contractSnapshotDir(migrationsDir, resolvedHash),
121
+ 'contract.json',
122
+ );
119
123
  try {
120
- const raw = await readFile(contractJsonPath, 'utf-8');
121
- contractJson = JSON.parse(raw) as Record<string, unknown>;
124
+ await readContractSnapshotJson(migrationsDir, resolvedHash);
122
125
  } catch (readError) {
123
- if (readError instanceof Error && (readError as NodeJS.ErrnoException).code === 'ENOENT') {
126
+ if (
127
+ MigrationToolsError.is(readError) &&
128
+ readError.code === 'MIGRATION.CONTRACT_SNAPSHOT_MISSING'
129
+ ) {
124
130
  return notOk(
125
131
  errorFileNotFound(contractJsonPath, {
126
- why: `Migration bundle for hash ${resolvedHash} is missing its end-contract snapshot at ${contractJsonPath}`,
127
- fix: 'Run `pnpm fixtures:check`, or re-emit the migration so its end-contract.json is restored.',
132
+ why: `Migration bundle for hash ${resolvedHash} is missing its contract snapshot at ${contractJsonPath}`,
133
+ fix: 'Restore migrations/snapshots/ from version control, or re-run the command that produced this migration to regenerate its snapshot.',
128
134
  }),
129
135
  );
130
136
  }
131
137
  throw readError;
132
138
  }
133
139
 
134
- const contractIR = await readContractIR(contractJson, contractJsonPath);
135
140
  const entry: RefEntry = { hash: resolvedHash, invariants: [] };
136
- await writeRefPaired(refsDir, name, entry, contractIR);
141
+ await writeRef(refsDir, name, entry);
137
142
  return ok({ ok: true as const, ref: name, hash: resolvedHash, invariants: [] });
138
143
  } catch (error) {
139
144
  if (error instanceof CliStructuredError) return notOk(error);
@@ -148,7 +153,7 @@ export async function executeRefDeleteCommand(
148
153
  try {
149
154
  const config = await loadConfig(options.config);
150
155
  const { refsDir } = resolveMigrationPaths(options.config, config);
151
- await deleteRefPaired(refsDir, name);
156
+ await deleteRef(refsDir, name);
152
157
  return ok({ ok: true as const, ref: name, deleted: true as const });
153
158
  } catch (error) {
154
159
  if (error instanceof CliStructuredError) return notOk(error);
@@ -103,7 +103,7 @@ class ControlClientImpl implements ControlClient {
103
103
  target: this.options.target,
104
104
  adapter: this.options.adapter,
105
105
  driver: this.options.driver,
106
- extensionPacks: this.options.extensionPacks,
106
+ extensions: this.options.extensions,
107
107
  });
108
108
 
109
109
  this.familyInstance = this.options.family.create(this.stack);
@@ -112,7 +112,7 @@ class ControlClientImpl implements ControlClient {
112
112
  const rawComponents = [
113
113
  this.options.target,
114
114
  this.options.adapter,
115
- ...(this.options.extensionPacks ?? []),
115
+ ...(this.options.extensions ?? []),
116
116
  ];
117
117
  this.frameworkComponents = assertFrameworkComponentsCompatible(
118
118
  this.options.family.familyId,
@@ -404,7 +404,7 @@ class ControlClientImpl implements ControlClient {
404
404
  frameworkComponents,
405
405
  migrationsDir: options.migrationsDir,
406
406
  targetId: this.options.target.targetId,
407
- extensionPacks: this.options.extensionPacks ?? [],
407
+ extensions: this.options.extensions ?? [],
408
408
  ...ifDefined('onProgress', onProgress),
409
409
  });
410
410
  }
@@ -438,7 +438,7 @@ class ControlClientImpl implements ControlClient {
438
438
  frameworkComponents,
439
439
  migrationsDir: options.migrationsDir,
440
440
  targetId: this.options.target.targetId,
441
- extensionPacks: this.options.extensionPacks ?? [],
441
+ extensions: this.options.extensions ?? [],
442
442
  ...ifDefined('acceptDataLoss', options.acceptDataLoss),
443
443
  ...ifDefined('onProgress', onProgress),
444
444
  });
@@ -455,7 +455,7 @@ class ControlClientImpl implements ControlClient {
455
455
  contract: options.contract,
456
456
  migrationsDir: options.migrationsDir,
457
457
  targetId: this.options.target.targetId,
458
- extensionPacks: this.options.extensionPacks ?? [],
458
+ extensions: this.options.extensions ?? [],
459
459
  frameworkComponents,
460
460
  mode: options.strict ? 'strict' : 'lenient',
461
461
  skipSchema: options.skipSchema,
@@ -508,7 +508,7 @@ class ControlClientImpl implements ControlClient {
508
508
  migrations: this.options.target.migrations,
509
509
  frameworkComponents,
510
510
  migrationsDir: options.migrationsDir,
511
- extensionPacks: this.options.extensionPacks ?? [],
511
+ extensions: this.options.extensions ?? [],
512
512
  targetId: this.options.target.targetId,
513
513
  ...ifDefined('refHash', options.refHash),
514
514
  ...ifDefined('refInvariants', options.refInvariants),
@@ -607,9 +607,8 @@ class ControlClientImpl implements ControlClient {
607
607
  try {
608
608
  const stack = this.stack!;
609
609
  const sourceContext = {
610
- composedExtensionPacks: stack.extensionPacks.map((p) => p.id),
610
+ composedExtensions: stack.extensions.map((p) => p.id),
611
611
  composedExtensionContracts: stack.extensionContracts,
612
- scalarTypeDescriptors: stack.scalarTypeDescriptors,
613
612
  authoringContributions: stack.authoringContributions,
614
613
  codecLookup: stack.codecLookup,
615
614
  controlMutationDefaults: stack.controlMutationDefaults,
@@ -65,21 +65,21 @@ export function enrichContract(
65
65
  ): Contract {
66
66
  const mergedCapabilities = mergeCapabilityMatrices(ir.capabilities, components);
67
67
 
68
- const extensionPacksMeta: Record<string, unknown> = {};
68
+ const extensionsMeta: Record<string, unknown> = {};
69
69
  for (const component of components) {
70
70
  if (component.kind === 'extension') {
71
- extensionPacksMeta[component.id] = extractExtensionPackMeta(component);
71
+ extensionsMeta[component.id] = extractExtensionPackMeta(component);
72
72
  }
73
73
  }
74
74
 
75
- const extensionPacks =
76
- Object.keys(extensionPacksMeta).length > 0
77
- ? { ...ir.extensionPacks, ...extensionPacksMeta }
78
- : ir.extensionPacks;
75
+ const extensions =
76
+ Object.keys(extensionsMeta).length > 0
77
+ ? { ...ir.extensions, ...extensionsMeta }
78
+ : ir.extensions;
79
79
 
80
80
  return {
81
81
  ...ir,
82
82
  capabilities: sortDeepTyped(mergedCapabilities),
83
- extensionPacks: sortDeepTyped(extensionPacks),
83
+ extensions: sortDeepTyped(extensions),
84
84
  };
85
85
  }
@@ -195,9 +195,8 @@ export async function executeContractEmit(
195
195
  const stack = createControlStack(config);
196
196
 
197
197
  const sourceContext = {
198
- composedExtensionPacks: stack.extensionPacks.map((p) => p.id),
198
+ composedExtensions: stack.extensions.map((p) => p.id),
199
199
  composedExtensionContracts: stack.extensionContracts,
200
- scalarTypeDescriptors: stack.scalarTypeDescriptors,
201
200
  authoringContributions: stack.authoringContributions,
202
201
  codecLookup: stack.codecLookup,
203
202
  controlMutationDefaults: stack.controlMutationDefaults,
@@ -231,7 +230,7 @@ export async function executeContractEmit(
231
230
  let emitResult: Awaited<ReturnType<typeof emit>>;
232
231
  try {
233
232
  const familyInstance = config.family.create(stack);
234
- const rawComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];
233
+ const rawComponents = [config.target, config.adapter, ...(config.extensions ?? [])];
235
234
  const frameworkComponents = assertFrameworkComponentsCompatible(
236
235
  config.family.familyId,
237
236
  config.target.targetId,
@@ -25,7 +25,7 @@ import { executeRun } from './db-run';
25
25
  * 3. The runner's `execute` applies the per-space plans
26
26
  * inside one outer transaction.
27
27
  *
28
- * `extensionPacks` mirrors `Config.extensionPacks` (descriptor list).
28
+ * `extensions` mirrors `Config.extensions` (descriptor list).
29
29
  * The loader (sub-spec § Loader) is the sole descriptor-import boundary.
30
30
  */
31
31
  export interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {
@@ -55,7 +55,7 @@ export interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extend
55
55
  * routes through the same loader → planner → runner pipeline with no
56
56
  * extension spaces in the aggregate.
57
57
  */
58
- readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
58
+ readonly extensions?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
59
59
  /** Optional progress callback for observing operation progress */
60
60
  readonly onProgress?: OnControlProgress;
61
61
  }
@@ -80,7 +80,7 @@ export async function executeDbInit<TFamilyId extends string, TTargetId extends
80
80
  frameworkComponents: options.frameworkComponents,
81
81
  migrationsDir: options.migrationsDir,
82
82
  targetId: options.targetId,
83
- extensionPacks: options.extensionPacks ?? [],
83
+ extensions: options.extensions ?? [],
84
84
  policy: { allowedOperationClasses: ['additive'] },
85
85
  action: 'dbInit',
86
86
  ...ifDefined('onProgress', options.onProgress),
@@ -80,7 +80,7 @@ export interface ExecuteRunOptions<TFamilyId extends string, TTargetId extends s
80
80
  >;
81
81
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
82
82
  readonly migrationsDir: string;
83
- readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
83
+ readonly extensions: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
84
84
  readonly targetId: TTargetId;
85
85
  readonly policy: MigrationOperationPolicy;
86
86
  readonly action: 'dbInit' | 'dbUpdate';
@@ -119,7 +119,7 @@ export async function executeRun<TFamilyId extends string, TTargetId extends str
119
119
  migrations,
120
120
  frameworkComponents,
121
121
  migrationsDir,
122
- extensionPacks,
122
+ extensions,
123
123
  targetId,
124
124
  policy,
125
125
  action,
@@ -131,7 +131,7 @@ export async function executeRun<TFamilyId extends string, TTargetId extends str
131
131
  targetId,
132
132
  migrationsDir,
133
133
  appContract: contract,
134
- extensionPacks,
134
+ extensions,
135
135
  deserializeContract: (json) => familyInstance.deserializeContract(json),
136
136
  };
137
137
  const loaded = await buildContractSpaceAggregate(loadInputs);
@@ -283,7 +283,7 @@ function aggregatePlannerWarnings(
283
283
  * Compare the live `_prisma_marker` rows against the aggregate's
284
284
  * declared contract spaces. Any marker row whose `space` is not a space of
285
285
  * the aggregate is an "orphan" — typically a marker left behind by
286
- * an extension that was removed from `extensionPacks` without first
286
+ * an extension that was removed from `extensions` without first
287
287
  * cleaning up its on-disk migrations / database tables.
288
288
  *
289
289
  * Returns a {@link CliStructuredError} envelope (code
@@ -319,8 +319,8 @@ function detectOrphanMarkers(
319
319
  .map((s) => `"${s}"`)
320
320
  .join(
321
321
  ', ',
322
- )}) that are not declared in the project's \`extensionPacks\`. The aggregate pipeline refuses to advance markers it cannot account for.`,
323
- fix: 'Either re-declare the missing extension(s) in `extensionPacks` (so the aggregate owns them again), or remove the orphan marker row(s) from `_prisma_marker` once you have confirmed the corresponding tables can be safely retired.',
322
+ )}) that are not declared in the project's \`extensions\`. The aggregate pipeline refuses to advance markers it cannot account for.`,
323
+ fix: 'Either re-declare the missing extension(s) in `extensions` (so the aggregate owns them again), or remove the orphan marker row(s) from `_prisma_marker` once you have confirmed the corresponding tables can be safely retired.',
324
324
  docsUrl: 'https://pris.ly/contract-spaces',
325
325
  meta: {
326
326
  violations: orphans.map((spaceId) => ({ kind: 'orphanMarker', spaceId })),
@@ -40,7 +40,7 @@ export interface ExecuteDbUpdateOptions<TFamilyId extends string, TTargetId exte
40
40
  readonly acceptDataLoss?: boolean;
41
41
  readonly migrationsDir: string;
42
42
  readonly targetId: TTargetId;
43
- readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
43
+ readonly extensions?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
44
44
  readonly onProgress?: OnControlProgress;
45
45
  }
46
46
 
@@ -65,7 +65,7 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
65
65
  frameworkComponents: options.frameworkComponents,
66
66
  migrationsDir: options.migrationsDir,
67
67
  targetId: options.targetId,
68
- extensionPacks: options.extensionPacks ?? [],
68
+ extensions: options.extensions ?? [],
69
69
  policy: DB_UPDATE_POLICY,
70
70
  action: 'dbUpdate' as const,
71
71
  ...ifDefined('onProgress', options.onProgress),
@@ -50,7 +50,7 @@ export interface ExecuteDbVerifyOptions<TFamilyId extends string, TTargetId exte
50
50
  readonly contract: Contract;
51
51
  readonly migrationsDir: string;
52
52
  readonly targetId: TTargetId;
53
- readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
53
+ readonly extensions: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
54
54
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
55
55
  readonly mode: 'strict' | 'lenient';
56
56
  readonly skipSchema: boolean;
@@ -149,7 +149,7 @@ function buildLoadInputs<TFamilyId extends string, TTargetId extends string>(
149
149
  targetId: options.targetId,
150
150
  migrationsDir: options.migrationsDir,
151
151
  appContract: options.contract,
152
- extensionPacks: options.extensionPacks,
152
+ extensions: options.extensions,
153
153
  deserializeContract: (json) => options.familyInstance.deserializeContract(json),
154
154
  };
155
155
  }
@@ -349,7 +349,7 @@ function mapMarkerCheckFailures(
349
349
  violations.push({
350
350
  kind: 'orphanMarker',
351
351
  spaceId: orphan.spaceId,
352
- remediation: `Add the corresponding extension to \`extensionPacks\` in \`prisma-next.config.ts\`, or delete the orphan marker row for "${orphan.spaceId}".`,
352
+ remediation: `Add the corresponding extension to \`extensions\` in \`prisma-next.config.ts\`, or delete the orphan marker row for "${orphan.spaceId}".`,
353
353
  });
354
354
  }
355
355
  if (violations.length === 0) return null;
@@ -359,7 +359,7 @@ function mapMarkerCheckFailures(
359
359
  ? 'Contract-space verifier found a violation'
360
360
  : `Contract-space verifier found violations (${violations.length})`;
361
361
  return new CliStructuredError('MIGRATION.CONTRACT_SPACE_VIOLATION', summary, {
362
- why: `The on-disk \`migrations/\` directory, the \`extensionPacks\` declaration, and the live database marker rows are not in agreement.\n${lines.join('\n')}`,
362
+ why: `The on-disk \`migrations/\` directory, the \`extensions\` declaration, and the live database marker rows are not in agreement.\n${lines.join('\n')}`,
363
363
  fix: violations[0]?.remediation ?? 'Review and reconcile the violations listed above.',
364
364
  docsUrl: 'https://pris.ly/contract-spaces',
365
365
  meta: { violations },
@@ -1,8 +1,9 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { EOL } from 'node:os';
3
3
  import { loadConfig } from '@prisma-next/config-loader';
4
- import { type FormatOptions, format, PslFormatError } from '@prisma-next/psl-parser/format';
4
+ import { type FormatOptions, format } from '@prisma-next/psl-parser/format';
5
5
  import { notOk, ok, type Result } from '@prisma-next/utils/result';
6
+ import { isStructuredError } from '@prisma-next/utils/structured-error';
6
7
  import { CliStructuredError, errorRuntime, errorUnexpected } from '../../utils/cli-errors';
7
8
 
8
9
  export interface FormatOperationOptions {
@@ -41,7 +42,7 @@ export async function executeFormat(
41
42
  }
42
43
 
43
44
  const source = config.contract?.source;
44
- if (source?.sourceFormat !== 'psl') {
45
+ if (source?.format !== 'psl') {
45
46
  return ok({ formatted: false });
46
47
  }
47
48
 
@@ -71,12 +72,12 @@ export async function executeFormat(
71
72
  try {
72
73
  formatted = format(contents, formatOptions);
73
74
  } catch (error) {
74
- if (error instanceof PslFormatError) {
75
+ if (isStructuredError(error) && error.code === 'PSL.PARSE_FAILED') {
75
76
  return notOk(
76
77
  errorRuntime('Cannot format PSL with parse errors', {
77
78
  why: error.message,
78
79
  fix: 'Fix the parse errors in your schema and try again.',
79
- meta: { diagnostics: error.diagnostics },
80
+ meta: { diagnostics: error.meta?.['diagnostics'] },
80
81
  }),
81
82
  );
82
83
  }
@@ -60,7 +60,7 @@ export interface ExecuteMigrateOptions<TFamilyId extends string, TTargetId exten
60
60
  >;
61
61
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
62
62
  readonly migrationsDir: string;
63
- readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
63
+ readonly extensions: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
64
64
  readonly targetId: TTargetId;
65
65
  /**
66
66
  * Optional app-space ref override. When provided, the app space's
@@ -122,7 +122,7 @@ export async function executeMigrate<TFamilyId extends string, TTargetId extends
122
122
  migrations,
123
123
  frameworkComponents,
124
124
  migrationsDir,
125
- extensionPacks,
125
+ extensions,
126
126
  targetId,
127
127
  refHash,
128
128
  refInvariants,
@@ -134,7 +134,7 @@ export async function executeMigrate<TFamilyId extends string, TTargetId extends
134
134
  targetId,
135
135
  migrationsDir,
136
136
  appContract: contract,
137
- extensionPacks,
137
+ extensions,
138
138
  deserializeContract: (json) => familyInstance.deserializeContract(json),
139
139
  };
140
140
  const loaded = await buildContractSpaceAggregate(loadInputs);
@@ -52,7 +52,7 @@ export interface ControlClientOptions {
52
52
  // biome-ignore lint/suspicious/noExplicitAny: required for contravariance in driver.create()
53
53
  readonly driver?: ControlDriverDescriptor<any, any, any, any>;
54
54
  // biome-ignore lint/suspicious/noExplicitAny: required for contravariance in extension.create()
55
- readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<any, any, any>>;
55
+ readonly extensions?: ReadonlyArray<ControlExtensionDescriptor<any, any, any>>;
56
56
  /**
57
57
  * Optional default connection for auto-connect.
58
58
  * When provided, operations will auto-connect if not already connected.
@@ -10,7 +10,7 @@ import {
10
10
  errorConfigFileNotFound,
11
11
  errorConfigValidation,
12
12
  errorContractConfigMissing,
13
- errorContractMissingExtensionPacks,
13
+ errorContractMissingExtensions,
14
14
  errorContractValidationFailed,
15
15
  errorDatabaseConnectionRequired,
16
16
  errorDriverRequired,
@@ -54,7 +54,7 @@ export {
54
54
  errorConfigFileNotFound,
55
55
  errorConfigValidation,
56
56
  errorContractConfigMissing,
57
- errorContractMissingExtensionPacks,
57
+ errorContractMissingExtensions,
58
58
  errorContractValidationFailed,
59
59
  errorDatabaseConnectionRequired,
60
60
  errorDriverRequired,
@@ -215,22 +215,30 @@ export function errorPlanForgotTheFlag(
215
215
  });
216
216
  }
217
217
 
218
+ /**
219
+ * `viaRef: true` (the default) mirrors migration-tools' `errorRefNotResolvable`:
220
+ * a ref name with no pointer file, where the fallback hash isn't a graph
221
+ * node either — there's nothing to materialize a contract from.
222
+ * `viaRef: false` is a distinct, ref-independent case: an explicit `--from
223
+ * <hash>` that doesn't name a ref, on an empty migration graph, so there is
224
+ * no graph node and no ref to resolve a contract through.
225
+ */
218
226
  export function errorSnapshotMissing(
219
227
  identifier: string,
220
228
  options?: { readonly viaRef?: boolean },
221
229
  ): CliStructuredError {
222
230
  const viaRef = options?.viaRef !== false;
223
231
  const fix = viaRef
224
- ? `Run "prisma-next db update --advance-ref ${identifier}" to repopulate the snapshot, or "prisma-next ref delete ${identifier}" to clear the orphan pointer.`
225
- : `No contract source exists for hash "${identifier}" on an empty migration graph. Use --from with a ref name that has a paired snapshot, or run db update first.`;
232
+ ? `Create the ref with "prisma-next ref set ${identifier} <hash>" (or advance it via "prisma-next db update --advance-ref ${identifier}"), or pass a hash that is a node in the migration graph.`
233
+ : `No contract source exists for hash "${identifier}" on an empty migration graph. Use --from with a ref name (its contract resolves through the snapshot store), or run db update first.`;
226
234
  return errorRuntime(
227
235
  viaRef
228
- ? `Ref "${identifier}" has no paired contract snapshot`
236
+ ? `Ref "${identifier}" is not resolvable`
229
237
  : `No contract source for from-hash "${identifier}"`,
230
238
  {
231
239
  why: viaRef
232
- ? `Ref "${identifier}" exists but its paired snapshot files are missing.`
233
- : `Hash "${identifier}" is not a graph node and no paired ref snapshot supplies a contract.`,
240
+ ? `Ref "${identifier}" has no pointer file, and the hash being resolved is not a node in the migration graph either.`
241
+ : `Hash "${identifier}" is not a node in the migration graph (the graph is empty), and it does not name a ref either.`,
234
242
  fix,
235
243
  meta: {
236
244
  code: 'MIGRATION.SNAPSHOT_MISSING',
@@ -1,6 +1,5 @@
1
1
  import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
2
2
  import { notOk, type Result } from '@prisma-next/utils/result';
3
- import { join } from 'pathe';
4
3
  import {
5
4
  CliStructuredError,
6
5
  errorContractValidationFailed,
@@ -16,7 +15,7 @@ export function mapContractAtError(
16
15
  ): Result<never, CliStructuredError> {
17
16
  if (MigrationToolsError.is(error)) {
18
17
  switch (error.code) {
19
- case 'MIGRATION.SNAPSHOT_MISSING': {
18
+ case 'MIGRATION.REF_NOT_RESOLVABLE': {
20
19
  const refName =
21
20
  typeof error.details?.['refName'] === 'string'
22
21
  ? error.details['refName']
@@ -27,18 +26,13 @@ export function mapContractAtError(
27
26
  }
28
27
  case 'MIGRATION.CONTRACT_DESERIALIZATION_FAILED': {
29
28
  const filePath =
30
- typeof error.details?.['filePath'] === 'string'
31
- ? error.details['filePath']
32
- : 'ref-snapshot';
29
+ typeof error.details?.['filePath'] === 'string' ? error.details['filePath'] : 'unknown';
33
30
  const message =
34
31
  typeof error.details?.['message'] === 'string' ? error.details['message'] : error.message;
35
- const isRefSnapshot = filePath.endsWith('.contract.json');
36
32
  return notOk(
37
33
  errorContractValidationFailed(
38
- isRefSnapshot
39
- ? `Ref snapshot contract failed to deserialize: ${message}`
40
- : `Predecessor contract at ${filePath} failed to deserialize: ${message}`,
41
- { where: { path: isRefSnapshot ? 'ref-snapshot' : filePath } },
34
+ `Predecessor contract at ${filePath} failed to deserialize: ${message}`,
35
+ { where: { path: filePath } },
42
36
  ),
43
37
  );
44
38
  }
@@ -66,22 +60,19 @@ export function mapContractAtError(
66
60
  fix: error.fix,
67
61
  }),
68
62
  );
69
- case 'MIGRATION.FILE_MISSING': {
70
- const file =
71
- typeof error.details?.['file'] === 'string' ? error.details['file'] : 'end-contract.json';
72
- const dir = typeof error.details?.['dir'] === 'string' ? error.details['dir'] : '';
73
- const jsonPath = dir ? join(dir, 'end-contract.json') : file;
63
+ case 'MIGRATION.CONTRACT_SNAPSHOT_MISSING': {
64
+ const expectedPath =
65
+ typeof error.details?.['expectedPath'] === 'string'
66
+ ? error.details['expectedPath']
67
+ : 'migrations/snapshots/';
74
68
  const role = options?.artifactRole ?? 'from';
75
69
  return notOk(
76
- errorFileNotFound(jsonPath, {
70
+ errorFileNotFound(expectedPath, {
77
71
  why:
78
72
  role === 'to'
79
- ? `Target migration is missing its destination contract snapshot at ${jsonPath}`
80
- : `Predecessor migration is missing its destination contract snapshot at ${jsonPath}`,
81
- fix:
82
- role === 'to'
83
- ? 'Re-emit the target migration so its sibling `end-contract.json` / `end-contract.d.ts` are restored, then re-run this command.'
84
- : '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.',
73
+ ? `Target migration is missing its contract snapshot at ${expectedPath}`
74
+ : `Predecessor migration is missing its contract snapshot at ${expectedPath}`,
75
+ fix: 'Restore migrations/snapshots/ from version control, or re-run the command that produced this migration to regenerate its snapshot.',
85
76
  }),
86
77
  );
87
78
  }
@@ -114,8 +114,8 @@ export function mapIntegrityViolations(
114
114
  ? 'Contract-space layout violation detected'
115
115
  : `Contract-space layout violations detected (${layout.length})`;
116
116
  return new CliStructuredError('MIGRATION.CONTRACT_SPACE_LAYOUT_VIOLATION', summary, {
117
- why: `The on-disk \`migrations/\` directory and your \`extensionPacks\` declaration are not in agreement.\n${lines.join('\n')}`,
118
- fix: 'Declare the extension in `extensionPacks` and re-emit its contract-space artefacts, or remove the orphan `migrations/<space>` directory.',
117
+ why: `The on-disk \`migrations/\` directory and your \`extensions\` declaration are not in agreement.\n${lines.join('\n')}`,
118
+ fix: 'Declare the extension in `extensions` and re-emit its contract-space artefacts, or remove the orphan `migrations/<space>` directory.',
119
119
  docsUrl: CONTRACT_SPACES_DOCS_URL,
120
120
  meta: { violations: layout },
121
121
  });
@@ -177,14 +177,14 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
177
177
  readonly targetId: TTargetId;
178
178
  readonly migrationsDir: string;
179
179
  readonly appContract: Contract;
180
- readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
180
+ readonly extensions: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
181
181
  readonly deserializeContract: (contractJson: unknown) => Contract;
182
182
  }
183
183
 
184
184
  function declaredExtensionsFromInputs(
185
- extensionPacks: BuildAggregateInputs<string, string>['extensionPacks'],
185
+ extensions: BuildAggregateInputs<string, string>['extensions'],
186
186
  ): readonly DeclaredExtensionEntry[] {
187
- return toDeclaredExtensionsFromRaw(extensionPacks as ReadonlyArray<unknown>);
187
+ return toDeclaredExtensionsFromRaw(extensions as ReadonlyArray<unknown>);
188
188
  }
189
189
 
190
190
  /**
@@ -195,7 +195,7 @@ export function refuseDeclaredExtensionTargetMismatch<
195
195
  TFamilyId extends string,
196
196
  TTargetId extends string,
197
197
  >(inputs: BuildAggregateInputs<TFamilyId, TTargetId>): CliStructuredError | null {
198
- for (const declared of declaredExtensionsFromInputs(inputs.extensionPacks)) {
198
+ for (const declared of declaredExtensionsFromInputs(inputs.extensions)) {
199
199
  if (declared.targetId !== inputs.targetId) {
200
200
  return targetMismatchError(declared.id, inputs.targetId, declared.targetId);
201
201
  }
@@ -271,7 +271,7 @@ export async function buildContractSpaceAggregate<
271
271
  >(
272
272
  inputs: BuildAggregateInputs<TFamilyId, TTargetId>,
273
273
  ): Promise<Result<ContractSpaceAggregate, CliStructuredError>> {
274
- const declaredExtensions = declaredExtensionsFromInputs(inputs.extensionPacks);
274
+ const declaredExtensions = declaredExtensionsFromInputs(inputs.extensions);
275
275
  const loaded = await loadContractSpaceAggregateForCli(inputs);
276
276
  if (!loaded.ok) {
277
277
  return loaded;
@@ -375,7 +375,7 @@ export async function buildReadAggregate(
375
375
  targetId: config.target.id,
376
376
  migrationsDir: options.migrationsDir,
377
377
  appContract: appContractForLoad,
378
- extensionPacks: config.extensionPacks ?? [],
378
+ extensions: config.extensions ?? [],
379
379
  deserializeContract,
380
380
  });
381
381
  if (!loaded.ok) {