@prisma-next/cli 0.3.0-dev.17 → 0.3.0-dev.19
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/dist/{chunk-ZG5T6OB5.js → chunk-AGOTG4L3.js} +43 -1
- 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.js +1621 -1382
- package/dist/cli.js.map +1 -1
- package/dist/commands/contract-emit.d.ts.map +1 -1
- package/dist/commands/contract-emit.js +3 -4
- package/dist/commands/db-init.js +4 -49
- package/dist/commands/db-init.js.map +1 -1
- package/dist/commands/db-introspect.d.ts.map +1 -1
- package/dist/commands/db-introspect.js +106 -136
- package/dist/commands/db-introspect.js.map +1 -1
- package/dist/commands/db-schema-verify.d.ts.map +1 -1
- package/dist/commands/db-schema-verify.js +118 -110
- package/dist/commands/db-schema-verify.js.map +1 -1
- package/dist/commands/db-sign.d.ts.map +1 -1
- package/dist/commands/db-sign.js +150 -153
- package/dist/commands/db-sign.js.map +1 -1
- package/dist/commands/db-verify.d.ts.map +1 -1
- package/dist/commands/db-verify.js +140 -119
- package/dist/commands/db-verify.js.map +1 -1
- package/dist/control-api/client.d.ts.map +1 -1
- package/dist/control-api/types.d.ts +132 -1
- package/dist/control-api/types.d.ts.map +1 -1
- package/dist/exports/control-api.d.ts +1 -1
- package/dist/exports/control-api.d.ts.map +1 -1
- package/dist/exports/control-api.js +1 -3
- package/dist/exports/index.js +3 -4
- package/dist/exports/index.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/contract-emit.ts +179 -102
- package/src/commands/db-introspect.ts +151 -178
- package/src/commands/db-schema-verify.ts +150 -143
- package/src/commands/db-sign.ts +202 -196
- package/src/commands/db-verify.ts +179 -149
- package/src/control-api/client.ts +352 -22
- package/src/control-api/types.ts +149 -1
- package/src/exports/control-api.ts +9 -0
- package/dist/chunk-5MPKZYVI.js +0 -47
- package/dist/chunk-5MPKZYVI.js.map +0 -1
- package/dist/chunk-6EPKRATC.js +0 -91
- package/dist/chunk-6EPKRATC.js.map +0 -1
- package/dist/chunk-74IELXRA.js +0 -371
- package/dist/chunk-74IELXRA.js.map +0 -1
- package/dist/chunk-U6QI3AZ3.js +0 -133
- package/dist/chunk-U6QI3AZ3.js.map +0 -1
- package/dist/chunk-VI2YETW7.js +0 -38
- package/dist/chunk-VI2YETW7.js.map +0 -1
- package/dist/chunk-ZG5T6OB5.js.map +0 -1
- package/dist/utils/action.d.ts +0 -16
- package/dist/utils/action.d.ts.map +0 -1
- package/dist/utils/spinner.d.ts +0 -29
- package/dist/utils/spinner.d.ts.map +0 -1
- package/src/utils/action.ts +0 -43
- package/src/utils/spinner.ts +0 -67
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
|
|
2
|
+
import type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';
|
|
2
3
|
import { createControlPlaneStack } from '@prisma-next/core-control-plane/stack';
|
|
3
4
|
import type {
|
|
4
5
|
ControlDriverInstance,
|
|
@@ -8,6 +9,7 @@ import type {
|
|
|
8
9
|
VerifyDatabaseResult,
|
|
9
10
|
VerifyDatabaseSchemaResult,
|
|
10
11
|
} from '@prisma-next/core-control-plane/types';
|
|
12
|
+
import { notOk, ok } from '@prisma-next/utils/result';
|
|
11
13
|
import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
|
|
12
14
|
import { executeDbInit } from './operations/db-init';
|
|
13
15
|
import type {
|
|
@@ -15,6 +17,8 @@ import type {
|
|
|
15
17
|
ControlClientOptions,
|
|
16
18
|
DbInitOptions,
|
|
17
19
|
DbInitResult,
|
|
20
|
+
EmitOptions,
|
|
21
|
+
EmitResult,
|
|
18
22
|
IntrospectOptions,
|
|
19
23
|
SchemaVerifyOptions,
|
|
20
24
|
SignOptions,
|
|
@@ -148,51 +152,220 @@ class ControlClientImpl implements ControlClient {
|
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
async verify(options: VerifyOptions): Promise<VerifyDatabaseResult> {
|
|
155
|
+
const { onProgress } = options;
|
|
156
|
+
|
|
157
|
+
// Connect with progress span if connection provided
|
|
158
|
+
if (options.connection !== undefined) {
|
|
159
|
+
onProgress?.({
|
|
160
|
+
action: 'verify',
|
|
161
|
+
kind: 'spanStart',
|
|
162
|
+
spanId: 'connect',
|
|
163
|
+
label: 'Connecting to database...',
|
|
164
|
+
});
|
|
165
|
+
try {
|
|
166
|
+
await this.connect(options.connection);
|
|
167
|
+
onProgress?.({
|
|
168
|
+
action: 'verify',
|
|
169
|
+
kind: 'spanEnd',
|
|
170
|
+
spanId: 'connect',
|
|
171
|
+
outcome: 'ok',
|
|
172
|
+
});
|
|
173
|
+
} catch (error) {
|
|
174
|
+
onProgress?.({
|
|
175
|
+
action: 'verify',
|
|
176
|
+
kind: 'spanEnd',
|
|
177
|
+
spanId: 'connect',
|
|
178
|
+
outcome: 'error',
|
|
179
|
+
});
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
151
184
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
152
185
|
|
|
153
186
|
// Validate contract using family instance
|
|
154
187
|
const contractIR = familyInstance.validateContractIR(options.contractIR);
|
|
155
188
|
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
contractIR,
|
|
163
|
-
expectedTargetId: this.options.target.targetId,
|
|
164
|
-
contractPath: '',
|
|
189
|
+
// Emit verify span
|
|
190
|
+
onProgress?.({
|
|
191
|
+
action: 'verify',
|
|
192
|
+
kind: 'spanStart',
|
|
193
|
+
spanId: 'verify',
|
|
194
|
+
label: 'Verifying contract marker...',
|
|
165
195
|
});
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
// Delegate to family instance verify method
|
|
199
|
+
// Note: We pass empty strings for contractPath/configPath since the programmatic
|
|
200
|
+
// API doesn't deal with file paths. The family instance accepts these as optional
|
|
201
|
+
// metadata for error reporting.
|
|
202
|
+
const result = await familyInstance.verify({
|
|
203
|
+
driver,
|
|
204
|
+
contractIR,
|
|
205
|
+
expectedTargetId: this.options.target.targetId,
|
|
206
|
+
contractPath: '',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
onProgress?.({
|
|
210
|
+
action: 'verify',
|
|
211
|
+
kind: 'spanEnd',
|
|
212
|
+
spanId: 'verify',
|
|
213
|
+
outcome: result.ok ? 'ok' : 'error',
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
return result;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
onProgress?.({
|
|
219
|
+
action: 'verify',
|
|
220
|
+
kind: 'spanEnd',
|
|
221
|
+
spanId: 'verify',
|
|
222
|
+
outcome: 'error',
|
|
223
|
+
});
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
166
226
|
}
|
|
167
227
|
|
|
168
228
|
async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {
|
|
229
|
+
const { onProgress } = options;
|
|
230
|
+
|
|
231
|
+
// Connect with progress span if connection provided
|
|
232
|
+
if (options.connection !== undefined) {
|
|
233
|
+
onProgress?.({
|
|
234
|
+
action: 'schemaVerify',
|
|
235
|
+
kind: 'spanStart',
|
|
236
|
+
spanId: 'connect',
|
|
237
|
+
label: 'Connecting to database...',
|
|
238
|
+
});
|
|
239
|
+
try {
|
|
240
|
+
await this.connect(options.connection);
|
|
241
|
+
onProgress?.({
|
|
242
|
+
action: 'schemaVerify',
|
|
243
|
+
kind: 'spanEnd',
|
|
244
|
+
spanId: 'connect',
|
|
245
|
+
outcome: 'ok',
|
|
246
|
+
});
|
|
247
|
+
} catch (error) {
|
|
248
|
+
onProgress?.({
|
|
249
|
+
action: 'schemaVerify',
|
|
250
|
+
kind: 'spanEnd',
|
|
251
|
+
spanId: 'connect',
|
|
252
|
+
outcome: 'error',
|
|
253
|
+
});
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
169
258
|
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
170
259
|
|
|
171
260
|
// Validate contract using family instance
|
|
172
261
|
const contractIR = familyInstance.validateContractIR(options.contractIR);
|
|
173
262
|
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
frameworkComponents,
|
|
263
|
+
// Emit schemaVerify span
|
|
264
|
+
onProgress?.({
|
|
265
|
+
action: 'schemaVerify',
|
|
266
|
+
kind: 'spanStart',
|
|
267
|
+
spanId: 'schemaVerify',
|
|
268
|
+
label: 'Verifying database schema...',
|
|
181
269
|
});
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
// Delegate to family instance schemaVerify method
|
|
273
|
+
const result = await familyInstance.schemaVerify({
|
|
274
|
+
driver,
|
|
275
|
+
contractIR,
|
|
276
|
+
strict: options.strict ?? false,
|
|
277
|
+
contractPath: '',
|
|
278
|
+
frameworkComponents,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
onProgress?.({
|
|
282
|
+
action: 'schemaVerify',
|
|
283
|
+
kind: 'spanEnd',
|
|
284
|
+
spanId: 'schemaVerify',
|
|
285
|
+
outcome: result.ok ? 'ok' : 'error',
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return result;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
onProgress?.({
|
|
291
|
+
action: 'schemaVerify',
|
|
292
|
+
kind: 'spanEnd',
|
|
293
|
+
spanId: 'schemaVerify',
|
|
294
|
+
outcome: 'error',
|
|
295
|
+
});
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
182
298
|
}
|
|
183
299
|
|
|
184
300
|
async sign(options: SignOptions): Promise<SignDatabaseResult> {
|
|
301
|
+
const { onProgress } = options;
|
|
302
|
+
|
|
303
|
+
// Connect with progress span if connection provided
|
|
304
|
+
if (options.connection !== undefined) {
|
|
305
|
+
onProgress?.({
|
|
306
|
+
action: 'sign',
|
|
307
|
+
kind: 'spanStart',
|
|
308
|
+
spanId: 'connect',
|
|
309
|
+
label: 'Connecting to database...',
|
|
310
|
+
});
|
|
311
|
+
try {
|
|
312
|
+
await this.connect(options.connection);
|
|
313
|
+
onProgress?.({
|
|
314
|
+
action: 'sign',
|
|
315
|
+
kind: 'spanEnd',
|
|
316
|
+
spanId: 'connect',
|
|
317
|
+
outcome: 'ok',
|
|
318
|
+
});
|
|
319
|
+
} catch (error) {
|
|
320
|
+
onProgress?.({
|
|
321
|
+
action: 'sign',
|
|
322
|
+
kind: 'spanEnd',
|
|
323
|
+
spanId: 'connect',
|
|
324
|
+
outcome: 'error',
|
|
325
|
+
});
|
|
326
|
+
throw error;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
185
330
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
186
331
|
|
|
187
332
|
// Validate contract using family instance
|
|
188
333
|
const contractIR = familyInstance.validateContractIR(options.contractIR);
|
|
189
334
|
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
335
|
+
// Emit sign span
|
|
336
|
+
onProgress?.({
|
|
337
|
+
action: 'sign',
|
|
338
|
+
kind: 'spanStart',
|
|
339
|
+
spanId: 'sign',
|
|
340
|
+
label: 'Signing database...',
|
|
195
341
|
});
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
// Delegate to family instance sign method
|
|
345
|
+
const result = await familyInstance.sign({
|
|
346
|
+
driver,
|
|
347
|
+
contractIR,
|
|
348
|
+
contractPath: options.contractPath ?? '',
|
|
349
|
+
...(options.configPath ? { configPath: options.configPath } : {}),
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
onProgress?.({
|
|
353
|
+
action: 'sign',
|
|
354
|
+
kind: 'spanEnd',
|
|
355
|
+
spanId: 'sign',
|
|
356
|
+
outcome: 'ok',
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
return result;
|
|
360
|
+
} catch (error) {
|
|
361
|
+
onProgress?.({
|
|
362
|
+
action: 'sign',
|
|
363
|
+
kind: 'spanEnd',
|
|
364
|
+
spanId: 'sign',
|
|
365
|
+
outcome: 'error',
|
|
366
|
+
});
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
196
369
|
}
|
|
197
370
|
|
|
198
371
|
async dbInit(options: DbInitOptions): Promise<DbInitResult> {
|
|
@@ -248,12 +421,169 @@ class ControlClientImpl implements ControlClient {
|
|
|
248
421
|
}
|
|
249
422
|
|
|
250
423
|
async introspect(options?: IntrospectOptions): Promise<unknown> {
|
|
424
|
+
const onProgress = options?.onProgress;
|
|
425
|
+
|
|
426
|
+
// Connect with progress span if connection provided
|
|
427
|
+
if (options?.connection !== undefined) {
|
|
428
|
+
onProgress?.({
|
|
429
|
+
action: 'introspect',
|
|
430
|
+
kind: 'spanStart',
|
|
431
|
+
spanId: 'connect',
|
|
432
|
+
label: 'Connecting to database...',
|
|
433
|
+
});
|
|
434
|
+
try {
|
|
435
|
+
await this.connect(options.connection);
|
|
436
|
+
onProgress?.({
|
|
437
|
+
action: 'introspect',
|
|
438
|
+
kind: 'spanEnd',
|
|
439
|
+
spanId: 'connect',
|
|
440
|
+
outcome: 'ok',
|
|
441
|
+
});
|
|
442
|
+
} catch (error) {
|
|
443
|
+
onProgress?.({
|
|
444
|
+
action: 'introspect',
|
|
445
|
+
kind: 'spanEnd',
|
|
446
|
+
spanId: 'connect',
|
|
447
|
+
outcome: 'error',
|
|
448
|
+
});
|
|
449
|
+
throw error;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
251
453
|
const { driver, familyInstance } = await this.ensureConnected();
|
|
252
454
|
|
|
253
455
|
// TODO: Pass schema option to familyInstance.introspect when schema filtering is implemented
|
|
254
456
|
const _schema = options?.schema;
|
|
255
457
|
void _schema;
|
|
256
458
|
|
|
257
|
-
|
|
459
|
+
// Emit introspect span
|
|
460
|
+
onProgress?.({
|
|
461
|
+
action: 'introspect',
|
|
462
|
+
kind: 'spanStart',
|
|
463
|
+
spanId: 'introspect',
|
|
464
|
+
label: 'Introspecting database schema...',
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
const result = await familyInstance.introspect({ driver });
|
|
469
|
+
|
|
470
|
+
onProgress?.({
|
|
471
|
+
action: 'introspect',
|
|
472
|
+
kind: 'spanEnd',
|
|
473
|
+
spanId: 'introspect',
|
|
474
|
+
outcome: 'ok',
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
return result;
|
|
478
|
+
} catch (error) {
|
|
479
|
+
onProgress?.({
|
|
480
|
+
action: 'introspect',
|
|
481
|
+
kind: 'spanEnd',
|
|
482
|
+
spanId: 'introspect',
|
|
483
|
+
outcome: 'error',
|
|
484
|
+
});
|
|
485
|
+
throw error;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
toSchemaView(schemaIR: unknown): CoreSchemaView | undefined {
|
|
490
|
+
this.init();
|
|
491
|
+
if (this.familyInstance?.toSchemaView) {
|
|
492
|
+
return this.familyInstance.toSchemaView(schemaIR);
|
|
493
|
+
}
|
|
494
|
+
return undefined;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
async emit(options: EmitOptions): Promise<EmitResult> {
|
|
498
|
+
const { onProgress, contractConfig } = options;
|
|
499
|
+
|
|
500
|
+
// Ensure initialized (creates stack and family instance)
|
|
501
|
+
// emit() does NOT require a database connection
|
|
502
|
+
this.init();
|
|
503
|
+
|
|
504
|
+
if (!this.familyInstance) {
|
|
505
|
+
throw new Error('Family instance was not initialized. This is a bug.');
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Resolve contract source
|
|
509
|
+
let contractRaw: unknown;
|
|
510
|
+
onProgress?.({
|
|
511
|
+
action: 'emit',
|
|
512
|
+
kind: 'spanStart',
|
|
513
|
+
spanId: 'resolveSource',
|
|
514
|
+
label: 'Resolving contract source...',
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
try {
|
|
518
|
+
switch (contractConfig.source.kind) {
|
|
519
|
+
case 'loader':
|
|
520
|
+
contractRaw = await contractConfig.source.load();
|
|
521
|
+
break;
|
|
522
|
+
case 'value':
|
|
523
|
+
contractRaw = contractConfig.source.value;
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
onProgress?.({
|
|
528
|
+
action: 'emit',
|
|
529
|
+
kind: 'spanEnd',
|
|
530
|
+
spanId: 'resolveSource',
|
|
531
|
+
outcome: 'ok',
|
|
532
|
+
});
|
|
533
|
+
} catch (error) {
|
|
534
|
+
onProgress?.({
|
|
535
|
+
action: 'emit',
|
|
536
|
+
kind: 'spanEnd',
|
|
537
|
+
spanId: 'resolveSource',
|
|
538
|
+
outcome: 'error',
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
return notOk({
|
|
542
|
+
code: 'CONTRACT_SOURCE_INVALID',
|
|
543
|
+
summary: 'Failed to resolve contract source',
|
|
544
|
+
why: error instanceof Error ? error.message : String(error),
|
|
545
|
+
meta: undefined,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Emit contract
|
|
550
|
+
onProgress?.({
|
|
551
|
+
action: 'emit',
|
|
552
|
+
kind: 'spanStart',
|
|
553
|
+
spanId: 'emit',
|
|
554
|
+
label: 'Emitting contract...',
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
try {
|
|
558
|
+
const emitResult = await this.familyInstance.emitContract({ contractIR: contractRaw });
|
|
559
|
+
|
|
560
|
+
onProgress?.({
|
|
561
|
+
action: 'emit',
|
|
562
|
+
kind: 'spanEnd',
|
|
563
|
+
spanId: 'emit',
|
|
564
|
+
outcome: 'ok',
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
return ok({
|
|
568
|
+
coreHash: emitResult.coreHash,
|
|
569
|
+
profileHash: emitResult.profileHash,
|
|
570
|
+
contractJson: emitResult.contractJson,
|
|
571
|
+
contractDts: emitResult.contractDts,
|
|
572
|
+
});
|
|
573
|
+
} catch (error) {
|
|
574
|
+
onProgress?.({
|
|
575
|
+
action: 'emit',
|
|
576
|
+
kind: 'spanEnd',
|
|
577
|
+
spanId: 'emit',
|
|
578
|
+
outcome: 'error',
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
return notOk({
|
|
582
|
+
code: 'EMIT_FAILED',
|
|
583
|
+
summary: 'Failed to emit contract',
|
|
584
|
+
why: error instanceof Error ? error.message : String(error),
|
|
585
|
+
meta: undefined,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
258
588
|
}
|
|
259
589
|
}
|
package/src/control-api/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';
|
|
1
2
|
import type {
|
|
2
3
|
ControlAdapterDescriptor,
|
|
3
4
|
ControlDriverDescriptor,
|
|
@@ -53,7 +54,13 @@ export interface ControlClientOptions {
|
|
|
53
54
|
/**
|
|
54
55
|
* Action names for control-api operations that can emit progress events.
|
|
55
56
|
*/
|
|
56
|
-
export type ControlActionName =
|
|
57
|
+
export type ControlActionName =
|
|
58
|
+
| 'dbInit'
|
|
59
|
+
| 'verify'
|
|
60
|
+
| 'schemaVerify'
|
|
61
|
+
| 'sign'
|
|
62
|
+
| 'introspect'
|
|
63
|
+
| 'emit';
|
|
57
64
|
|
|
58
65
|
/**
|
|
59
66
|
* Progress event emitted during control-api operation execution.
|
|
@@ -100,6 +107,12 @@ export type OnControlProgress = (event: ControlProgressEvent) => void;
|
|
|
100
107
|
export interface VerifyOptions {
|
|
101
108
|
/** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
|
|
102
109
|
readonly contractIR: unknown;
|
|
110
|
+
/**
|
|
111
|
+
* Database connection. If provided, verify will connect before executing.
|
|
112
|
+
* If omitted, the client must already be connected.
|
|
113
|
+
* The type is driver-specific (e.g., string URL for Postgres).
|
|
114
|
+
*/
|
|
115
|
+
readonly connection?: unknown;
|
|
103
116
|
/** Optional progress callback for observing operation progress */
|
|
104
117
|
readonly onProgress?: OnControlProgress;
|
|
105
118
|
}
|
|
@@ -116,6 +129,12 @@ export interface SchemaVerifyOptions {
|
|
|
116
129
|
* Default: false (tolerant mode - allows superset)
|
|
117
130
|
*/
|
|
118
131
|
readonly strict?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Database connection. If provided, schemaVerify will connect before executing.
|
|
134
|
+
* If omitted, the client must already be connected.
|
|
135
|
+
* The type is driver-specific (e.g., string URL for Postgres).
|
|
136
|
+
*/
|
|
137
|
+
readonly connection?: unknown;
|
|
119
138
|
/** Optional progress callback for observing operation progress */
|
|
120
139
|
readonly onProgress?: OnControlProgress;
|
|
121
140
|
}
|
|
@@ -126,6 +145,20 @@ export interface SchemaVerifyOptions {
|
|
|
126
145
|
export interface SignOptions {
|
|
127
146
|
/** Contract IR or unvalidated JSON - validated at runtime via familyInstance.validateContractIR() */
|
|
128
147
|
readonly contractIR: unknown;
|
|
148
|
+
/**
|
|
149
|
+
* Path to the contract file (for metadata in the result).
|
|
150
|
+
*/
|
|
151
|
+
readonly contractPath?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Path to the config file (for metadata in the result).
|
|
154
|
+
*/
|
|
155
|
+
readonly configPath?: string;
|
|
156
|
+
/**
|
|
157
|
+
* Database connection. If provided, sign will connect before executing.
|
|
158
|
+
* If omitted, the client must already be connected.
|
|
159
|
+
* The type is driver-specific (e.g., string URL for Postgres).
|
|
160
|
+
*/
|
|
161
|
+
readonly connection?: unknown;
|
|
129
162
|
/** Optional progress callback for observing operation progress */
|
|
130
163
|
readonly onProgress?: OnControlProgress;
|
|
131
164
|
}
|
|
@@ -160,6 +193,67 @@ export interface IntrospectOptions {
|
|
|
160
193
|
* Optional schema name to introspect.
|
|
161
194
|
*/
|
|
162
195
|
readonly schema?: string;
|
|
196
|
+
/**
|
|
197
|
+
* Database connection. If provided, introspect will connect before executing.
|
|
198
|
+
* If omitted, the client must already be connected.
|
|
199
|
+
* The type is driver-specific (e.g., string URL for Postgres).
|
|
200
|
+
*/
|
|
201
|
+
readonly connection?: unknown;
|
|
202
|
+
/** Optional progress callback for observing operation progress */
|
|
203
|
+
readonly onProgress?: OnControlProgress;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Contract source as a raw value (any JSON-serializable value).
|
|
208
|
+
*/
|
|
209
|
+
export interface ContractSourceValue {
|
|
210
|
+
readonly kind: 'value';
|
|
211
|
+
readonly value: unknown;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Contract source as a lazy loader function.
|
|
216
|
+
*/
|
|
217
|
+
export interface ContractSourceLoader {
|
|
218
|
+
readonly kind: 'loader';
|
|
219
|
+
readonly load: () => unknown | Promise<unknown>;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Discriminated union for contract source.
|
|
224
|
+
* Use `kind` to determine how to resolve the contract.
|
|
225
|
+
*/
|
|
226
|
+
export type EmitContractSource = ContractSourceValue | ContractSourceLoader;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Contract configuration for emit operation.
|
|
230
|
+
*/
|
|
231
|
+
export interface EmitContractConfig {
|
|
232
|
+
/**
|
|
233
|
+
* Contract source - either a raw value or a loader function.
|
|
234
|
+
* Switch on `source.kind` to determine how to resolve.
|
|
235
|
+
*/
|
|
236
|
+
readonly source: EmitContractSource;
|
|
237
|
+
/**
|
|
238
|
+
* Output path for contract.json.
|
|
239
|
+
* Should be an absolute or relative path.
|
|
240
|
+
*/
|
|
241
|
+
readonly output: string;
|
|
242
|
+
/**
|
|
243
|
+
* Output path for contract.d.ts.
|
|
244
|
+
* Should be an absolute or relative path.
|
|
245
|
+
*/
|
|
246
|
+
readonly types: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Options for the emit operation.
|
|
251
|
+
*/
|
|
252
|
+
export interface EmitOptions {
|
|
253
|
+
/**
|
|
254
|
+
* Contract configuration containing source, output, and types paths.
|
|
255
|
+
*/
|
|
256
|
+
readonly contractConfig: EmitContractConfig;
|
|
163
257
|
/** Optional progress callback for observing operation progress */
|
|
164
258
|
readonly onProgress?: OnControlProgress;
|
|
165
259
|
}
|
|
@@ -221,6 +315,42 @@ export interface DbInitFailure {
|
|
|
221
315
|
*/
|
|
222
316
|
export type DbInitResult = Result<DbInitSuccess, DbInitFailure>;
|
|
223
317
|
|
|
318
|
+
/**
|
|
319
|
+
* Successful emit result.
|
|
320
|
+
* Contains the hashes and paths of emitted files.
|
|
321
|
+
*/
|
|
322
|
+
export interface EmitSuccess {
|
|
323
|
+
/** Core hash of the emitted contract */
|
|
324
|
+
readonly coreHash: string;
|
|
325
|
+
/** Profile hash of the emitted contract (target-specific) */
|
|
326
|
+
readonly profileHash: string;
|
|
327
|
+
/** The emitted contract as JSON string */
|
|
328
|
+
readonly contractJson: string;
|
|
329
|
+
/** The emitted contract TypeScript declarations */
|
|
330
|
+
readonly contractDts: string;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Failure codes for emit operation.
|
|
335
|
+
*/
|
|
336
|
+
export type EmitFailureCode = 'CONTRACT_SOURCE_INVALID' | 'EMIT_FAILED';
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Failure details for emit operation.
|
|
340
|
+
*/
|
|
341
|
+
export interface EmitFailure {
|
|
342
|
+
readonly code: EmitFailureCode;
|
|
343
|
+
readonly summary: string;
|
|
344
|
+
readonly why: string | undefined;
|
|
345
|
+
readonly meta: Record<string, unknown> | undefined;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Result type for emit operation.
|
|
350
|
+
* Uses Result pattern: success returns EmitSuccess, failure returns EmitFailure.
|
|
351
|
+
*/
|
|
352
|
+
export type EmitResult = Result<EmitSuccess, EmitFailure>;
|
|
353
|
+
|
|
224
354
|
// ============================================================================
|
|
225
355
|
// Client Interface
|
|
226
356
|
// ============================================================================
|
|
@@ -310,4 +440,22 @@ export interface ControlClient {
|
|
|
310
440
|
* @throws If not connected or infrastructure failure
|
|
311
441
|
*/
|
|
312
442
|
introspect(options?: IntrospectOptions): Promise<unknown>;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Converts a schema IR to a schema view for CLI tree rendering.
|
|
446
|
+
* Delegates to the family instance's toSchemaView method.
|
|
447
|
+
*
|
|
448
|
+
* @param schemaIR - The schema IR from introspect()
|
|
449
|
+
* @returns CoreSchemaView if the family supports it, undefined otherwise
|
|
450
|
+
*/
|
|
451
|
+
toSchemaView(schemaIR: unknown): CoreSchemaView | undefined;
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Emits the contract to JSON and TypeScript declarations.
|
|
455
|
+
* This is an offline operation that does NOT require a database connection.
|
|
456
|
+
* Uses `init()` to create the stack but does NOT call `connect()`.
|
|
457
|
+
*
|
|
458
|
+
* @returns Result pattern: Ok with emit details, NotOk with failure details
|
|
459
|
+
*/
|
|
460
|
+
emit(options: EmitOptions): Promise<EmitResult>;
|
|
313
461
|
}
|
|
@@ -20,6 +20,8 @@ export { createControlClient } from '../control-api/client';
|
|
|
20
20
|
|
|
21
21
|
// CLI-specific types
|
|
22
22
|
export type {
|
|
23
|
+
ContractSourceLoader,
|
|
24
|
+
ContractSourceValue,
|
|
23
25
|
ControlActionName,
|
|
24
26
|
ControlClient,
|
|
25
27
|
ControlClientOptions,
|
|
@@ -29,6 +31,13 @@ export type {
|
|
|
29
31
|
DbInitOptions,
|
|
30
32
|
DbInitResult,
|
|
31
33
|
DbInitSuccess,
|
|
34
|
+
EmitContractConfig,
|
|
35
|
+
EmitContractSource,
|
|
36
|
+
EmitFailure,
|
|
37
|
+
EmitFailureCode,
|
|
38
|
+
EmitOptions,
|
|
39
|
+
EmitResult,
|
|
40
|
+
EmitSuccess,
|
|
32
41
|
IntrospectOptions,
|
|
33
42
|
OnControlProgress,
|
|
34
43
|
SchemaVerifyOptions,
|
package/dist/chunk-5MPKZYVI.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CliStructuredError
|
|
3
|
-
} from "./chunk-VI2YETW7.js";
|
|
4
|
-
|
|
5
|
-
// src/utils/action.ts
|
|
6
|
-
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
|
-
async function performAction(fn) {
|
|
8
|
-
try {
|
|
9
|
-
const value = await fn();
|
|
10
|
-
return ok(value);
|
|
11
|
-
} catch (error) {
|
|
12
|
-
if (error instanceof CliStructuredError) {
|
|
13
|
-
return notOk(error);
|
|
14
|
-
}
|
|
15
|
-
throw error;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// src/utils/spinner.ts
|
|
20
|
-
import ora from "ora";
|
|
21
|
-
async function withSpinner(operation, options) {
|
|
22
|
-
const { message, flags } = options;
|
|
23
|
-
const shouldShowSpinner = !flags.quiet && flags.json !== "object" && process.stdout.isTTY;
|
|
24
|
-
if (!shouldShowSpinner) {
|
|
25
|
-
return operation();
|
|
26
|
-
}
|
|
27
|
-
const startTime = Date.now();
|
|
28
|
-
const spinner = ora({
|
|
29
|
-
text: message,
|
|
30
|
-
color: flags.color !== false ? "cyan" : false
|
|
31
|
-
}).start();
|
|
32
|
-
try {
|
|
33
|
-
const result = await operation();
|
|
34
|
-
const elapsed = Date.now() - startTime;
|
|
35
|
-
spinner.succeed(`${message} (${elapsed}ms)`);
|
|
36
|
-
return result;
|
|
37
|
-
} catch (error) {
|
|
38
|
-
spinner.fail(`${message} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
39
|
-
throw error;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
performAction,
|
|
45
|
-
withSpinner
|
|
46
|
-
};
|
|
47
|
-
//# sourceMappingURL=chunk-5MPKZYVI.js.map
|