@prisma-next/cli 0.3.0-dev.3 → 0.3.0-dev.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -27
- package/dist/{chunk-BZMBKEEQ.js → chunk-AGOTG4L3.js} +44 -76
- package/dist/chunk-AGOTG4L3.js.map +1 -0
- package/dist/chunk-HLLI4YL7.js +180 -0
- package/dist/chunk-HLLI4YL7.js.map +1 -0
- package/dist/chunk-VG2R7DGF.js +735 -0
- package/dist/chunk-VG2R7DGF.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1502 -968
- package/dist/cli.js.map +1 -1
- package/dist/commands/contract-emit.d.ts +2 -4
- package/dist/commands/contract-emit.d.ts.map +1 -0
- package/dist/commands/contract-emit.js +3 -2
- package/dist/commands/db-init.d.ts +2 -4
- package/dist/commands/db-init.d.ts.map +1 -0
- package/dist/commands/db-init.js +205 -289
- package/dist/commands/db-init.js.map +1 -1
- package/dist/commands/db-introspect.d.ts +2 -4
- package/dist/commands/db-introspect.d.ts.map +1 -0
- package/dist/commands/db-introspect.js +108 -143
- package/dist/commands/db-introspect.js.map +1 -1
- package/dist/commands/db-schema-verify.d.ts +2 -4
- package/dist/commands/db-schema-verify.d.ts.map +1 -0
- package/dist/commands/db-schema-verify.js +120 -113
- package/dist/commands/db-schema-verify.js.map +1 -1
- package/dist/commands/db-sign.d.ts +2 -4
- package/dist/commands/db-sign.d.ts.map +1 -0
- package/dist/commands/db-sign.js +152 -156
- package/dist/commands/db-sign.js.map +1 -1
- package/dist/commands/db-verify.d.ts +2 -4
- package/dist/commands/db-verify.d.ts.map +1 -0
- package/dist/commands/db-verify.js +142 -122
- package/dist/commands/db-verify.js.map +1 -1
- package/dist/config-loader.d.ts +3 -5
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/control-api/client.d.ts +13 -0
- package/dist/control-api/client.d.ts.map +1 -0
- package/dist/control-api/operations/db-init.d.ts +29 -0
- package/dist/control-api/operations/db-init.d.ts.map +1 -0
- package/dist/control-api/types.d.ts +387 -0
- package/dist/control-api/types.d.ts.map +1 -0
- package/dist/exports/config-types.d.ts +3 -0
- package/dist/exports/config-types.d.ts.map +1 -0
- package/dist/exports/config-types.js.map +1 -0
- package/dist/exports/control-api.d.ts +13 -0
- package/dist/exports/control-api.d.ts.map +1 -0
- package/dist/exports/control-api.js +7 -0
- package/dist/exports/control-api.js.map +1 -0
- package/dist/exports/index.d.ts +4 -0
- package/dist/exports/index.d.ts.map +1 -0
- package/dist/{index.js → exports/index.js} +4 -3
- package/dist/exports/index.js.map +1 -0
- package/dist/{index.d.ts → load-ts-contract.d.ts} +4 -8
- package/dist/load-ts-contract.d.ts.map +1 -0
- package/dist/utils/cli-errors.d.ts +7 -0
- package/dist/utils/cli-errors.d.ts.map +1 -0
- package/dist/utils/command-helpers.d.ts +12 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/framework-components.d.ts +70 -0
- package/dist/utils/framework-components.d.ts.map +1 -0
- package/dist/utils/global-flags.d.ts +25 -0
- package/dist/utils/global-flags.d.ts.map +1 -0
- package/dist/utils/output.d.ts +142 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/progress-adapter.d.ts +26 -0
- package/dist/utils/progress-adapter.d.ts.map +1 -0
- package/dist/utils/result-handler.d.ts +15 -0
- package/dist/utils/result-handler.d.ts.map +1 -0
- package/package.json +30 -26
- package/src/cli.ts +260 -0
- package/src/commands/contract-emit.ts +259 -0
- package/src/commands/db-init.ts +360 -0
- package/src/commands/db-introspect.ts +227 -0
- package/src/commands/db-schema-verify.ts +238 -0
- package/src/commands/db-sign.ts +279 -0
- package/src/commands/db-verify.ts +258 -0
- package/src/config-loader.ts +76 -0
- package/src/control-api/client.ts +589 -0
- package/src/control-api/operations/db-init.ts +281 -0
- package/src/control-api/types.ts +461 -0
- package/src/exports/config-types.ts +6 -0
- package/src/exports/control-api.ts +46 -0
- package/src/exports/index.ts +4 -0
- package/src/load-ts-contract.ts +217 -0
- package/src/utils/cli-errors.ts +26 -0
- package/src/utils/command-helpers.ts +26 -0
- package/src/utils/framework-components.ts +177 -0
- package/src/utils/global-flags.ts +75 -0
- package/src/utils/output.ts +1471 -0
- package/src/utils/progress-adapter.ts +86 -0
- package/src/utils/result-handler.ts +44 -0
- package/dist/chunk-464LNZCE.js +0 -134
- package/dist/chunk-464LNZCE.js.map +0 -1
- package/dist/chunk-BZMBKEEQ.js.map +0 -1
- package/dist/chunk-ZKYEJROM.js +0 -94
- package/dist/chunk-ZKYEJROM.js.map +0 -1
- package/dist/config-types.d.ts +0 -1
- package/dist/config-types.js.map +0 -1
- package/dist/index.js.map +0 -1
- /package/dist/{config-types.js → exports/config-types.js} +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
|
|
2
|
+
import type { ContractIR } from '@prisma-next/contract/ir';
|
|
3
|
+
import type {
|
|
4
|
+
ControlDriverInstance,
|
|
5
|
+
ControlFamilyInstance,
|
|
6
|
+
MigrationPlan,
|
|
7
|
+
MigrationPlannerResult,
|
|
8
|
+
MigrationPlanOperation,
|
|
9
|
+
MigrationRunnerResult,
|
|
10
|
+
TargetMigrationsCapability,
|
|
11
|
+
} from '@prisma-next/core-control-plane/types';
|
|
12
|
+
import { notOk, ok } from '@prisma-next/utils/result';
|
|
13
|
+
import type { DbInitResult, DbInitSuccess, OnControlProgress } from '../types';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Options for executing dbInit operation.
|
|
17
|
+
*/
|
|
18
|
+
export interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {
|
|
19
|
+
readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
|
|
20
|
+
readonly familyInstance: ControlFamilyInstance<TFamilyId>;
|
|
21
|
+
readonly contractIR: ContractIR;
|
|
22
|
+
readonly mode: 'plan' | 'apply';
|
|
23
|
+
readonly migrations: TargetMigrationsCapability<
|
|
24
|
+
TFamilyId,
|
|
25
|
+
TTargetId,
|
|
26
|
+
ControlFamilyInstance<TFamilyId>
|
|
27
|
+
>;
|
|
28
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
|
|
29
|
+
/** Optional progress callback for observing operation progress */
|
|
30
|
+
readonly onProgress?: OnControlProgress;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Executes the dbInit operation.
|
|
35
|
+
*
|
|
36
|
+
* This is the core logic extracted from the CLI command, without any file I/O,
|
|
37
|
+
* process.exit(), or console output. It uses the Result pattern to return
|
|
38
|
+
* success or failure details.
|
|
39
|
+
*
|
|
40
|
+
* @param options - The options for executing dbInit
|
|
41
|
+
* @returns Result with DbInitSuccess on success, DbInitFailure on failure
|
|
42
|
+
*/
|
|
43
|
+
export async function executeDbInit<TFamilyId extends string, TTargetId extends string>(
|
|
44
|
+
options: ExecuteDbInitOptions<TFamilyId, TTargetId>,
|
|
45
|
+
): Promise<DbInitResult> {
|
|
46
|
+
const { driver, familyInstance, contractIR, mode, migrations, frameworkComponents, onProgress } =
|
|
47
|
+
options;
|
|
48
|
+
|
|
49
|
+
// Create planner and runner from target migrations capability
|
|
50
|
+
const planner = migrations.createPlanner(familyInstance);
|
|
51
|
+
const runner = migrations.createRunner(familyInstance);
|
|
52
|
+
|
|
53
|
+
// Introspect live schema
|
|
54
|
+
const introspectSpanId = 'introspect';
|
|
55
|
+
onProgress?.({
|
|
56
|
+
action: 'dbInit',
|
|
57
|
+
kind: 'spanStart',
|
|
58
|
+
spanId: introspectSpanId,
|
|
59
|
+
label: 'Introspecting database schema',
|
|
60
|
+
});
|
|
61
|
+
const schemaIR = await familyInstance.introspect({ driver });
|
|
62
|
+
onProgress?.({
|
|
63
|
+
action: 'dbInit',
|
|
64
|
+
kind: 'spanEnd',
|
|
65
|
+
spanId: introspectSpanId,
|
|
66
|
+
outcome: 'ok',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Policy for init mode (additive only)
|
|
70
|
+
const policy = { allowedOperationClasses: ['additive'] as const };
|
|
71
|
+
|
|
72
|
+
// Plan migration
|
|
73
|
+
const planSpanId = 'plan';
|
|
74
|
+
onProgress?.({
|
|
75
|
+
action: 'dbInit',
|
|
76
|
+
kind: 'spanStart',
|
|
77
|
+
spanId: planSpanId,
|
|
78
|
+
label: 'Planning migration',
|
|
79
|
+
});
|
|
80
|
+
const plannerResult: MigrationPlannerResult = await planner.plan({
|
|
81
|
+
contract: contractIR,
|
|
82
|
+
schema: schemaIR,
|
|
83
|
+
policy,
|
|
84
|
+
frameworkComponents,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (plannerResult.kind === 'failure') {
|
|
88
|
+
onProgress?.({
|
|
89
|
+
action: 'dbInit',
|
|
90
|
+
kind: 'spanEnd',
|
|
91
|
+
spanId: planSpanId,
|
|
92
|
+
outcome: 'error',
|
|
93
|
+
});
|
|
94
|
+
return notOk({
|
|
95
|
+
code: 'PLANNING_FAILED' as const,
|
|
96
|
+
summary: 'Migration planning failed due to conflicts',
|
|
97
|
+
conflicts: plannerResult.conflicts,
|
|
98
|
+
why: undefined,
|
|
99
|
+
meta: undefined,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const migrationPlan: MigrationPlan = plannerResult.plan;
|
|
104
|
+
onProgress?.({
|
|
105
|
+
action: 'dbInit',
|
|
106
|
+
kind: 'spanEnd',
|
|
107
|
+
spanId: planSpanId,
|
|
108
|
+
outcome: 'ok',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Check for existing marker - handle idempotency and mismatch errors
|
|
112
|
+
const checkMarkerSpanId = 'checkMarker';
|
|
113
|
+
onProgress?.({
|
|
114
|
+
action: 'dbInit',
|
|
115
|
+
kind: 'spanStart',
|
|
116
|
+
spanId: checkMarkerSpanId,
|
|
117
|
+
label: 'Checking contract marker',
|
|
118
|
+
});
|
|
119
|
+
const existingMarker = await familyInstance.readMarker({ driver });
|
|
120
|
+
if (existingMarker) {
|
|
121
|
+
const markerMatchesDestination =
|
|
122
|
+
existingMarker.coreHash === migrationPlan.destination.coreHash &&
|
|
123
|
+
(!migrationPlan.destination.profileHash ||
|
|
124
|
+
existingMarker.profileHash === migrationPlan.destination.profileHash);
|
|
125
|
+
|
|
126
|
+
if (markerMatchesDestination) {
|
|
127
|
+
// Already at destination - return success with no operations
|
|
128
|
+
onProgress?.({
|
|
129
|
+
action: 'dbInit',
|
|
130
|
+
kind: 'spanEnd',
|
|
131
|
+
spanId: checkMarkerSpanId,
|
|
132
|
+
outcome: 'skipped',
|
|
133
|
+
});
|
|
134
|
+
const result: DbInitSuccess = {
|
|
135
|
+
mode,
|
|
136
|
+
plan: { operations: [] },
|
|
137
|
+
...(mode === 'apply'
|
|
138
|
+
? {
|
|
139
|
+
execution: { operationsPlanned: 0, operationsExecuted: 0 },
|
|
140
|
+
marker: {
|
|
141
|
+
coreHash: existingMarker.coreHash,
|
|
142
|
+
profileHash: existingMarker.profileHash,
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
: {}),
|
|
146
|
+
summary: 'Database already at target contract state',
|
|
147
|
+
};
|
|
148
|
+
return ok(result);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Marker exists but doesn't match destination - fail
|
|
152
|
+
onProgress?.({
|
|
153
|
+
action: 'dbInit',
|
|
154
|
+
kind: 'spanEnd',
|
|
155
|
+
spanId: checkMarkerSpanId,
|
|
156
|
+
outcome: 'error',
|
|
157
|
+
});
|
|
158
|
+
return notOk({
|
|
159
|
+
code: 'MARKER_ORIGIN_MISMATCH' as const,
|
|
160
|
+
summary: 'Existing contract marker does not match plan destination',
|
|
161
|
+
marker: {
|
|
162
|
+
coreHash: existingMarker.coreHash,
|
|
163
|
+
profileHash: existingMarker.profileHash,
|
|
164
|
+
},
|
|
165
|
+
destination: {
|
|
166
|
+
coreHash: migrationPlan.destination.coreHash,
|
|
167
|
+
profileHash: migrationPlan.destination.profileHash,
|
|
168
|
+
},
|
|
169
|
+
why: undefined,
|
|
170
|
+
conflicts: undefined,
|
|
171
|
+
meta: undefined,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
onProgress?.({
|
|
176
|
+
action: 'dbInit',
|
|
177
|
+
kind: 'spanEnd',
|
|
178
|
+
spanId: checkMarkerSpanId,
|
|
179
|
+
outcome: 'ok',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Plan mode - don't execute
|
|
183
|
+
if (mode === 'plan') {
|
|
184
|
+
const result: DbInitSuccess = {
|
|
185
|
+
mode: 'plan',
|
|
186
|
+
plan: { operations: migrationPlan.operations },
|
|
187
|
+
summary: `Planned ${migrationPlan.operations.length} operation(s)`,
|
|
188
|
+
};
|
|
189
|
+
return ok(result);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Apply mode - execute runner
|
|
193
|
+
const applySpanId = 'apply';
|
|
194
|
+
onProgress?.({
|
|
195
|
+
action: 'dbInit',
|
|
196
|
+
kind: 'spanStart',
|
|
197
|
+
spanId: applySpanId,
|
|
198
|
+
label: 'Applying migration plan',
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const callbacks = onProgress
|
|
202
|
+
? {
|
|
203
|
+
onOperationStart: (op: MigrationPlanOperation) => {
|
|
204
|
+
onProgress({
|
|
205
|
+
action: 'dbInit',
|
|
206
|
+
kind: 'spanStart',
|
|
207
|
+
spanId: `operation:${op.id}`,
|
|
208
|
+
parentSpanId: applySpanId,
|
|
209
|
+
label: op.label,
|
|
210
|
+
});
|
|
211
|
+
},
|
|
212
|
+
onOperationComplete: (op: MigrationPlanOperation) => {
|
|
213
|
+
onProgress({
|
|
214
|
+
action: 'dbInit',
|
|
215
|
+
kind: 'spanEnd',
|
|
216
|
+
spanId: `operation:${op.id}`,
|
|
217
|
+
outcome: 'ok',
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
: undefined;
|
|
222
|
+
|
|
223
|
+
const runnerResult: MigrationRunnerResult = await runner.execute({
|
|
224
|
+
plan: migrationPlan,
|
|
225
|
+
driver,
|
|
226
|
+
destinationContract: contractIR,
|
|
227
|
+
policy,
|
|
228
|
+
...(callbacks ? { callbacks } : {}),
|
|
229
|
+
// db init plans and applies back-to-back from a fresh introspection, so per-operation
|
|
230
|
+
// pre/postchecks and the idempotency probe are usually redundant overhead. We still
|
|
231
|
+
// enforce marker/origin compatibility and a full schema verification after apply.
|
|
232
|
+
executionChecks: {
|
|
233
|
+
prechecks: false,
|
|
234
|
+
postchecks: false,
|
|
235
|
+
idempotencyChecks: false,
|
|
236
|
+
},
|
|
237
|
+
frameworkComponents,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
if (!runnerResult.ok) {
|
|
241
|
+
onProgress?.({
|
|
242
|
+
action: 'dbInit',
|
|
243
|
+
kind: 'spanEnd',
|
|
244
|
+
spanId: applySpanId,
|
|
245
|
+
outcome: 'error',
|
|
246
|
+
});
|
|
247
|
+
return notOk({
|
|
248
|
+
code: 'RUNNER_FAILED' as const,
|
|
249
|
+
summary: runnerResult.failure.summary,
|
|
250
|
+
why: runnerResult.failure.why,
|
|
251
|
+
meta: runnerResult.failure.meta,
|
|
252
|
+
conflicts: undefined,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const execution = runnerResult.value;
|
|
257
|
+
|
|
258
|
+
onProgress?.({
|
|
259
|
+
action: 'dbInit',
|
|
260
|
+
kind: 'spanEnd',
|
|
261
|
+
spanId: applySpanId,
|
|
262
|
+
outcome: 'ok',
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const result: DbInitSuccess = {
|
|
266
|
+
mode: 'apply',
|
|
267
|
+
plan: { operations: migrationPlan.operations },
|
|
268
|
+
execution: {
|
|
269
|
+
operationsPlanned: execution.operationsPlanned,
|
|
270
|
+
operationsExecuted: execution.operationsExecuted,
|
|
271
|
+
},
|
|
272
|
+
marker: migrationPlan.destination.profileHash
|
|
273
|
+
? {
|
|
274
|
+
coreHash: migrationPlan.destination.coreHash,
|
|
275
|
+
profileHash: migrationPlan.destination.profileHash,
|
|
276
|
+
}
|
|
277
|
+
: { coreHash: migrationPlan.destination.coreHash },
|
|
278
|
+
summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,
|
|
279
|
+
};
|
|
280
|
+
return ok(result);
|
|
281
|
+
}
|