@prisma-next/cli 0.11.0 → 0.12.0
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 +13 -9
- package/dist/cli.mjs +259 -12
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-oXO2WCPD.mjs → client-KgJorIvG.mjs} +72 -60
- package/dist/client-KgJorIvG.mjs.map +1 -0
- package/dist/{command-helpers-BSb0tRC8.mjs → command-helpers-Bbw1GbwL.mjs} +646 -46
- package/dist/command-helpers-Bbw1GbwL.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +32 -7
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -4
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +12 -10
- 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 +41 -11
- 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 +6 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +75 -40
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +4 -3
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +1 -280
- package/dist/commands/migration-graph.d.mts +13 -2
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +2 -137
- package/dist/commands/migration-list.d.mts +64 -4
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +143 -56
- package/dist/commands/migration-list.mjs.map +1 -1
- package/dist/commands/migration-log.d.mts +10 -1
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +10 -15
- package/dist/commands/migration-log.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +32 -38
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +3 -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 +4 -55
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +61 -153
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +12 -49
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +85 -81
- package/dist/commands/migration-status.mjs.map +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +38 -10
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/contract-at-errors-BxP-TOMl.mjs +42 -0
- package/dist/contract-at-errors-BxP-TOMl.mjs.map +1 -0
- package/dist/{contract-emit-bcrpT-wD.mjs → contract-emit-D-4jrNve.mjs} +25 -10
- package/dist/contract-emit-D-4jrNve.mjs.map +1 -0
- package/dist/{contract-emit-r4y8Zhf1.mjs → contract-emit-DxcGl4Uq.mjs} +19 -14
- package/dist/contract-emit-DxcGl4Uq.mjs.map +1 -0
- package/dist/{contract-enrichment-Dani0mMW.mjs → contract-enrichment-a0V5Y_mL.mjs} +4 -25
- package/dist/contract-enrichment-a0V5Y_mL.mjs.map +1 -0
- package/dist/{contract-infer-BmySmqVT.mjs → contract-infer-D8uEbJuu.mjs} +4 -5
- package/dist/{contract-infer-BmySmqVT.mjs.map → contract-infer-D8uEbJuu.mjs.map} +1 -1
- package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs +247 -0
- package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs.map +1 -0
- package/dist/{db-verify-BClPs3ph.mjs → db-verify-v_vUKXTU.mjs} +5 -7
- package/dist/{db-verify-BClPs3ph.mjs.map → db-verify-v_vUKXTU.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +3 -3
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -3
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/extension-pack-inputs-IDvjRCi3.mjs +62 -0
- package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +1 -0
- package/dist/{framework-components-65gOHkHB.mjs → framework-components-fYXjz_in.mjs} +2 -2
- package/dist/{framework-components-65gOHkHB.mjs.map → framework-components-fYXjz_in.mjs.map} +1 -1
- package/dist/global-flags-DEHjV8_s.d.mts +34 -0
- package/dist/global-flags-DEHjV8_s.d.mts.map +1 -0
- package/dist/{graph-render-DJVv0_uf.mjs → graph-render-rFAqZujX.mjs} +2 -2
- package/dist/{graph-render-DJVv0_uf.mjs.map → graph-render-rFAqZujX.mjs.map} +1 -1
- package/dist/{init-BCJZPWE1.mjs → init-Cv9UzWL5.mjs} +20 -269
- package/dist/init-Cv9UzWL5.mjs.map +1 -0
- package/dist/{inspect-live-schema-DSRbFoOL.mjs → inspect-live-schema-C6ohV_oQ.mjs} +4 -5
- package/dist/{inspect-live-schema-DSRbFoOL.mjs.map → inspect-live-schema-C6ohV_oQ.mjs.map} +1 -1
- package/dist/migration-check-BiBJoYYW.mjs +341 -0
- package/dist/migration-check-BiBJoYYW.mjs.map +1 -0
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +4 -4
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-Bzd9La5c.mjs → migration-command-scaffold-CjvwO6at.mjs} +4 -5
- package/dist/{migration-command-scaffold-Bzd9La5c.mjs.map → migration-command-scaffold-CjvwO6at.mjs.map} +1 -1
- package/dist/migration-graph-D7DVUElV.mjs +1232 -0
- package/dist/migration-graph-D7DVUElV.mjs.map +1 -0
- package/dist/migration-list-styler-BRwF4-gy.mjs +399 -0
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +1 -0
- package/dist/{migration-plan-CFwqw3Gk.mjs → migration-plan-9DJ7q7_z.mjs} +372 -133
- package/dist/migration-plan-9DJ7q7_z.mjs.map +1 -0
- package/dist/{migration-types-BXWvz12q.d.mts → migration-types-D2FW63pr.d.mts} +1 -1
- package/dist/{migration-types-BXWvz12q.d.mts.map → migration-types-D2FW63pr.d.mts.map} +1 -1
- package/dist/{migrations-CwZMa1Ck.mjs → migrations-Cv2jxNNK.mjs} +12 -13
- package/dist/migrations-Cv2jxNNK.mjs.map +1 -0
- package/dist/{output-BlsrGMEF.mjs → output-B60Gw5fu.mjs} +1 -1
- package/dist/{output-BlsrGMEF.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs → progress-adapter-C644QK8l.mjs} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs.map → progress-adapter-C644QK8l.mjs.map} +1 -1
- package/dist/ref-advancement-DUZqsue6.mjs +50 -0
- package/dist/ref-advancement-DUZqsue6.mjs.map +1 -0
- package/dist/terminal-ui-5Y6mrg93.d.mts +133 -0
- package/dist/terminal-ui-5Y6mrg93.d.mts.map +1 -0
- package/dist/{types--CqjMdk0.d.mts → types-Dt_SfqFm.d.mts} +28 -28
- package/dist/types-Dt_SfqFm.d.mts.map +1 -0
- package/dist/{verify-Bom75OYI.mjs → verify-DCA9Sldu.mjs} +2 -2
- package/dist/{verify-Bom75OYI.mjs.map → verify-DCA9Sldu.mjs.map} +1 -1
- package/package.json +35 -24
- package/src/commands/contract-emit.ts +19 -7
- package/src/commands/contract-infer.ts +1 -1
- package/src/commands/db-init.ts +48 -2
- package/src/commands/db-sign.ts +9 -5
- package/src/commands/db-update.ts +54 -8
- package/src/commands/init/hygiene-gitattributes.ts +2 -2
- package/src/commands/init/index.ts +2 -1
- package/src/commands/init/templates/code-templates.ts +4 -2
- package/src/commands/init/templates/env.ts +13 -14
- package/src/commands/migrate.ts +125 -44
- package/src/commands/migration-check.ts +43 -83
- package/src/commands/migration-graph.ts +75 -60
- package/src/commands/migration-list.ts +220 -74
- package/src/commands/migration-log.ts +8 -14
- package/src/commands/migration-new.ts +44 -48
- package/src/commands/migration-plan.ts +412 -197
- package/src/commands/migration-show.ts +65 -284
- package/src/commands/migration-status.ts +127 -124
- package/src/commands/ref.ts +53 -8
- package/src/control-api/client.ts +0 -1
- package/src/control-api/contract-enrichment.ts +6 -42
- package/src/control-api/operations/{apply-aggregate.ts → apply.ts} +44 -75
- package/src/control-api/operations/contract-emit.ts +14 -6
- package/src/control-api/operations/{db-apply-aggregate.ts → db-apply.ts} +19 -19
- package/src/control-api/operations/db-init.ts +4 -4
- package/src/control-api/operations/db-update.ts +4 -4
- package/src/control-api/operations/db-verify.ts +15 -11
- package/src/control-api/operations/migration-apply.ts +56 -47
- package/src/control-api/types.ts +26 -27
- package/src/migration-cli.ts +4 -4
- package/src/utils/cli-errors.ts +234 -0
- package/src/utils/command-helpers.ts +9 -24
- package/src/utils/contract-at-errors.ts +96 -0
- package/src/utils/contract-space-aggregate-loader.ts +336 -117
- package/src/utils/formatters/migration-graph-layout.ts +1119 -0
- package/src/utils/formatters/migration-graph-rows.ts +336 -0
- package/src/utils/formatters/migration-graph-tree-render.ts +459 -0
- package/src/utils/formatters/migration-list-data-column.ts +115 -0
- package/src/utils/formatters/migration-list-graph-topology.ts +368 -0
- package/src/utils/formatters/migration-list-render.ts +191 -0
- package/src/utils/formatters/migration-list-styler.ts +63 -0
- package/src/utils/formatters/migration-list-types.ts +21 -0
- package/src/utils/formatters/migrations.ts +37 -46
- package/src/utils/glyph-mode.ts +22 -0
- package/src/utils/integrity-violation-to-check-failure.ts +130 -0
- package/src/utils/plan-resolution.ts +258 -0
- package/src/utils/ref-advancement.ts +68 -0
- package/src/utils/terminal-ui.ts +42 -1
- package/dist/cli-errors-Czmx92Zy.d.mts +0 -3
- package/dist/cli-errors-Djtz98Vm.mjs +0 -71
- package/dist/cli-errors-Djtz98Vm.mjs.map +0 -1
- package/dist/client-oXO2WCPD.mjs.map +0 -1
- package/dist/command-helpers-BSb0tRC8.mjs.map +0 -1
- package/dist/commands/migration-check.mjs.map +0 -1
- package/dist/commands/migration-graph.mjs.map +0 -1
- package/dist/contract-emit-bcrpT-wD.mjs.map +0 -1
- package/dist/contract-emit-r4y8Zhf1.mjs.map +0 -1
- package/dist/contract-enrichment-Dani0mMW.mjs.map +0 -1
- package/dist/contract-space-aggregate-loader-BmNQwlws.mjs +0 -160
- package/dist/contract-space-aggregate-loader-BmNQwlws.mjs.map +0 -1
- package/dist/global-flags-CdE7M0d9.d.mts +0 -15
- package/dist/global-flags-CdE7M0d9.d.mts.map +0 -1
- package/dist/init-BCJZPWE1.mjs.map +0 -1
- package/dist/migration-plan-CFwqw3Gk.mjs.map +0 -1
- package/dist/migrations-CwZMa1Ck.mjs.map +0 -1
- package/dist/rolldown-runtime-twds-ZHy.mjs +0 -14
- package/dist/terminal-ui-BiB_8KNo.mjs +0 -379
- package/dist/terminal-ui-BiB_8KNo.mjs.map +0 -1
- package/dist/types--CqjMdk0.d.mts.map +0 -1
|
@@ -7,16 +7,16 @@ import type {
|
|
|
7
7
|
TargetMigrationsCapability,
|
|
8
8
|
} from '@prisma-next/framework-components/control';
|
|
9
9
|
import {
|
|
10
|
-
type AggregatePerSpacePlan,
|
|
11
10
|
type ContractMarkerRecordLike,
|
|
12
11
|
type ContractSpaceAggregate,
|
|
13
12
|
type ContractSpaceMember,
|
|
14
13
|
graphWalkStrategy,
|
|
14
|
+
type PerSpacePlan,
|
|
15
|
+
requireHeadRef,
|
|
15
16
|
} from '@prisma-next/migration-tools/aggregate';
|
|
16
17
|
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
17
18
|
import { errorNoInvariantPath } from '@prisma-next/migration-tools/errors';
|
|
18
19
|
import { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';
|
|
19
|
-
import type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';
|
|
20
20
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
21
21
|
import { notOk, ok } from '@prisma-next/utils/result';
|
|
22
22
|
import {
|
|
@@ -24,14 +24,14 @@ import {
|
|
|
24
24
|
buildContractSpaceAggregate,
|
|
25
25
|
} from '../../utils/contract-space-aggregate-loader';
|
|
26
26
|
import type {
|
|
27
|
-
AggregatePerSpaceExecutionEntry,
|
|
28
27
|
MigrationApplyFailure,
|
|
29
28
|
MigrationApplyPathDecision,
|
|
30
29
|
MigrationApplyResult,
|
|
31
30
|
MigrationApplySuccess,
|
|
32
31
|
OnControlProgress,
|
|
32
|
+
PerSpaceExecutionEntry,
|
|
33
33
|
} from '../types';
|
|
34
|
-
import {
|
|
34
|
+
import { applyMigration, buildPerSpaceBreakdown } from './apply';
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Inputs for the aggregate-walking `migrate` control-api
|
|
@@ -56,21 +56,10 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
|
|
|
56
56
|
readonly migrationsDir: string;
|
|
57
57
|
readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
|
|
58
58
|
readonly targetId: TTargetId;
|
|
59
|
-
/**
|
|
60
|
-
* Already-loaded app-space migration packages. The CLI command
|
|
61
|
-
* loads these via `loadMigrationPackages(appMigrationsDir)`; the
|
|
62
|
-
* operation hydrates the app member's graph with them. Required
|
|
63
|
-
* because the framework-neutral aggregate loader doesn't know how
|
|
64
|
-
* to read the user's `migrations/` directory layout (it's family-
|
|
65
|
-
* aware: ops.json shape, manifest keys, etc.).
|
|
66
|
-
*/
|
|
67
|
-
readonly appMigrationPackages: ReadonlyArray<OnDiskMigrationPackage>;
|
|
68
59
|
/**
|
|
69
60
|
* Optional app-space ref override. When provided, the app member's
|
|
70
61
|
* graph-walk targets this hash instead of `member.headRef.hash`.
|
|
71
62
|
* Extensions are unaffected — they always walk to their own head.
|
|
72
|
-
*
|
|
73
|
-
* Sub-spec § `--ref <hash>` semantics under multi-space.
|
|
74
63
|
*/
|
|
75
64
|
readonly refHash?: string;
|
|
76
65
|
/**
|
|
@@ -106,7 +95,7 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
|
|
|
106
95
|
* marker to `member.headRef.hash` (or `refHash` for the app
|
|
107
96
|
* member when provided). Empty-graph members fail loudly — a
|
|
108
97
|
* "never planned" space is a user-error condition for replay.
|
|
109
|
-
* 4. Hand off to {@link
|
|
98
|
+
* 4. Hand off to {@link applyMigration} (the runner-driving tail
|
|
110
99
|
* shared with `db init` / `db update`). Marker advancement is
|
|
111
100
|
* inside the per-space transaction.
|
|
112
101
|
*
|
|
@@ -125,7 +114,6 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
125
114
|
migrationsDir,
|
|
126
115
|
extensionPacks,
|
|
127
116
|
targetId,
|
|
128
|
-
appMigrationPackages,
|
|
129
117
|
refHash,
|
|
130
118
|
refInvariants,
|
|
131
119
|
refName,
|
|
@@ -138,7 +126,6 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
138
126
|
appContract: contract,
|
|
139
127
|
extensionPacks,
|
|
140
128
|
deserializeContract: (json) => familyInstance.deserializeContract(json),
|
|
141
|
-
appMigrationPackages,
|
|
142
129
|
};
|
|
143
130
|
const loaded = await buildContractSpaceAggregate(loadInputs);
|
|
144
131
|
if (!loaded.ok) {
|
|
@@ -152,21 +139,24 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
152
139
|
// when provided, otherwise its own head; extensions always walk
|
|
153
140
|
// to their own head ref.
|
|
154
141
|
const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];
|
|
155
|
-
const perSpacePlans = new Map<string,
|
|
142
|
+
const perSpacePlans = new Map<string, PerSpacePlan>();
|
|
156
143
|
// Already-at-head empty-graph members (typically extensions whose
|
|
157
144
|
// head ref is the empty sentinel, or whose live marker already
|
|
158
145
|
// matches the target). Kept out of the runner schedule so we don't
|
|
159
146
|
// write spurious markers for greenfield extensions, but merged back
|
|
160
147
|
// into the success envelope so every loaded member is represented.
|
|
161
|
-
const atHeadResolutions = new Map<string,
|
|
148
|
+
const atHeadResolutions = new Map<string, PerSpacePlan>();
|
|
162
149
|
for (const member of allMembers) {
|
|
163
150
|
const isAppMember = member.spaceId === aggregate.app.spaceId;
|
|
164
|
-
|
|
151
|
+
// The aggregate passed the integrity gate, so every member's head ref
|
|
152
|
+
// is resolved (the app's is synthesised from the live contract).
|
|
153
|
+
const headRef = requireHeadRef(member);
|
|
154
|
+
const targetHash = isAppMember && refHash !== undefined ? refHash : headRef.hash;
|
|
165
155
|
const liveMarker = markerRows.get(member.spaceId) ?? null;
|
|
166
156
|
|
|
167
157
|
// Empty-graph members fail loudly: replay needs an on-disk path
|
|
168
158
|
// and an empty graph means the user has never planned this space.
|
|
169
|
-
if (member.
|
|
159
|
+
if (member.graph().nodes.size === 0) {
|
|
170
160
|
// Edge case: target == EMPTY (greenfield, nothing to do) or
|
|
171
161
|
// the live marker already matches the target. Loader integrity
|
|
172
162
|
// allows this for extensions whose head ref is the empty
|
|
@@ -197,9 +187,9 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
197
187
|
const targetInvariants =
|
|
198
188
|
isAppMember && refHash !== undefined && refInvariants !== undefined
|
|
199
189
|
? refInvariants
|
|
200
|
-
:
|
|
190
|
+
: headRef.invariants;
|
|
201
191
|
const targetMember: ContractSpaceMember =
|
|
202
|
-
targetHash ===
|
|
192
|
+
targetHash === headRef.hash && targetInvariants === headRef.invariants
|
|
203
193
|
? member
|
|
204
194
|
: { ...member, headRef: { hash: targetHash, invariants: targetInvariants } };
|
|
205
195
|
|
|
@@ -224,7 +214,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
224
214
|
// is never a graph node, producing an empty `structuralPath` and
|
|
225
215
|
// a less actionable diagnostic.
|
|
226
216
|
const fromHash = liveMarker?.storageHash ?? EMPTY_CONTRACT_HASH;
|
|
227
|
-
const structural = findPathWithDecision(targetMember.
|
|
217
|
+
const structural = findPathWithDecision(targetMember.graph(), fromHash, targetHash, {
|
|
228
218
|
required: new Set<string>(),
|
|
229
219
|
});
|
|
230
220
|
const structuralPath =
|
|
@@ -286,7 +276,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
286
276
|
);
|
|
287
277
|
}
|
|
288
278
|
|
|
289
|
-
const applied = await
|
|
279
|
+
const applied = await applyMigration({
|
|
290
280
|
aggregate,
|
|
291
281
|
perSpacePlans,
|
|
292
282
|
applyOrder,
|
|
@@ -346,7 +336,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
346
336
|
}
|
|
347
337
|
|
|
348
338
|
/**
|
|
349
|
-
* Build a zero-op {@link
|
|
339
|
+
* Build a zero-op {@link PerSpacePlan} for an empty-graph
|
|
350
340
|
* member whose live marker already matches the target. Lets the apply
|
|
351
341
|
* pipeline thread the member through `perSpacePlans` -> `applyOrder`
|
|
352
342
|
* -> the success envelope's `perSpace[]` block so the result reflects
|
|
@@ -357,7 +347,7 @@ function buildAtHeadResolution(args: {
|
|
|
357
347
|
readonly member: ContractSpaceMember;
|
|
358
348
|
readonly targetHash: string;
|
|
359
349
|
readonly liveMarker: ContractMarkerRecordLike | null;
|
|
360
|
-
}):
|
|
350
|
+
}): PerSpacePlan {
|
|
361
351
|
const { aggregateTargetId, member, targetHash, liveMarker } = args;
|
|
362
352
|
return {
|
|
363
353
|
plan: {
|
|
@@ -369,7 +359,7 @@ function buildAtHeadResolution(args: {
|
|
|
369
359
|
providedInvariants: [],
|
|
370
360
|
},
|
|
371
361
|
displayOps: [],
|
|
372
|
-
destinationContract: member.contract,
|
|
362
|
+
destinationContract: member.contract(),
|
|
373
363
|
strategy: 'graph-walk',
|
|
374
364
|
migrationEdges: [],
|
|
375
365
|
};
|
|
@@ -377,7 +367,7 @@ function buildAtHeadResolution(args: {
|
|
|
377
367
|
|
|
378
368
|
function sumPlannedOps(
|
|
379
369
|
applyOrder: readonly string[],
|
|
380
|
-
perSpacePlans: ReadonlyMap<string,
|
|
370
|
+
perSpacePlans: ReadonlyMap<string, PerSpacePlan>,
|
|
381
371
|
): number {
|
|
382
372
|
let total = 0;
|
|
383
373
|
for (const spaceId of applyOrder) {
|
|
@@ -392,28 +382,27 @@ interface BuildSuccessArgs {
|
|
|
392
382
|
readonly aggregate: ContractSpaceAggregate;
|
|
393
383
|
readonly orderedResolutions: ReadonlyArray<{
|
|
394
384
|
readonly spaceId: string;
|
|
395
|
-
readonly entry:
|
|
385
|
+
readonly entry: PerSpacePlan;
|
|
396
386
|
}>;
|
|
397
|
-
readonly perSpace: ReadonlyArray<
|
|
387
|
+
readonly perSpace: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
398
388
|
readonly totalOpsExecuted: number;
|
|
399
389
|
readonly summary: string;
|
|
400
390
|
}
|
|
401
391
|
|
|
402
392
|
function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
|
|
403
393
|
// The marker hash surfaced at the top level is the **app member's**
|
|
404
|
-
// post-apply marker (
|
|
394
|
+
// post-apply marker (the top-level `markerHash` field).
|
|
405
395
|
// Per-space markers live on `perSpace[].marker.storageHash`.
|
|
406
396
|
const appResolution = args.orderedResolutions.find(
|
|
407
397
|
(r) => r.spaceId === args.aggregate.app.spaceId,
|
|
408
398
|
);
|
|
409
399
|
const appMarkerHash =
|
|
410
|
-
appResolution?.entry.plan.destination.storageHash ?? args.aggregate.app.
|
|
400
|
+
appResolution?.entry.plan.destination.storageHash ?? requireHeadRef(args.aggregate.app).hash;
|
|
411
401
|
|
|
412
402
|
// Per-migration entries (one per authored edge) preserve the
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
//
|
|
416
|
-
// `perSpace[]`.
|
|
403
|
+
// `migrationsApplied` count semantics for back-compat with existing
|
|
404
|
+
// JSON-shape consumers (e.g. `parsed.applied.length` in integration
|
|
405
|
+
// tests). The aggregate per-space breakdown lives on `perSpace[]`.
|
|
417
406
|
const applied = args.orderedResolutions.flatMap((r) => {
|
|
418
407
|
const edges = r.entry.migrationEdges ?? [];
|
|
419
408
|
return edges.map((edge) => ({
|
|
@@ -458,26 +447,46 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
|
|
|
458
447
|
};
|
|
459
448
|
}
|
|
460
449
|
|
|
461
|
-
|
|
450
|
+
/**
|
|
451
|
+
* Build the `neverPlanned` failure raised when a contract space has no on-disk
|
|
452
|
+
* migration graph but migrate was asked to reach a target hash. The `why`
|
|
453
|
+
* states only the condition; the recovery sequence is composed by
|
|
454
|
+
* `errorPathUnreachable`'s `fix`.
|
|
455
|
+
*
|
|
456
|
+
* @internal Exported for testing only.
|
|
457
|
+
*/
|
|
458
|
+
export function buildNeverPlannedFailure(
|
|
459
|
+
spaceId: string,
|
|
460
|
+
targetHash: string,
|
|
461
|
+
): MigrationApplyFailure {
|
|
462
462
|
return {
|
|
463
463
|
code: 'MIGRATION_PATH_NOT_FOUND',
|
|
464
464
|
summary: `No on-disk migrations for contract space "${spaceId}"`,
|
|
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}"
|
|
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}".`,
|
|
466
466
|
meta: { spaceId, target: targetHash, kind: 'neverPlanned' },
|
|
467
467
|
};
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Build the `pathUnreachable` failure raised when an emitted contract has no
|
|
472
|
+
* on-disk migration edge from the current marker to the target. The `why`
|
|
473
|
+
* states only the condition (no edge between the two named states, and migrate
|
|
474
|
+
* replays edges rather than inventing them); the recovery sequence — plan the
|
|
475
|
+
* edge, then re-apply — is composed by `errorPathUnreachable`'s `fix`, so the
|
|
476
|
+
* two read as one non-redundant plan-then-apply story.
|
|
477
|
+
*
|
|
478
|
+
* @internal Exported for testing only.
|
|
479
|
+
*/
|
|
480
|
+
export function buildPathNotFoundFailure(
|
|
471
481
|
spaceId: string,
|
|
472
482
|
marker: ContractMarkerRecordLike | null,
|
|
473
483
|
targetHash: string,
|
|
474
484
|
): MigrationApplyFailure {
|
|
475
485
|
const fromHash = marker?.storageHash ?? '<empty>';
|
|
476
|
-
// The
|
|
477
|
-
//
|
|
478
|
-
//
|
|
479
|
-
//
|
|
480
|
-
// condition expressed against the offending space.
|
|
486
|
+
// The app-case phrasing names the user-visible condition (a
|
|
487
|
+
// contract has been emitted that no on-disk migration reaches) so
|
|
488
|
+
// the error reads naturally for the app member. Extension spaces
|
|
489
|
+
// see the same condition expressed against the offending space.
|
|
481
490
|
const summary =
|
|
482
491
|
spaceId === 'app'
|
|
483
492
|
? 'Current contract has no planned migration path'
|
|
@@ -485,7 +494,7 @@ function buildPathNotFoundFailure(
|
|
|
485
494
|
return {
|
|
486
495
|
code: 'MIGRATION_PATH_NOT_FOUND',
|
|
487
496
|
summary,
|
|
488
|
-
why: `
|
|
497
|
+
why: `No migration edge connects the current state "${fromHash}" to the target "${targetHash}" in contract space "${spaceId}". The on-disk migration graph does not join the two, and migrate replays existing edges — it never invents one.`,
|
|
489
498
|
meta: { spaceId, fromHash, targetHash, kind: 'pathUnreachable' },
|
|
490
499
|
};
|
|
491
500
|
}
|
package/src/control-api/types.ts
CHANGED
|
@@ -18,7 +18,6 @@ import type {
|
|
|
18
18
|
VerifyDatabaseSchemaResult,
|
|
19
19
|
} from '@prisma-next/framework-components/control';
|
|
20
20
|
import type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';
|
|
21
|
-
import type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';
|
|
22
21
|
import type { Result } from '@prisma-next/utils/result';
|
|
23
22
|
import type { ExecuteDbVerifyResult } from './operations/db-verify';
|
|
24
23
|
|
|
@@ -246,7 +245,7 @@ export interface DbUpdateOptions {
|
|
|
246
245
|
* Options for the dbVerify operation.
|
|
247
246
|
*
|
|
248
247
|
* Drives the loader → aggregate-verifier pipeline. `strict` maps to
|
|
249
|
-
* `
|
|
248
|
+
* `verifyMigration({ mode: 'strict' | 'lenient' })`; `skipSchema`
|
|
250
249
|
* mirrors the `--marker-only` CLI flag and short-circuits the schema
|
|
251
250
|
* portion of the verifier.
|
|
252
251
|
*/
|
|
@@ -327,7 +326,7 @@ export interface EmitOptions {
|
|
|
327
326
|
* to the user instead of being collapsed into a single ambiguous
|
|
328
327
|
* top-level hash.
|
|
329
328
|
*/
|
|
330
|
-
export interface
|
|
329
|
+
export interface PerSpaceExecutionEntry {
|
|
331
330
|
readonly spaceId: string;
|
|
332
331
|
/** `'app'` for the application's contract space; `'extension'` for any extension space. */
|
|
333
332
|
readonly kind: 'app' | 'extension';
|
|
@@ -388,9 +387,9 @@ export interface DbInitSuccess {
|
|
|
388
387
|
* alphabetically, then app). Present whenever the aggregate flow
|
|
389
388
|
* produced one — both `mode: 'plan'` and `mode: 'apply'`.
|
|
390
389
|
*
|
|
391
|
-
* See {@link
|
|
390
|
+
* See {@link PerSpaceExecutionEntry}.
|
|
392
391
|
*/
|
|
393
|
-
readonly perSpace?: ReadonlyArray<
|
|
392
|
+
readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
394
393
|
readonly summary: string;
|
|
395
394
|
}
|
|
396
395
|
|
|
@@ -458,9 +457,9 @@ export interface DbUpdateSuccess {
|
|
|
458
457
|
};
|
|
459
458
|
/**
|
|
460
459
|
* Per-space breakdown in canonical schedule order (extensions
|
|
461
|
-
* alphabetically, then app). See {@link
|
|
460
|
+
* alphabetically, then app). See {@link PerSpaceExecutionEntry}.
|
|
462
461
|
*/
|
|
463
|
-
readonly perSpace?: ReadonlyArray<
|
|
462
|
+
readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
464
463
|
readonly summary: string;
|
|
465
464
|
}
|
|
466
465
|
|
|
@@ -539,7 +538,7 @@ export type EmitResult = Result<EmitSuccess, EmitFailure>;
|
|
|
539
538
|
* contract-space aggregate, reading per-space marker rows from the
|
|
540
539
|
* live database, plotting per-space paths via `graphWalkStrategy`
|
|
541
540
|
* (replay-only — no synth, no introspection), and dispatching
|
|
542
|
-
* through the shared `
|
|
541
|
+
* through the shared `applyMigration` primitive. The CLI command
|
|
543
542
|
* just resolves the descriptor surface (config, refs, contract
|
|
544
543
|
* envelope, app-space migration packages) and hands the inputs in.
|
|
545
544
|
*/
|
|
@@ -548,12 +547,6 @@ export interface MigrationApplyOptions {
|
|
|
548
547
|
readonly contract: unknown;
|
|
549
548
|
/** Migrations root directory (`migrations/` under the project). */
|
|
550
549
|
readonly migrationsDir: string;
|
|
551
|
-
/**
|
|
552
|
-
* Already-loaded app-space migration packages. The CLI loads these
|
|
553
|
-
* via `loadMigrationPackages(appMigrationsDir)` before invoking
|
|
554
|
-
* `migrationApply`.
|
|
555
|
-
*/
|
|
556
|
-
readonly appMigrationPackages: ReadonlyArray<OnDiskMigrationPackage>;
|
|
557
550
|
/**
|
|
558
551
|
* Optional app-space ref override. When provided, the app member's
|
|
559
552
|
* graph-walk targets this hash instead of `contract.storage.storageHash`.
|
|
@@ -584,11 +577,11 @@ export interface MigrationApplyOptions {
|
|
|
584
577
|
|
|
585
578
|
/**
|
|
586
579
|
* A single on-disk migration package surfaced to the operation. The
|
|
587
|
-
* SQL family
|
|
588
|
-
* the operation hands it through to the
|
|
589
|
-
* loader's `appMigrationPackages` slot.
|
|
580
|
+
* SQL family surfaces this shape from the tolerant contract-space
|
|
581
|
+
* aggregate's app packages; the operation hands it through to the
|
|
582
|
+
* framework-neutral aggregate loader's `appMigrationPackages` slot.
|
|
590
583
|
*
|
|
591
|
-
* (Originally named `MigrationApplyStep` for the
|
|
584
|
+
* (Originally named `MigrationApplyStep` for the earlier app-only
|
|
592
585
|
* apply path; the name is kept for compatibility with existing CLI
|
|
593
586
|
* callers and tests.)
|
|
594
587
|
*/
|
|
@@ -612,8 +605,8 @@ export interface MigrationApplyStep {
|
|
|
612
605
|
*/
|
|
613
606
|
/**
|
|
614
607
|
* One entry per authored migration package applied. Preserves the
|
|
615
|
-
*
|
|
616
|
-
*
|
|
608
|
+
* `migrationsApplied` count semantics (each entry is one migration
|
|
609
|
+
* directory) so `applied.length === migrationsApplied`.
|
|
617
610
|
*
|
|
618
611
|
* Per-space aggregate detail (markers, ops grouped by space) lives
|
|
619
612
|
* on `perSpace[]`; this list is the per-edge view.
|
|
@@ -628,16 +621,15 @@ export interface MigrationApplyAppliedEntry {
|
|
|
628
621
|
}
|
|
629
622
|
|
|
630
623
|
/**
|
|
631
|
-
* Successful migrationApply result. Carries both the
|
|
632
|
-
*
|
|
633
|
-
* marker, surfaced for back-compat with single-space callers) and the
|
|
624
|
+
* Successful migrationApply result. Carries both the top-level fields
|
|
625
|
+
* (`markerHash` is the **app member's** post-apply marker) and the
|
|
634
626
|
* per-space breakdown (`perSpace` — markers / operations in canonical
|
|
635
627
|
* schedule order).
|
|
636
628
|
*/
|
|
637
629
|
/**
|
|
638
630
|
* Path-decision summary for the **app member** post-apply. Surfaced
|
|
639
|
-
*
|
|
640
|
-
*
|
|
631
|
+
* at the top level (and consumed by the cli-journeys suite, which
|
|
632
|
+
* inspects `requiredInvariants`/`satisfiedInvariants`/
|
|
641
633
|
* `selectedPath` to validate invariant routing).
|
|
642
634
|
*
|
|
643
635
|
* Per-space path decisions for extension members are not surfaced —
|
|
@@ -667,10 +659,10 @@ export interface MigrationApplySuccess {
|
|
|
667
659
|
readonly summary: string;
|
|
668
660
|
/**
|
|
669
661
|
* Per-space breakdown in canonical schedule order (extensions
|
|
670
|
-
* alphabetically, then app). See {@link
|
|
662
|
+
* alphabetically, then app). See {@link PerSpaceExecutionEntry}.
|
|
671
663
|
* Always present for the aggregate-walking operation.
|
|
672
664
|
*/
|
|
673
|
-
readonly perSpace: ReadonlyArray<
|
|
665
|
+
readonly perSpace: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
674
666
|
/**
|
|
675
667
|
* Path-decision data for the app member. Present whenever the
|
|
676
668
|
* graph-walk strategy ran for the app (i.e. always for the
|
|
@@ -719,6 +711,13 @@ export type MigrationApplyResult = Result<MigrationApplySuccess, MigrationApplyF
|
|
|
719
711
|
export interface ContractEmitOptions {
|
|
720
712
|
/** Path to the prisma-next.config.ts file */
|
|
721
713
|
readonly configPath: string;
|
|
714
|
+
/**
|
|
715
|
+
* Directory to write contract artifacts into. When set, `contract.json` and
|
|
716
|
+
* `contract.d.ts` are written inside this directory, taking precedence over
|
|
717
|
+
* any output path from the loaded config. The value must be an absolute path;
|
|
718
|
+
* resolution against cwd is the caller's responsibility.
|
|
719
|
+
*/
|
|
720
|
+
readonly outputPath?: string;
|
|
722
721
|
/** Optional AbortSignal for cancelling the in-flight emit */
|
|
723
722
|
readonly signal?: AbortSignal;
|
|
724
723
|
/** Optional progress callback for observing source-resolution and emit spans */
|
package/src/migration-cli.ts
CHANGED
|
@@ -461,8 +461,8 @@ function writeStructuredError(stream: MigrationCliWritable, err: CliStructuredEr
|
|
|
461
461
|
* `null` when the file is missing and throwing `MIGRATION.INVALID_JSON`
|
|
462
462
|
* when the file is present but cannot be parsed as JSON. The CLI feeds
|
|
463
463
|
* this into `buildMigrationArtifacts` so the pure builder can preserve
|
|
464
|
-
* fields owned by `migration plan` (contract bookends,
|
|
465
|
-
*
|
|
464
|
+
* fields owned by `migration plan` (contract bookends, `createdAt`) across
|
|
465
|
+
* re-emits.
|
|
466
466
|
*
|
|
467
467
|
* Author-time path: this loader still does not verify the manifest hash
|
|
468
468
|
* or schema — that is the apply-time loader's job. Hash mismatch is the
|
|
@@ -472,8 +472,8 @@ function writeStructuredError(stream: MigrationCliWritable, err: CliStructuredEr
|
|
|
472
472
|
* however, is now surfaced rather than swallowed: a malformed
|
|
473
473
|
* `migration.json` indicates either a hand-edit gone wrong or partial
|
|
474
474
|
* write, and silently rebuilding from `describe()` would discard the
|
|
475
|
-
* user's on-disk content (preserved bookends,
|
|
476
|
-
*
|
|
475
|
+
* user's on-disk content (preserved bookends, `createdAt`) without any
|
|
476
|
+
* indication something was wrong on disk.
|
|
477
477
|
* Apply-time consumers always route through the verifying
|
|
478
478
|
* `readMigrationPackage` in `@prisma-next/migration-tools/io` instead.
|
|
479
479
|
*/
|