@prisma-next/cli 0.8.0-dev.7 → 0.8.0-dev.8

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 (140) hide show
  1. package/README.md +7 -8
  2. package/dist/{cli-errors-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
  3. package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
  4. package/dist/cli.mjs +66 -18
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-4d26awB-.mjs → client-XkUw4xD0.mjs} +10 -9
  7. package/dist/client-XkUw4xD0.mjs.map +1 -0
  8. package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
  9. package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
  10. package/dist/commands/contract-emit.mjs +1 -1
  11. package/dist/commands/contract-infer.mjs +1 -1
  12. package/dist/commands/db-init.mjs +7 -7
  13. package/dist/commands/db-schema.mjs +5 -5
  14. package/dist/commands/db-sign.d.mts.map +1 -1
  15. package/dist/commands/db-sign.mjs +67 -25
  16. package/dist/commands/db-sign.mjs.map +1 -1
  17. package/dist/commands/db-update.d.mts.map +1 -1
  18. package/dist/commands/db-update.mjs +37 -9
  19. package/dist/commands/db-update.mjs.map +1 -1
  20. package/dist/commands/db-verify.mjs +1 -1
  21. package/dist/commands/migrate.d.mts +28 -0
  22. package/dist/commands/migrate.d.mts.map +1 -0
  23. package/dist/commands/{migration-apply.mjs → migrate.mjs} +54 -36
  24. package/dist/commands/migrate.mjs.map +1 -0
  25. package/dist/commands/migration-check.d.mts +18 -0
  26. package/dist/commands/migration-check.d.mts.map +1 -0
  27. package/dist/commands/migration-check.mjs +284 -0
  28. package/dist/commands/migration-check.mjs.map +1 -0
  29. package/dist/commands/migration-graph.d.mts +16 -0
  30. package/dist/commands/migration-graph.d.mts.map +1 -0
  31. package/dist/commands/migration-graph.mjs +141 -0
  32. package/dist/commands/migration-graph.mjs.map +1 -0
  33. package/dist/commands/migration-list.d.mts +20 -0
  34. package/dist/commands/migration-list.d.mts.map +1 -0
  35. package/dist/commands/migration-list.mjs +107 -0
  36. package/dist/commands/migration-list.mjs.map +1 -0
  37. package/dist/commands/migration-log.d.mts +21 -0
  38. package/dist/commands/migration-log.d.mts.map +1 -0
  39. package/dist/commands/migration-log.mjs +146 -0
  40. package/dist/commands/migration-log.mjs.map +1 -0
  41. package/dist/commands/migration-new.mjs +5 -5
  42. package/dist/commands/migration-plan.d.mts +2 -2
  43. package/dist/commands/migration-plan.d.mts.map +1 -1
  44. package/dist/commands/migration-plan.mjs +1 -1
  45. package/dist/commands/migration-show.d.mts +1 -1
  46. package/dist/commands/migration-show.d.mts.map +1 -1
  47. package/dist/commands/migration-show.mjs +85 -47
  48. package/dist/commands/migration-show.mjs.map +1 -1
  49. package/dist/commands/migration-status.d.mts +3 -15
  50. package/dist/commands/migration-status.d.mts.map +1 -1
  51. package/dist/commands/migration-status.mjs +732 -1
  52. package/dist/commands/migration-status.mjs.map +1 -0
  53. package/dist/commands/ref.d.mts +34 -0
  54. package/dist/commands/ref.d.mts.map +1 -0
  55. package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
  56. package/dist/commands/ref.mjs.map +1 -0
  57. package/dist/{contract-emit-DLc5GYbr.mjs → contract-emit-CgoFk9AU.mjs} +3 -3
  58. package/dist/{contract-emit-DLc5GYbr.mjs.map → contract-emit-CgoFk9AU.mjs.map} +1 -1
  59. package/dist/{contract-emit-BhKR-D9Y.mjs → contract-emit-GpxW5RLe.mjs} +6 -6
  60. package/dist/{contract-emit-BhKR-D9Y.mjs.map → contract-emit-GpxW5RLe.mjs.map} +1 -1
  61. package/dist/{contract-infer-Bnla2kuK.mjs → contract-infer-D8edZOCi.mjs} +5 -5
  62. package/dist/{contract-infer-Bnla2kuK.mjs.map → contract-infer-D8edZOCi.mjs.map} +1 -1
  63. package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-D68YpuPR.mjs} +3 -3
  64. package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-D68YpuPR.mjs.map} +1 -1
  65. package/dist/{db-verify-DitNxDiE.mjs → db-verify-DtRB9iHJ.mjs} +7 -7
  66. package/dist/{db-verify-DitNxDiE.mjs.map → db-verify-DtRB9iHJ.mjs.map} +1 -1
  67. package/dist/errors-Cw6kyTyV.mjs +56 -0
  68. package/dist/errors-Cw6kyTyV.mjs.map +1 -0
  69. package/dist/exports/control-api.d.mts +1 -1
  70. package/dist/exports/control-api.mjs +2 -2
  71. package/dist/exports/index.mjs +1 -1
  72. package/dist/exports/init-output.mjs +1 -1
  73. package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
  74. package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
  75. package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
  76. package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
  77. package/dist/{migration-status-Do4Ei0i_.mjs → graph-render-eJDcLWny.mjs} +3 -692
  78. package/dist/graph-render-eJDcLWny.mjs.map +1 -0
  79. package/dist/{init-CcDCJMLk.mjs → init-e5Q4s1_5.mjs} +7 -6
  80. package/dist/{init-CcDCJMLk.mjs.map → init-e5Q4s1_5.mjs.map} +1 -1
  81. package/dist/{inspect-live-schema-CyzAzPzF.mjs → inspect-live-schema-CPPqCips.mjs} +4 -4
  82. package/dist/{inspect-live-schema-CyzAzPzF.mjs.map → inspect-live-schema-CPPqCips.mjs.map} +1 -1
  83. package/dist/migration-cli.mjs +1 -1
  84. package/dist/migration-cli.mjs.map +1 -1
  85. package/dist/{migration-command-scaffold-Jp1rosw8.mjs → migration-command-scaffold-B_ezTTwX.mjs} +4 -4
  86. package/dist/{migration-command-scaffold-Jp1rosw8.mjs.map → migration-command-scaffold-B_ezTTwX.mjs.map} +1 -1
  87. package/dist/{migration-plan-DTwYi61q.mjs → migration-plan-DWB-NTxH.mjs} +26 -24
  88. package/dist/migration-plan-DWB-NTxH.mjs.map +1 -0
  89. package/dist/migration-types-D2FW63pr.d.mts +15 -0
  90. package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
  91. package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
  92. package/dist/migrations-DyUf5lTt.mjs.map +1 -0
  93. package/dist/{output-DEg3SSnJ.mjs → output-B60Gw5fu.mjs} +1 -1
  94. package/dist/{output-DEg3SSnJ.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
  95. package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
  96. package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
  97. package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
  98. package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
  99. package/dist/{types-LItU7E4l.d.mts → types-BS_wpjAY.d.mts} +2 -2
  100. package/dist/{types-LItU7E4l.d.mts.map → types-BS_wpjAY.d.mts.map} +1 -1
  101. package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
  102. package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
  103. package/package.json +39 -23
  104. package/src/cli.ts +78 -15
  105. package/src/commands/db-sign.ts +102 -32
  106. package/src/commands/db-update.ts +56 -4
  107. package/src/commands/{migration-apply.ts → migrate.ts} +54 -70
  108. package/src/commands/migration-check/exit-codes.ts +3 -0
  109. package/src/commands/migration-check.ts +369 -0
  110. package/src/commands/migration-graph.ts +184 -0
  111. package/src/commands/migration-list.ts +155 -0
  112. package/src/commands/migration-log.ts +218 -0
  113. package/src/commands/migration-plan.ts +29 -22
  114. package/src/commands/migration-show.ts +132 -60
  115. package/src/commands/migration-status.ts +77 -64
  116. package/src/commands/{migration-ref.ts → ref.ts} +32 -86
  117. package/src/control-api/operations/apply-aggregate.ts +4 -4
  118. package/src/control-api/operations/db-apply-aggregate.ts +3 -2
  119. package/src/control-api/operations/migration-apply.ts +4 -3
  120. package/src/migration-cli.ts +1 -1
  121. package/src/utils/cli-errors.ts +37 -0
  122. package/src/utils/command-helpers.ts +28 -3
  123. package/src/utils/contract-space-aggregate-loader.ts +2 -2
  124. package/src/utils/contract-space-seed-phase.ts +1 -1
  125. package/src/utils/formatters/help.ts +12 -2
  126. package/src/utils/formatters/migrations.ts +2 -2
  127. package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
  128. package/dist/client-4d26awB-.mjs.map +0 -1
  129. package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
  130. package/dist/commands/migration-apply.d.mts +0 -51
  131. package/dist/commands/migration-apply.d.mts.map +0 -1
  132. package/dist/commands/migration-apply.mjs.map +0 -1
  133. package/dist/commands/migration-ref.d.mts +0 -45
  134. package/dist/commands/migration-ref.d.mts.map +0 -1
  135. package/dist/commands/migration-ref.mjs.map +0 -1
  136. package/dist/migration-plan-DTwYi61q.mjs.map +0 -1
  137. package/dist/migration-status-Do4Ei0i_.mjs.map +0 -1
  138. package/dist/migrations-CTsyBXCA.mjs.map +0 -1
  139. package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
  140. /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
@@ -1,8 +1,8 @@
1
1
  import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
2
+ import { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';
2
3
  import type { RefEntry } from '@prisma-next/migration-tools/refs';
3
4
  import {
4
5
  deleteRef,
5
- readRef,
6
6
  readRefs,
7
7
  validateRefName,
8
8
  validateRefValue,
@@ -16,9 +16,11 @@ import {
16
16
  errorRuntime,
17
17
  errorUnexpected,
18
18
  mapMigrationToolsError,
19
+ mapRefResolutionError,
19
20
  } from '../utils/cli-errors';
20
21
  import {
21
22
  addGlobalOptions,
23
+ loadMigrationPackages,
22
24
  resolveMigrationPaths,
23
25
  setCommandDescriptions,
24
26
  } from '../utils/command-helpers';
@@ -34,13 +36,6 @@ interface RefSetResult {
34
36
  readonly invariants: readonly string[];
35
37
  }
36
38
 
37
- interface RefGetResult {
38
- readonly ok: true;
39
- readonly ref: string;
40
- readonly hash: string;
41
- readonly invariants: readonly string[];
42
- }
43
-
44
39
  interface RefDeleteResult {
45
40
  readonly ok: true;
46
41
  readonly ref: string;
@@ -66,53 +61,42 @@ function cliErrorInvalidRefName(name: string): CliStructuredError {
66
61
  });
67
62
  }
68
63
 
69
- function cliErrorInvalidRefValue(hash: string): CliStructuredError {
70
- return errorRuntime(`Invalid contract hash "${hash}"`, {
71
- why: `"${hash}" is not a valid contract hash`,
72
- fix: 'Contract hashes must match the format "sha256:<64 hex chars>". Copy the hash from `prisma-next contract emit` or `migration status --json`.',
73
- });
74
- }
75
-
76
- async function executeRefSetCommand(
64
+ export async function executeRefSetCommand(
77
65
  name: string,
78
- hash: string,
66
+ contractInput: string,
79
67
  options: { config?: string },
80
68
  ): Promise<Result<RefSetResult, CliStructuredError>> {
81
69
  if (!validateRefName(name)) {
82
70
  return notOk(cliErrorInvalidRefName(name));
83
71
  }
84
- if (!validateRefValue(hash)) {
85
- return notOk(cliErrorInvalidRefValue(hash));
86
- }
87
72
 
88
73
  try {
89
74
  const config = await loadConfig(options.config);
90
- const { refsDir } = resolveMigrationPaths(options.config, config);
91
- const entry: RefEntry = { hash, invariants: [] };
75
+ const { appMigrationsDir, refsDir } = resolveMigrationPaths(options.config, config);
76
+
77
+ let resolvedHash: string;
78
+ if (validateRefValue(contractInput)) {
79
+ resolvedHash = contractInput;
80
+ } else {
81
+ const { graph } = await loadMigrationPackages(appMigrationsDir);
82
+ const refs = await readRefs(refsDir);
83
+ const refResult = parseContractRef(contractInput, { graph, refs });
84
+ if (!refResult.ok) {
85
+ return notOk(mapRefResolutionError(refResult.failure));
86
+ }
87
+ resolvedHash = refResult.value.hash;
88
+ }
89
+
90
+ const entry: RefEntry = { hash: resolvedHash, invariants: [] };
92
91
  await writeRef(refsDir, name, entry);
93
- return ok({ ok: true as const, ref: name, hash, invariants: [] });
94
- } catch (error) {
95
- if (error instanceof CliStructuredError) return notOk(error);
96
- return notOk(mapError(error));
97
- }
98
- }
99
-
100
- async function executeRefGetCommand(
101
- name: string,
102
- options: { config?: string },
103
- ): Promise<Result<RefGetResult, CliStructuredError>> {
104
- try {
105
- const config = await loadConfig(options.config);
106
- const { refsDir } = resolveMigrationPaths(options.config, config);
107
- const entry = await readRef(refsDir, name);
108
- return ok({ ok: true as const, ref: name, hash: entry.hash, invariants: entry.invariants });
92
+ return ok({ ok: true as const, ref: name, hash: resolvedHash, invariants: [] });
109
93
  } catch (error) {
110
94
  if (error instanceof CliStructuredError) return notOk(error);
111
95
  return notOk(mapError(error));
112
96
  }
113
97
  }
114
98
 
115
- async function executeRefDeleteCommand(
99
+ export async function executeRefDeleteCommand(
116
100
  name: string,
117
101
  options: { config?: string },
118
102
  ): Promise<Result<RefDeleteResult, CliStructuredError>> {
@@ -127,7 +111,7 @@ async function executeRefDeleteCommand(
127
111
  }
128
112
  }
129
113
 
130
- async function executeRefListCommand(options: {
114
+ export async function executeRefListCommand(options: {
131
115
  config?: string;
132
116
  }): Promise<Result<RefListResult, CliStructuredError>> {
133
117
  try {
@@ -145,12 +129,15 @@ function createRefSetCommand(): Command {
145
129
  const command = new Command('set');
146
130
  setCommandDescriptions(
147
131
  command,
148
- 'Set a ref to a contract hash',
149
- 'Sets a named ref to point to a contract hash in migrations/refs/.',
132
+ 'Set a ref to a contract reference',
133
+ 'Sets a named ref to point to a resolved contract reference (hash, alias, or path) in migrations/refs/.',
150
134
  );
151
135
  addGlobalOptions(command)
152
136
  .argument('<name>', 'Ref name (e.g., staging, production)')
153
- .argument('<hash>', 'Contract hash to point to')
137
+ .argument(
138
+ '<contract>',
139
+ 'Contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',
140
+ )
154
141
  .option('--config <path>', 'Path to prisma-next.config.ts')
155
142
  .action(
156
143
  async (
@@ -174,37 +161,6 @@ function createRefSetCommand(): Command {
174
161
  return command;
175
162
  }
176
163
 
177
- function createRefGetCommand(): Command {
178
- const command = new Command('get');
179
- setCommandDescriptions(
180
- command,
181
- 'Get the hash for a ref',
182
- 'Reads a named ref from migrations/refs/ and prints its contract hash.',
183
- );
184
- addGlobalOptions(command)
185
- .argument('<name>', 'Ref name to look up')
186
- .option('--config <path>', 'Path to prisma-next.config.ts')
187
- .action(
188
- async (
189
- name: string,
190
- options: { config?: string; json?: string | boolean; quiet?: boolean },
191
- ) => {
192
- const flags = parseGlobalFlags(options);
193
- const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
194
- const result = await executeRefGetCommand(name, options);
195
- const exitCode = handleResult(result, flags, ui, (value) => {
196
- if (flags.json) {
197
- ui.output(JSON.stringify(value));
198
- } else {
199
- ui.output(value.hash);
200
- }
201
- });
202
- process.exit(exitCode);
203
- },
204
- );
205
- return command;
206
- }
207
-
208
164
  function createRefDeleteCommand(): Command {
209
165
  const command = new Command('delete');
210
166
  setCommandDescriptions(command, 'Delete a ref', 'Removes a named ref from migrations/refs/.');
@@ -262,20 +218,11 @@ function createRefListCommand(): Command {
262
218
  return command;
263
219
  }
264
220
 
265
- export {
266
- cliErrorInvalidRefName,
267
- cliErrorInvalidRefValue,
268
- executeRefDeleteCommand,
269
- executeRefGetCommand,
270
- executeRefListCommand,
271
- executeRefSetCommand,
272
- };
273
-
274
- export function createMigrationRefCommand(): Command {
221
+ export function createRefCommand(): Command {
275
222
  const command = new Command('ref');
276
223
  setCommandDescriptions(
277
224
  command,
278
- 'Manage migration refs',
225
+ 'Manage contract refs',
279
226
  'Manage named refs in migrations/refs/. Refs map logical environment\n' +
280
227
  'names (e.g., staging, production) to contract hashes.',
281
228
  );
@@ -284,7 +231,6 @@ export function createMigrationRefCommand(): Command {
284
231
  subcommandDescription: () => '',
285
232
  });
286
233
  command.addCommand(createRefSetCommand());
287
- command.addCommand(createRefGetCommand());
288
234
  command.addCommand(createRefDeleteCommand());
289
235
  command.addCommand(createRefListCommand());
290
236
  return command;
@@ -49,7 +49,7 @@ export interface ApplyAggregateInputs<TFamilyId extends string, TTargetId extend
49
49
  * Per-space plans, keyed by `spaceId`. Produced by either the full
50
50
  * {@link planAggregate} pipeline (`db init` / `db update` — synth
51
51
  * for the app, graph-walk for extensions) or by direct
52
- * {@link graphWalkStrategy} calls (`migration apply` — graph-walk
52
+ * {@link graphWalkStrategy} calls (`migrate` — graph-walk
53
53
  * for every member). Either way, the runner consumes the same shape.
54
54
  */
55
55
  readonly perSpacePlans: ReadonlyMap<string, AggregatePerSpacePlan>;
@@ -100,7 +100,7 @@ export type ApplyAggregateResult = Result<ApplyAggregateValue, AggregateApplyRun
100
100
 
101
101
  /**
102
102
  * Runner-driving tail shared by every aggregate apply caller — `db init`,
103
- * `db update`, and `migration apply`. Consumes already-resolved per-space
103
+ * `db update`, and `migrate`. Consumes already-resolved per-space
104
104
  * plans (the planner-vs-replay distinction is owned by the caller) and
105
105
  * dispatches them to the multi-space runner in canonical order.
106
106
  *
@@ -264,7 +264,7 @@ export function collectOrdered(
264
264
  /**
265
265
  * Action-appropriate label for the `spanStart` event the apply
266
266
  * primitive emits. `applyAggregate` is shared by `db init`, `db update`,
267
- * and `migration apply`; the span label tracks the user-visible action
267
+ * and `migrate`; the span label tracks the user-visible action
268
268
  * so structured-progress output reads naturally for each surface.
269
269
  */
270
270
  export function progressLabelForAction(action: AggregateApplyAction): string {
@@ -285,6 +285,6 @@ function labelForAction(action: AggregateApplyAction): string {
285
285
  case 'dbUpdate':
286
286
  return 'db update';
287
287
  case 'migrationApply':
288
- return 'migration apply';
288
+ return 'migrate';
289
289
  }
290
290
  }
@@ -207,9 +207,10 @@ export async function executeAggregateApply<TFamilyId extends string, TTargetId
207
207
 
208
208
  // 5. Apply mode: hand off to the shared `applyAggregate` primitive.
209
209
  // The runner-driving tail is identical for `db init` / `db update` /
210
- // `migration apply` — only how each caller produces `perSpacePlans`
210
+ // `migrate` — only how each caller produces `perSpacePlans`
211
211
  // differs (synth + graph-walk via planAggregate here; graph-walk
212
- // only for migration apply). See M6 sub-spec § Required changes 1.
212
+ // only for migrate). Each caller produces perSpacePlans differently;
213
+ // this helper handles the shared apply tail.
213
214
  const applied = await applyAggregate({
214
215
  aggregate,
215
216
  perSpacePlans: planResult.value.perSpace,
@@ -34,7 +34,7 @@ import type {
34
34
  import { applyAggregate, buildPerSpaceBreakdown } from './apply-aggregate';
35
35
 
36
36
  /**
37
- * Inputs for the aggregate-walking `migration apply` control-api
37
+ * Inputs for the aggregate-walking `migrate` control-api
38
38
  * operation.
39
39
  *
40
40
  * The CLI command resolves the descriptor surface (config, refs,
@@ -110,7 +110,8 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
110
110
  * shared with `db init` / `db update`). Marker advancement is
111
111
  * inside the per-space transaction.
112
112
  *
113
- * Sub-spec § `migration apply` semantics + § Required changes 1.
113
+ * Encodes the replay-only contract: every contract space must have an
114
+ * authored migration graph on disk before this operation can advance it.
114
115
  */
115
116
  export async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(
116
117
  options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,
@@ -461,7 +462,7 @@ function buildNeverPlannedFailure(spaceId: string, targetHash: string): Migratio
461
462
  return {
462
463
  code: 'MIGRATION_PATH_NOT_FOUND',
463
464
  summary: `No on-disk migrations for contract space "${spaceId}"`,
464
- why: `migration apply is replay-only: every contract space must have an authored migration graph on disk. Space "${spaceId}" has no migrations under \`migrations/${spaceId}/\` but its head ref targets "${targetHash}". Run \`prisma-next migration plan\` first to materialise the path.`,
465
+ why: `migrate is replay-only: every contract space must have an authored migration graph on disk. Space "${spaceId}" has no migrations under \`migrations/${spaceId}/\` but its head ref targets "${targetHash}". Run \`prisma-next migration plan\` first to materialise the path.`,
465
466
  meta: { spaceId, target: targetHash, kind: 'neverPlanned' },
466
467
  };
467
468
  }
@@ -3,7 +3,7 @@
3
3
  * `node migration.ts` directly.
4
4
  *
5
5
  * Naming: this is *not* a "migration runner" in the apply-time sense. The
6
- * apply-time runner is the thing `prisma-next migration apply` uses to
6
+ * apply-time runner is the thing `prisma-next migrate` uses to
7
7
  * execute migration JSON ops against a database. `MigrationCLI` is the
8
8
  * tiny CLI surface owned by an authored `migration.ts` file: parse the
9
9
  * file's argv, load the project's `prisma-next.config.ts`, assemble a
@@ -25,6 +25,7 @@ import {
25
25
  } from '@prisma-next/errors/control';
26
26
  import { errorRuntime } from '@prisma-next/errors/execution';
27
27
  import type { MigrationToolsError } from '@prisma-next/migration-tools/errors';
28
+ import type { RefResolutionError } from '@prisma-next/migration-tools/ref-resolution';
28
29
 
29
30
  export {
30
31
  ERROR_CODE_DESTRUCTIVE_CHANGES,
@@ -85,3 +86,39 @@ export function mapMigrationToolsError(error: MigrationToolsError): CliStructure
85
86
  meta: { code: error.code, ...(error.details ?? {}) },
86
87
  });
87
88
  }
89
+
90
+ /**
91
+ * Maps a `RefResolutionError` from the contract/migration reference
92
+ * resolver into a CLI structured error envelope.
93
+ */
94
+ export function mapRefResolutionError(error: RefResolutionError): CliStructuredError {
95
+ switch (error.kind) {
96
+ case 'not-found':
97
+ return errorRuntime(`Not a known ${error.grammar} reference: "${error.input}"`, {
98
+ why: `No ${error.grammar} matching "${error.input}" exists in the migration graph or refs index.`,
99
+ fix:
100
+ error.grammar === 'contract'
101
+ ? 'Provide a valid contract hash, ref name, or migration directory name.'
102
+ : 'Provide a valid migration directory name or migration hash.',
103
+ meta: { input: error.input, grammar: error.grammar },
104
+ });
105
+ case 'ambiguous':
106
+ return errorRuntime(`Ambiguous ${error.grammar} reference: "${error.input}"`, {
107
+ why: `"${error.input}" matches multiple ${error.grammar}s: ${error.candidates.join(', ')}`,
108
+ fix: 'Provide a longer prefix or use the full hash to disambiguate.',
109
+ meta: { input: error.input, candidates: error.candidates, grammar: error.grammar },
110
+ });
111
+ case 'wrong-grammar':
112
+ return errorRuntime(error.message, {
113
+ why: error.message,
114
+ fix: error.fix,
115
+ meta: { input: error.input, expectedGrammar: error.expectedGrammar },
116
+ });
117
+ case 'invalid-format':
118
+ return errorRuntime(`Invalid reference format: "${error.input}"`, {
119
+ why: error.reason,
120
+ fix: 'Provide a valid contract hash, ref name, or migration directory name.',
121
+ meta: { input: error.input },
122
+ });
123
+ }
124
+ }
@@ -17,6 +17,10 @@ import { parseGlobalFlags } from './global-flags';
17
17
 
18
18
  const longDescriptions = new WeakMap<Command, string>();
19
19
  const commandExamples = new WeakMap<Command, readonly string[]>();
20
+ const commandSeeAlso = new WeakMap<
21
+ Command,
22
+ readonly { readonly verb: string; readonly oneLiner: string }[]
23
+ >();
20
24
 
21
25
  /**
22
26
  * Sets both short and long descriptions for a command.
@@ -57,6 +61,27 @@ export function getCommandExamples(command: Command): readonly string[] | undefi
57
61
  return commandExamples.get(command);
58
62
  }
59
63
 
64
+ /**
65
+ * Sets cross-references to related commands, rendered in a "See also"
66
+ * section below the Examples block in help output.
67
+ */
68
+ export function setCommandSeeAlso(
69
+ command: Command,
70
+ refs: readonly { readonly verb: string; readonly oneLiner: string }[],
71
+ ): Command {
72
+ commandSeeAlso.set(command, refs);
73
+ return command;
74
+ }
75
+
76
+ /**
77
+ * Gets the see-also cross-references from a command.
78
+ */
79
+ export function getCommandSeeAlso(
80
+ command: Command,
81
+ ): readonly { readonly verb: string; readonly oneLiner: string }[] | undefined {
82
+ return commandSeeAlso.get(command);
83
+ }
84
+
60
85
  /**
61
86
  * Shared CLI options interface for migration commands (db init, db update).
62
87
  * These are the Commander.js parsed options common to both commands.
@@ -79,13 +104,13 @@ export function resolveContractPath(config: { contract?: { output?: string } }):
79
104
 
80
105
  /**
81
106
  * Resolves the migrations directory and config path from CLI options.
82
- * Shared by migration-apply, migration-plan, and migration-status.
107
+ * Shared by migrate, migration-plan, and migration-status.
83
108
  *
84
109
  * - `migrationsDir` is the project's top-level `migrations/` directory
85
110
  * (the root that the aggregate loader walks for every contract space).
86
111
  * - `appMigrationsDir` is the app subspace directory under it
87
112
  * (`<migrationsDir>/<APP_SPACE_ID>/`). Every per-app reader / writer
88
- * (`migration new`, `migration plan`, `migration apply`,
113
+ * (`migration new`, `migration plan`, `migrate`,
89
114
  * `migration status`, `migration show`, `migration ref`) operates on
90
115
  * this directory. Extensions own their own `migrations/<spaceId>/`.
91
116
  * - `refsDir` is the app's refs directory (`<appMigrationsDir>/refs/`).
@@ -159,7 +184,7 @@ export function collectDeclaredInvariants(graph: MigrationGraph): ReadonlySet<st
159
184
  /**
160
185
  * Maps a `MigrationEdge` to the structural-edge shape used in the
161
186
  * `MIGRATION.NO_INVARIANT_PATH` error envelope. Shared between
162
- * `migration apply` and `migration status` so both commands surface
187
+ * `migrate` and `migration status` so both commands surface
163
188
  * the same JSON wire shape when an invariant-aware route is unsatisfiable.
164
189
  */
165
190
  export function toStructuralEdge(edge: MigrationEdge): NoInvariantPathStructuralEdge {
@@ -128,7 +128,7 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
128
128
  * `migrations/` graph is not walked — the planner uses the synth
129
129
  * strategy for the app member instead).
130
130
  *
131
- * `migration apply` callers thread the user's authored app-space
131
+ * `migrate` callers thread the user's authored app-space
132
132
  * packages (loaded via `loadMigrationPackages(appMigrationsDir)`)
133
133
  * through here so the graph-walk strategy can plot a path through
134
134
  * them — the prod-time replay path explicitly forbids synth.
@@ -144,7 +144,7 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
144
144
  * (defaulting to `[]`). `db init` / `db update` leave it empty: the
145
145
  * planner's `synth` strategy is used for the app member (driven by
146
146
  * `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`
147
- * graph does not need to be walked. `migration apply` threads the
147
+ * graph does not need to be walked. `migrate` threads the
148
148
  * already-loaded app-space packages through so the graph-walk strategy
149
149
  * can plot a path through them — replay forbids synth.
150
150
  *
@@ -91,7 +91,7 @@ export interface ContractSpaceSeedPhaseResult {
91
91
  * Output ordering is deterministic and alphabetical by spaceId (via
92
92
  * {@link planAllSpaces}, which also detects duplicate spaceIds). This
93
93
  * matches the canonical sort order used by every other aggregate
94
- * surface (`migration apply`, `migration status`, the runner).
94
+ * surface (`migrate`, `migration status`, the runner).
95
95
  */
96
96
  export async function runContractSpaceSeedPhase(
97
97
  inputs: ContractSpaceSeedPhaseInputs,
@@ -2,7 +2,7 @@ import { blue, bold, cyan, dim, green, magenta } from 'colorette';
2
2
  import type { Command } from 'commander';
3
3
  import wrapAnsi from 'wrap-ansi';
4
4
 
5
- import { getCommandExamples, getLongDescription } from '../command-helpers';
5
+ import { getCommandExamples, getCommandSeeAlso, getLongDescription } from '../command-helpers';
6
6
  import type { GlobalFlags } from '../global-flags';
7
7
  import { formatDim } from './helpers';
8
8
  import { padToFixedWidth, renderCommandTree } from './styled';
@@ -134,7 +134,7 @@ function getCommandDocsUrl(commandPath: string): string | undefined {
134
134
  'db verify': 'https://pris.ly/db-verify',
135
135
  'db update': 'https://pris.ly/db-update',
136
136
  'migration plan': 'https://pris.ly/migration-plan',
137
- 'migration apply': 'https://pris.ly/migration-apply',
137
+ migrate: 'https://pris.ly/migrate',
138
138
  'migration show': 'https://pris.ly/migration-show',
139
139
  'migration status': 'https://pris.ly/migration-status',
140
140
  };
@@ -268,6 +268,16 @@ export function formatCommandHelp(options: {
268
268
  }
269
269
  }
270
270
 
271
+ // See also (cross-references to related commands)
272
+ const seeAlso = getCommandSeeAlso(command);
273
+ if (seeAlso && seeAlso.length > 0) {
274
+ lines.push(formatDimText('│'));
275
+ lines.push(`${formatDimText('│')} ${formatDimText('See also:')}`);
276
+ for (const ref of seeAlso) {
277
+ lines.push(`${formatDimText('│')} ${ref.verb} ${formatDimText(ref.oneLiner)}`);
278
+ }
279
+ }
280
+
271
281
  // Multi-line description (if present) - shown after all other content
272
282
  if (longDescription) {
273
283
  lines.push(formatDimText('│'));
@@ -90,7 +90,7 @@ export interface MigrationCommandResult {
90
90
 
91
91
  /**
92
92
  * Render the shared per-space execution block consumed by the `db init`
93
- * / `db update` / `migration apply` summaries. Always shows: space
93
+ * / `db update` / `migrate` summaries. Always shows: space
94
94
  * label (`Extension space: <id>` or `App space`) → per-op lines under
95
95
  * each space → per-space marker hash (when known).
96
96
  *
@@ -254,7 +254,7 @@ export interface MigrationApplyCommandOutputResult {
254
254
  /**
255
255
  * Per-space breakdown in canonical schedule order (extensions
256
256
  * alphabetically, then app). Always present for the aggregate-walking
257
- * `migration apply` command.
257
+ * `migrate` command.
258
258
  */
259
259
  readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];
260
260
  readonly timings?: {
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-errors-D3_sMh2K.mjs","names":[],"sources":["../src/utils/cli-errors.ts"],"sourcesContent":["/**\n * Re-export all domain error factories from @prisma-next/errors for convenience.\n * CLI-specific errors (e.g., Commander argument validation in the main CLI, or\n * clipanion parse errors in the migration-file CLI) can be added here if needed.\n */\nexport type { CliErrorConflict, CliErrorEnvelope } from '@prisma-next/errors/control';\n\nimport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport type { MigrationToolsError } from '@prisma-next/migration-tools/errors';\n\nexport {\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorDestructiveChanges,\n errorHashMismatch,\n errorMarkerMissing,\n errorMarkerRequired,\n errorRunnerFailed,\n errorRuntime,\n errorSchemaVerificationFailed,\n errorTargetMismatch,\n} from '@prisma-next/errors/execution';\nexport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n errorUnfilledPlaceholder,\n placeholder,\n} from '@prisma-next/errors/migration';\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\n\n/**\n * Maps a `MigrationToolsError` raised by the migration-tools loader/graph\n * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,\n * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.\n *\n * The full `error.details` payload is forwarded into `meta` so machine\n * consumers (`--json`) see structural fields like `dir`, `storedHash`,\n * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable\n * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.\n *\n * Callers are expected to gate on `MigrationToolsError.is(error)` first\n * (mirroring the original inline pattern); non-`MigrationToolsError`\n * values are caller-classified (rethrow, wrap with command-specific\n * `errorUnexpected`, etc.).\n */\nexport function mapMigrationToolsError(error: MigrationToolsError): CliStructuredError {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,uBAAuB,OAAgD;CACrF,OAAO,aAAa,MAAM,SAAS;EACjC,KAAK,MAAM;EACX,KAAK,MAAM;EACX,MAAM;GAAE,MAAM,MAAM;GAAM,GAAI,MAAM,WAAW,EAAE;GAAG;EACrD,CAAC"}