@prisma-next/cli 0.8.0 → 0.9.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/{cli-errors-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
- package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
- package/dist/cli.mjs +67 -19
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-BCnP7cHo.mjs → client-Brv4qlfB.mjs} +28 -30
- package/dist/client-Brv4qlfB.mjs.map +1 -0
- package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
- package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +7 -7
- package/dist/commands/db-schema.mjs +5 -5
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +67 -25
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +37 -9
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +28 -0
- package/dist/commands/migrate.d.mts.map +1 -0
- package/dist/commands/{migration-apply.mjs → migrate.mjs} +65 -39
- package/dist/commands/migrate.mjs.map +1 -0
- package/dist/commands/migration-check.d.mts +18 -0
- package/dist/commands/migration-check.d.mts.map +1 -0
- package/dist/commands/migration-check.mjs +284 -0
- package/dist/commands/migration-check.mjs.map +1 -0
- package/dist/commands/migration-graph.d.mts +16 -0
- package/dist/commands/migration-graph.d.mts.map +1 -0
- package/dist/commands/migration-graph.mjs +141 -0
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +20 -0
- package/dist/commands/migration-list.d.mts.map +1 -0
- package/dist/commands/migration-list.mjs +107 -0
- package/dist/commands/migration-list.mjs.map +1 -0
- package/dist/commands/migration-log.d.mts +21 -0
- package/dist/commands/migration-log.d.mts.map +1 -0
- package/dist/commands/migration-log.mjs +146 -0
- package/dist/commands/migration-log.mjs.map +1 -0
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +30 -29
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +2 -2
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +90 -52
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +5 -17
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +732 -1
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/ref.d.mts +34 -0
- package/dist/commands/ref.d.mts.map +1 -0
- package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
- package/dist/commands/ref.mjs.map +1 -0
- package/dist/{contract-emit-9DBda5Ou.mjs → contract-emit-C3STUIBg.mjs} +6 -6
- package/dist/{contract-emit-9DBda5Ou.mjs.map → contract-emit-C3STUIBg.mjs.map} +1 -1
- package/dist/{contract-emit-B77TsJqf.mjs → contract-emit-iynA3BCA.mjs} +9 -5
- package/dist/contract-emit-iynA3BCA.mjs.map +1 -0
- package/dist/{contract-infer-ByxhPjpW.mjs → contract-infer-Cnj8G1E2.mjs} +5 -5
- package/dist/{contract-infer-ByxhPjpW.mjs.map → contract-infer-Cnj8G1E2.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-pAc8CDfY.mjs} +4 -4
- package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-pAc8CDfY.mjs.map} +1 -1
- package/dist/{db-verify-Czm5T-J4.mjs → db-verify-D7cyH_zz.mjs} +12 -9
- package/dist/db-verify-D7cyH_zz.mjs.map +1 -0
- package/dist/errors-Cw6kyTyV.mjs +56 -0
- package/dist/errors-Cw6kyTyV.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
- package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
- package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
- package/dist/{migration-status-By9G5p2H.mjs → graph-render-eJDcLWny.mjs} +3 -692
- package/dist/graph-render-eJDcLWny.mjs.map +1 -0
- package/dist/{init-B-k3a1Qw.mjs → init-Bqg5JWg7.mjs} +133 -61
- package/dist/init-Bqg5JWg7.mjs.map +1 -0
- package/dist/{inspect-live-schema-DxdBd4Er.mjs → inspect-live-schema-CWLK_lgs.mjs} +4 -4
- package/dist/{inspect-live-schema-DxdBd4Er.mjs.map → inspect-live-schema-CWLK_lgs.mjs.map} +1 -1
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs → migration-command-scaffold-CmXXC1UZ.mjs} +4 -4
- package/dist/{migration-command-scaffold-BdV8JYXV.mjs.map → migration-command-scaffold-CmXXC1UZ.mjs.map} +1 -1
- package/dist/{migration-plan-mRu5K81L.mjs → migration-plan-CHyUlBV0.mjs} +76 -37
- package/dist/migration-plan-CHyUlBV0.mjs.map +1 -0
- package/dist/migration-types-D2FW63pr.d.mts +15 -0
- package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
- package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
- package/dist/migrations-DyUf5lTt.mjs.map +1 -0
- package/dist/{output-BVj6a971.mjs → output-B60Gw5fu.mjs} +12 -11
- package/dist/{output-BVj6a971.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
- package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
- package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
- package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
- package/dist/{types-LItU7E4l.d.mts → types-0aS865QN.d.mts} +14 -8
- package/dist/types-0aS865QN.d.mts.map +1 -0
- package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
- package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
- package/package.json +39 -23
- package/src/cli.ts +78 -15
- package/src/commands/db-sign.ts +102 -32
- package/src/commands/db-update.ts +56 -4
- package/src/commands/db-verify.ts +19 -3
- package/src/commands/init/agent-skill-install.ts +145 -43
- package/src/commands/init/errors.ts +2 -2
- package/src/commands/init/exit-codes.ts +2 -2
- package/src/commands/init/index.ts +1 -1
- package/src/commands/init/init.ts +15 -6
- package/src/commands/init/inputs.ts +1 -1
- package/src/commands/init/output.ts +22 -17
- package/src/commands/{migration-apply.ts → migrate.ts} +77 -73
- package/src/commands/migration-check/exit-codes.ts +3 -0
- package/src/commands/migration-check.ts +369 -0
- package/src/commands/migration-graph.ts +184 -0
- package/src/commands/migration-list.ts +155 -0
- package/src/commands/migration-log.ts +218 -0
- package/src/commands/migration-new.ts +30 -22
- package/src/commands/migration-plan.ts +104 -35
- package/src/commands/migration-show.ts +141 -65
- package/src/commands/migration-status.ts +82 -69
- package/src/commands/{migration-ref.ts → ref.ts} +32 -86
- package/src/control-api/client.ts +30 -21
- package/src/control-api/operations/apply-aggregate.ts +4 -4
- package/src/control-api/operations/contract-emit.ts +26 -3
- package/src/control-api/operations/db-apply-aggregate.ts +4 -3
- package/src/control-api/operations/db-verify.ts +2 -2
- package/src/control-api/operations/migration-apply.ts +5 -4
- package/src/control-api/types.ts +12 -7
- package/src/load-ts-contract.ts +9 -1
- package/src/migration-cli.ts +1 -1
- package/src/utils/cli-errors.ts +37 -0
- package/src/utils/command-helpers.ts +28 -3
- package/src/utils/contract-space-aggregate-loader.ts +4 -4
- package/src/utils/contract-space-seed-phase.ts +2 -2
- package/src/utils/formatters/help.ts +12 -2
- package/src/utils/formatters/migrations.ts +2 -2
- package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
- package/dist/client-BCnP7cHo.mjs.map +0 -1
- package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
- package/dist/commands/migration-apply.d.mts +0 -51
- package/dist/commands/migration-apply.d.mts.map +0 -1
- package/dist/commands/migration-apply.mjs.map +0 -1
- package/dist/commands/migration-ref.d.mts +0 -45
- package/dist/commands/migration-ref.d.mts.map +0 -1
- package/dist/commands/migration-ref.mjs.map +0 -1
- package/dist/contract-emit-B77TsJqf.mjs.map +0 -1
- package/dist/db-verify-Czm5T-J4.mjs.map +0 -1
- package/dist/init-B-k3a1Qw.mjs.map +0 -1
- package/dist/migration-plan-mRu5K81L.mjs.map +0 -1
- package/dist/migration-status-By9G5p2H.mjs.map +0 -1
- package/dist/migrations-CTsyBXCA.mjs.map +0 -1
- package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
- package/dist/types-LItU7E4l.d.mts.map +0 -1
- /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
|
@@ -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 (`
|
|
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 `
|
|
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 `
|
|
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 '
|
|
288
|
+
return 'migrate';
|
|
289
289
|
}
|
|
290
290
|
}
|
|
@@ -4,6 +4,7 @@ import { emit, getEmittedArtifactPaths } from '@prisma-next/emitter';
|
|
|
4
4
|
import { createControlStack } from '@prisma-next/framework-components/control';
|
|
5
5
|
import { abortable } from '@prisma-next/utils/abortable';
|
|
6
6
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
7
|
+
import type { JsonObject } from '@prisma-next/utils/json';
|
|
7
8
|
import { dirname } from 'pathe';
|
|
8
9
|
import { loadConfig } from '../../config-loader';
|
|
9
10
|
import { errorContractConfigMissing, errorRuntime } from '../../utils/cli-errors';
|
|
@@ -231,10 +232,32 @@ export async function executeContractEmit(
|
|
|
231
232
|
config.target.targetId,
|
|
232
233
|
rawComponents,
|
|
233
234
|
);
|
|
234
|
-
|
|
235
|
-
|
|
235
|
+
// Blind cast: `validateProviderResult` upstream has already
|
|
236
|
+
// pinned `validatedContract.value` to the provider's loose
|
|
237
|
+
// `Contract` envelope, but the local `Contract` type at this
|
|
238
|
+
// call site is the precise structural interface. Re-narrowing
|
|
239
|
+
// the envelope into the precise type is exactly what the
|
|
240
|
+
// `familyInstance.deserializeContract(enrichedIR)` call on the
|
|
241
|
+
// next line does — the cast just defers the structural check
|
|
242
|
+
// by one statement so `enrichContract` can decorate first.
|
|
243
|
+
const enrichedIR = enrichContract(
|
|
244
|
+
validatedContract.value as unknown as Contract,
|
|
245
|
+
frameworkComponents,
|
|
246
|
+
);
|
|
247
|
+
familyInstance.deserializeContract(enrichedIR);
|
|
248
|
+
// Each target's descriptor ships a `contractSerializer` SPI; the
|
|
249
|
+
// framework canonicalizer threads its `serializeContract` so the
|
|
250
|
+
// on-disk JSON envelope is constructed by target-owned code
|
|
251
|
+
// rather than by walking the in-memory contract with
|
|
252
|
+
// `Object.entries` (which would leak runtime-only class API
|
|
253
|
+
// fields into the persisted shape).
|
|
254
|
+
const serializeContract = (c: Contract): JsonObject =>
|
|
255
|
+
config.target.contractSerializer.serializeContract(c);
|
|
236
256
|
emitResult = await unlessAborted(
|
|
237
|
-
emit(enrichedIR, stack, config.family.emission, {
|
|
257
|
+
emit(enrichedIR, stack, config.family.emission, {
|
|
258
|
+
outputJsonPath,
|
|
259
|
+
serializeContract,
|
|
260
|
+
}),
|
|
238
261
|
);
|
|
239
262
|
} catch (error) {
|
|
240
263
|
endSpan(onProgress, 'emit', 'error');
|
|
@@ -116,7 +116,7 @@ export async function executeAggregateApply<TFamilyId extends string, TTargetId
|
|
|
116
116
|
migrationsDir,
|
|
117
117
|
appContract: contract,
|
|
118
118
|
extensionPacks,
|
|
119
|
-
|
|
119
|
+
deserializeContract: (json) => familyInstance.deserializeContract(json),
|
|
120
120
|
};
|
|
121
121
|
const loaded = await buildContractSpaceAggregate(loadInputs);
|
|
122
122
|
if (!loaded.ok) {
|
|
@@ -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
|
-
// `
|
|
210
|
+
// `migrate` — only how each caller produces `perSpacePlans`
|
|
211
211
|
// differs (synth + graph-walk via planAggregate here; graph-walk
|
|
212
|
-
// only for
|
|
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,
|
|
@@ -120,7 +120,7 @@ function buildLoadInputs<TFamilyId extends string, TTargetId extends string>(
|
|
|
120
120
|
migrationsDir: options.migrationsDir,
|
|
121
121
|
appContract: options.contract,
|
|
122
122
|
extensionPacks: options.extensionPacks,
|
|
123
|
-
|
|
123
|
+
deserializeContract: (json) => options.familyInstance.deserializeContract(json),
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
|
|
@@ -172,7 +172,7 @@ function createPerMemberVerifier<TFamilyId extends string, TTargetId extends str
|
|
|
172
172
|
const { skipSchema, familyInstance, frameworkComponents } = options;
|
|
173
173
|
return (projectedSchema, member, verifyMode) => {
|
|
174
174
|
if (skipSchema) return buildSkippedSchemaResult(member);
|
|
175
|
-
return familyInstance.
|
|
175
|
+
return familyInstance.verifySchema({
|
|
176
176
|
contract: member.contract,
|
|
177
177
|
// The family's `TSchemaIR` is opaque to migration-tools; the
|
|
178
178
|
// aggregate verifier passes through whatever we hand it. The
|
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
import { applyAggregate, buildPerSpaceBreakdown } from './apply-aggregate';
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Inputs for the aggregate-walking `
|
|
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
|
-
*
|
|
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>,
|
|
@@ -136,7 +137,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
136
137
|
migrationsDir,
|
|
137
138
|
appContract: contract,
|
|
138
139
|
extensionPacks,
|
|
139
|
-
|
|
140
|
+
deserializeContract: (json) => familyInstance.deserializeContract(json),
|
|
140
141
|
appMigrationPackages,
|
|
141
142
|
};
|
|
142
143
|
const loaded = await buildContractSpaceAggregate(loadInputs);
|
|
@@ -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: `
|
|
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
|
}
|
package/src/control-api/types.ts
CHANGED
|
@@ -118,7 +118,7 @@ export type OnControlProgress = (event: ControlProgressEvent) => void;
|
|
|
118
118
|
* Options for the verify operation.
|
|
119
119
|
*/
|
|
120
120
|
export interface VerifyOptions {
|
|
121
|
-
/** Contract or unvalidated JSON - validated at runtime via familyInstance.
|
|
121
|
+
/** Contract or unvalidated JSON - validated at runtime via familyInstance.deserializeContract() */
|
|
122
122
|
readonly contract: unknown;
|
|
123
123
|
/**
|
|
124
124
|
* Database connection. If provided, verify will connect before executing.
|
|
@@ -134,7 +134,7 @@ export interface VerifyOptions {
|
|
|
134
134
|
* Options for the schemaVerify operation.
|
|
135
135
|
*/
|
|
136
136
|
export interface SchemaVerifyOptions {
|
|
137
|
-
/** Contract or unvalidated JSON - validated at runtime via familyInstance.
|
|
137
|
+
/** Contract or unvalidated JSON - validated at runtime via familyInstance.deserializeContract() */
|
|
138
138
|
readonly contract: unknown;
|
|
139
139
|
/**
|
|
140
140
|
* Whether to use strict mode for schema verification.
|
|
@@ -156,7 +156,7 @@ export interface SchemaVerifyOptions {
|
|
|
156
156
|
* Options for the sign operation.
|
|
157
157
|
*/
|
|
158
158
|
export interface SignOptions {
|
|
159
|
-
/** Contract or unvalidated JSON - validated at runtime via familyInstance.
|
|
159
|
+
/** Contract or unvalidated JSON - validated at runtime via familyInstance.deserializeContract() */
|
|
160
160
|
readonly contract: unknown;
|
|
161
161
|
/**
|
|
162
162
|
* Path to the contract file (for metadata in the result).
|
|
@@ -180,7 +180,7 @@ export interface SignOptions {
|
|
|
180
180
|
* Options for the dbInit operation.
|
|
181
181
|
*/
|
|
182
182
|
export interface DbInitOptions {
|
|
183
|
-
/** Contract or unvalidated JSON - validated at runtime via familyInstance.
|
|
183
|
+
/** Contract or unvalidated JSON - validated at runtime via familyInstance.deserializeContract() */
|
|
184
184
|
readonly contract: unknown;
|
|
185
185
|
/**
|
|
186
186
|
* Mode for the dbInit operation.
|
|
@@ -209,7 +209,7 @@ export interface DbInitOptions {
|
|
|
209
209
|
* Options for the dbUpdate operation.
|
|
210
210
|
*/
|
|
211
211
|
export interface DbUpdateOptions {
|
|
212
|
-
/** Contract or unvalidated JSON - validated at runtime via familyInstance.
|
|
212
|
+
/** Contract or unvalidated JSON - validated at runtime via familyInstance.deserializeContract() */
|
|
213
213
|
readonly contract: unknown;
|
|
214
214
|
/**
|
|
215
215
|
* Mode for the dbUpdate operation.
|
|
@@ -251,7 +251,13 @@ export interface DbUpdateOptions {
|
|
|
251
251
|
* portion of the verifier.
|
|
252
252
|
*/
|
|
253
253
|
export interface DbVerifyOptions {
|
|
254
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Already-deserialized contract. Callers cross the family
|
|
256
|
+
* `deserializeContract` seam at the read site (TML-2536) and pass the
|
|
257
|
+
* hydrated value through unchanged; this op no longer re-runs the
|
|
258
|
+
* SerializerBase pipeline.
|
|
259
|
+
*/
|
|
260
|
+
readonly contract: Contract;
|
|
255
261
|
readonly migrationsDir: string;
|
|
256
262
|
readonly strict: boolean;
|
|
257
263
|
readonly skipSchema: boolean;
|
|
@@ -590,7 +596,6 @@ export interface MigrationApplyStep {
|
|
|
590
596
|
readonly dirName: string;
|
|
591
597
|
readonly from: string | null;
|
|
592
598
|
readonly to: string;
|
|
593
|
-
readonly toContract: Contract;
|
|
594
599
|
readonly operations: readonly MigrationPlanOperation[];
|
|
595
600
|
/**
|
|
596
601
|
* Sorted, deduplicated invariant ids from `migration.json.providedInvariants`.
|
package/src/load-ts-contract.ts
CHANGED
|
@@ -212,7 +212,15 @@ export async function loadContractFromTs(
|
|
|
212
212
|
|
|
213
213
|
validatePurity(contract);
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
// Blind cast: the loaded module was authored by user code
|
|
216
|
+
// (typically via `defineContract` / a contract builder) and
|
|
217
|
+
// its runtime shape is structurally a `Contract`, but the
|
|
218
|
+
// dynamic import collapses the source typing. The contract
|
|
219
|
+
// structural validation that asserts the shape happens
|
|
220
|
+
// downstream at the `familyInstance.deserializeContract` seam
|
|
221
|
+
// (e.g. in `executeContractEmit`); this helper only checks
|
|
222
|
+
// purity here.
|
|
223
|
+
return contract as unknown as Contract;
|
|
216
224
|
} catch (error) {
|
|
217
225
|
try {
|
|
218
226
|
if (tempFile) {
|
package/src/migration-cli.ts
CHANGED
|
@@ -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
|
|
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
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -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
|
|
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`, `
|
|
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
|
-
* `
|
|
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 {
|
|
@@ -120,7 +120,7 @@ export interface BuildAggregateInputs<TFamilyId extends string, TTargetId extend
|
|
|
120
120
|
readonly migrationsDir: string;
|
|
121
121
|
readonly appContract: Contract;
|
|
122
122
|
readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
|
|
123
|
-
readonly
|
|
123
|
+
readonly deserializeContract: (contractJson: unknown) => Contract;
|
|
124
124
|
/**
|
|
125
125
|
* App-space migration packages to hydrate the app member's
|
|
126
126
|
* migration graph with. Defaults to `[]` (matches the `db init` /
|
|
@@ -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
|
-
* `
|
|
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. `
|
|
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
|
*
|
|
@@ -165,7 +165,7 @@ export async function buildContractSpaceAggregate<
|
|
|
165
165
|
migrationsDir: inputs.migrationsDir,
|
|
166
166
|
appContract: inputs.appContract,
|
|
167
167
|
declaredExtensions,
|
|
168
|
-
|
|
168
|
+
deserializeContract: inputs.deserializeContract,
|
|
169
169
|
appMigrationPackages: inputs.appMigrationPackages ?? [],
|
|
170
170
|
};
|
|
171
171
|
|
|
@@ -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 (`
|
|
94
|
+
* surface (`migrate`, `migration status`, the runner).
|
|
95
95
|
*/
|
|
96
96
|
export async function runContractSpaceSeedPhase(
|
|
97
97
|
inputs: ContractSpaceSeedPhaseInputs,
|
|
@@ -193,7 +193,7 @@ function buildPlaceholderContractDts(spaceId: string): string {
|
|
|
193
193
|
' * alongside `contract.json` and `refs/head.json`. A typed `.d.ts`',
|
|
194
194
|
' * rendering pass for extension contracts is tracked separately;',
|
|
195
195
|
' * until that ships, consumers should import `contract.json`',
|
|
196
|
-
' *
|
|
196
|
+
' * and pass it through the target descriptor’s `contractSerializer`.',
|
|
197
197
|
' */',
|
|
198
198
|
'export {};',
|
|
199
199
|
'',
|
|
@@ -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
|
-
|
|
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` / `
|
|
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
|
-
* `
|
|
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"}
|