@prisma-next/core-control-plane 0.3.0-dev.7 → 0.3.0-dev.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +31 -99
  3. package/dist/constants.d.mts +9 -0
  4. package/dist/constants.d.mts.map +1 -0
  5. package/dist/constants.mjs +10 -0
  6. package/dist/constants.mjs.map +1 -0
  7. package/dist/emission.d.mts +58 -0
  8. package/dist/emission.d.mts.map +1 -0
  9. package/dist/emission.mjs +315 -0
  10. package/dist/emission.mjs.map +1 -0
  11. package/dist/errors.d.mts +216 -0
  12. package/dist/errors.d.mts.map +1 -0
  13. package/dist/errors.mjs +310 -0
  14. package/dist/errors.mjs.map +1 -0
  15. package/dist/{schema-view.d.ts → schema-view-Dy-708a5.d.mts} +13 -10
  16. package/dist/schema-view-Dy-708a5.d.mts.map +1 -0
  17. package/dist/schema-view.d.mts +2 -0
  18. package/dist/schema-view.mjs +1 -0
  19. package/dist/stack.d.mts +30 -0
  20. package/dist/stack.d.mts.map +1 -0
  21. package/dist/stack.mjs +30 -0
  22. package/dist/stack.mjs.map +1 -0
  23. package/dist/types-DRfFlMdY.d.mts +613 -0
  24. package/dist/types-DRfFlMdY.d.mts.map +1 -0
  25. package/dist/types.d.mts +2 -0
  26. package/dist/types.mjs +1 -0
  27. package/package.json +31 -39
  28. package/src/constants.ts +5 -0
  29. package/src/emission/canonicalization.ts +68 -21
  30. package/src/emission/emit.ts +82 -21
  31. package/src/emission/hashing.ts +29 -27
  32. package/src/emission/types.ts +13 -2
  33. package/src/errors.ts +86 -12
  34. package/src/exports/constants.ts +1 -0
  35. package/src/exports/emission.ts +1 -1
  36. package/src/exports/errors.ts +4 -1
  37. package/src/exports/stack.ts +1 -0
  38. package/src/exports/types.ts +1 -0
  39. package/src/migrations.ts +22 -1
  40. package/src/stack.ts +38 -0
  41. package/src/types.ts +41 -17
  42. package/dist/chunk-U5RYT6PT.js +0 -229
  43. package/dist/chunk-U5RYT6PT.js.map +0 -1
  44. package/dist/config-types.d.ts +0 -68
  45. package/dist/config-types.d.ts.map +0 -1
  46. package/dist/config-validation.d.ts +0 -10
  47. package/dist/config-validation.d.ts.map +0 -1
  48. package/dist/emission/canonicalization.d.ts +0 -6
  49. package/dist/emission/canonicalization.d.ts.map +0 -1
  50. package/dist/emission/emit.d.ts +0 -5
  51. package/dist/emission/emit.d.ts.map +0 -1
  52. package/dist/emission/hashing.d.ts +0 -17
  53. package/dist/emission/hashing.d.ts.map +0 -1
  54. package/dist/emission/types.d.ts +0 -16
  55. package/dist/emission/types.d.ts.map +0 -1
  56. package/dist/errors.d.ts +0 -183
  57. package/dist/errors.d.ts.map +0 -1
  58. package/dist/exports/config-types.d.ts +0 -3
  59. package/dist/exports/config-types.d.ts.map +0 -1
  60. package/dist/exports/config-types.js +0 -53
  61. package/dist/exports/config-types.js.map +0 -1
  62. package/dist/exports/config-validation.d.ts +0 -2
  63. package/dist/exports/config-validation.d.ts.map +0 -1
  64. package/dist/exports/config-validation.js +0 -252
  65. package/dist/exports/config-validation.js.map +0 -1
  66. package/dist/exports/emission.d.ts +0 -5
  67. package/dist/exports/emission.d.ts.map +0 -1
  68. package/dist/exports/emission.js +0 -310
  69. package/dist/exports/emission.js.map +0 -1
  70. package/dist/exports/errors.d.ts +0 -3
  71. package/dist/exports/errors.d.ts.map +0 -1
  72. package/dist/exports/errors.js +0 -43
  73. package/dist/exports/errors.js.map +0 -1
  74. package/dist/exports/schema-view.d.ts +0 -2
  75. package/dist/exports/schema-view.d.ts.map +0 -1
  76. package/dist/exports/schema-view.js +0 -1
  77. package/dist/exports/schema-view.js.map +0 -1
  78. package/dist/exports/types.d.ts +0 -2
  79. package/dist/exports/types.d.ts.map +0 -1
  80. package/dist/exports/types.js +0 -1
  81. package/dist/exports/types.js.map +0 -1
  82. package/dist/migrations.d.ts +0 -190
  83. package/dist/migrations.d.ts.map +0 -1
  84. package/dist/schema-view.d.ts.map +0 -1
  85. package/dist/types.d.ts +0 -400
  86. package/dist/types.d.ts.map +0 -1
  87. package/src/config-types.ts +0 -157
  88. package/src/config-validation.ts +0 -270
  89. package/src/exports/config-types.ts +0 -5
  90. package/src/exports/config-validation.ts +0 -1
package/src/errors.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * This is the serialized form of a CliStructuredError.
4
4
  */
5
5
  export interface CliErrorEnvelope {
6
+ readonly ok: false;
6
7
  readonly code: string;
7
8
  readonly domain: string;
8
9
  readonly severity: 'error' | 'warn' | 'info';
@@ -66,7 +67,7 @@ export class CliStructuredError extends Error {
66
67
  this.domain = options?.domain ?? 'CLI';
67
68
  this.severity = options?.severity ?? 'error';
68
69
  this.why = options?.why;
69
- this.fix = options?.fix;
70
+ this.fix = options?.fix === options?.why ? undefined : options?.fix;
70
71
  this.where = options?.where
71
72
  ? {
72
73
  path: options.where.path,
@@ -83,6 +84,7 @@ export class CliStructuredError extends Error {
83
84
  toEnvelope(): CliErrorEnvelope {
84
85
  const codePrefix = this.domain === 'CLI' ? 'PN-CLI-' : 'PN-RTM-';
85
86
  return {
87
+ ok: false as const,
86
88
  code: `${codePrefix}${this.code}`,
87
89
  domain: this.domain,
88
90
  severity: this.severity,
@@ -94,6 +96,23 @@ export class CliStructuredError extends Error {
94
96
  docsUrl: this.docsUrl,
95
97
  };
96
98
  }
99
+
100
+ /**
101
+ * Type guard to check if an error is a CliStructuredError.
102
+ * Uses duck-typing to work across module boundaries where instanceof may fail.
103
+ */
104
+ static is(error: unknown): error is CliStructuredError {
105
+ if (!(error instanceof Error)) {
106
+ return false;
107
+ }
108
+ const candidate = error as CliStructuredError;
109
+ return (
110
+ candidate.name === 'CliStructuredError' &&
111
+ typeof candidate.code === 'string' &&
112
+ (candidate.domain === 'CLI' || candidate.domain === 'RTM') &&
113
+ typeof candidate.toEnvelope === 'function'
114
+ );
115
+ }
97
116
  }
98
117
 
99
118
  // ============================================================================
@@ -171,13 +190,15 @@ export function errorFileNotFound(
171
190
  }
172
191
 
173
192
  /**
174
- * Database URL is required but not provided.
193
+ * Database connection is required but not provided.
175
194
  */
176
- export function errorDatabaseUrlRequired(options?: { readonly why?: string }): CliStructuredError {
177
- return new CliStructuredError('4005', 'Database URL is required', {
195
+ export function errorDatabaseConnectionRequired(options?: {
196
+ readonly why?: string;
197
+ }): CliStructuredError {
198
+ return new CliStructuredError('4005', 'Database connection is required', {
178
199
  domain: 'CLI',
179
- why: options?.why ?? 'Database URL is required for this command',
180
- fix: 'Provide `--db <url>` or set `db: { url: "postgres://…" }` in prisma-next.config.ts',
200
+ why: options?.why ?? 'Database connection is required for this command',
201
+ fix: 'Provide `--db <url>` or set `db: { connection: "postgres://…" }` in prisma-next.config.ts',
181
202
  });
182
203
  }
183
204
 
@@ -316,16 +337,16 @@ export function errorConfigValidation(
316
337
  readonly why?: string;
317
338
  },
318
339
  ): CliStructuredError {
319
- return new CliStructuredError('4001', 'Config file not found', {
340
+ return new CliStructuredError('4009', 'Config validation error', {
320
341
  domain: 'CLI',
321
342
  why: options?.why ?? `Config must have a "${field}" field`,
322
- fix: "Run 'prisma-next init' to create a config file",
343
+ fix: 'Check your prisma-next.config.ts and ensure all required fields are provided',
323
344
  docsUrl: 'https://prisma-next.dev/docs/cli/config',
324
345
  });
325
346
  }
326
347
 
327
348
  // ============================================================================
328
- // Runtime Errors (PN-RTM-3000-3003)
349
+ // Runtime Errors (PN-RTM-3000-3030)
329
350
  // ============================================================================
330
351
 
331
352
  /**
@@ -335,10 +356,10 @@ export function errorMarkerMissing(options?: {
335
356
  readonly why?: string;
336
357
  readonly dbUrl?: string;
337
358
  }): CliStructuredError {
338
- return new CliStructuredError('3001', 'Marker missing', {
359
+ return new CliStructuredError('3001', 'Database not signed', {
339
360
  domain: 'RTM',
340
- why: options?.why ?? 'Contract marker not found in database',
341
- fix: 'Run `prisma-next db sign --db <url>` to create marker',
361
+ why: options?.why ?? 'No database signature (marker) found',
362
+ fix: 'Run `prisma-next db sign --db <url>` to sign the database',
342
363
  });
343
364
  }
344
365
 
@@ -385,6 +406,59 @@ export function errorTargetMismatch(
385
406
  });
386
407
  }
387
408
 
409
+ /**
410
+ * Database marker is required but not found.
411
+ * Used by commands that require a pre-existing marker as a precondition.
412
+ */
413
+ export function errorMarkerRequired(options?: {
414
+ readonly why?: string;
415
+ readonly fix?: string;
416
+ }): CliStructuredError {
417
+ return new CliStructuredError('3010', 'Database must be signed first', {
418
+ domain: 'RTM',
419
+ why: options?.why ?? 'No database signature (marker) found',
420
+ fix: options?.fix ?? 'Run `prisma-next db init` first to sign the database',
421
+ });
422
+ }
423
+
424
+ /**
425
+ * Migration runner failed during execution.
426
+ */
427
+ export function errorRunnerFailed(
428
+ summary: string,
429
+ options?: {
430
+ readonly why?: string;
431
+ readonly fix?: string;
432
+ readonly meta?: Record<string, unknown>;
433
+ },
434
+ ): CliStructuredError {
435
+ return new CliStructuredError('3020', summary, {
436
+ domain: 'RTM',
437
+ why: options?.why ?? 'Migration runner failed',
438
+ fix: options?.fix ?? 'Inspect the reported conflict and reconcile schema drift',
439
+ ...(options?.meta ? { meta: options.meta } : {}),
440
+ });
441
+ }
442
+
443
+ /**
444
+ * Destructive operations require explicit confirmation via --accept-data-loss.
445
+ */
446
+ export function errorDestructiveChanges(
447
+ summary: string,
448
+ options?: {
449
+ readonly why?: string;
450
+ readonly fix?: string;
451
+ readonly meta?: Record<string, unknown>;
452
+ },
453
+ ): CliStructuredError {
454
+ return new CliStructuredError('3030', summary, {
455
+ domain: 'RTM',
456
+ why: options?.why ?? 'Planned operations include destructive changes that require confirmation',
457
+ fix: options?.fix ?? 'Use `--plan` to preview, then re-run with `--accept-data-loss`',
458
+ ...(options?.meta ? { meta: options.meta } : {}),
459
+ });
460
+ }
461
+
388
462
  /**
389
463
  * Generic runtime error.
390
464
  */
@@ -0,0 +1 @@
1
+ export { EMPTY_CONTRACT_HASH } from '../constants';
@@ -2,5 +2,5 @@
2
2
 
3
3
  export { canonicalizeContract } from '../emission/canonicalization';
4
4
  export { emit } from '../emission/emit';
5
- export { computeCoreHash, computeProfileHash } from '../emission/hashing';
5
+ export { computeExecutionHash, computeProfileHash, computeStorageHash } from '../emission/hashing';
6
6
  export type { EmitOptions, EmitResult } from '../emission/types';
@@ -6,15 +6,18 @@ export {
6
6
  errorContractConfigMissing,
7
7
  errorContractMissingExtensionPacks,
8
8
  errorContractValidationFailed,
9
- errorDatabaseUrlRequired,
9
+ errorDatabaseConnectionRequired,
10
+ errorDestructiveChanges,
10
11
  errorDriverRequired,
11
12
  errorFamilyReadMarkerSqlRequired,
12
13
  errorFileNotFound,
13
14
  errorHashMismatch,
14
15
  errorJsonFormatNotSupported,
15
16
  errorMarkerMissing,
17
+ errorMarkerRequired,
16
18
  errorMigrationPlanningFailed,
17
19
  errorQueryRunnerFactoryRequired,
20
+ errorRunnerFailed,
18
21
  errorRuntime,
19
22
  errorTargetMigrationNotSupported,
20
23
  errorTargetMismatch,
@@ -0,0 +1 @@
1
+ export { createControlPlaneStack } from '../stack';
@@ -8,6 +8,7 @@ export type {
8
8
  ControlExtensionInstance,
9
9
  ControlFamilyDescriptor,
10
10
  ControlFamilyInstance,
11
+ ControlPlaneStack,
11
12
  ControlTargetDescriptor,
12
13
  ControlTargetInstance,
13
14
  EmitContractResult,
package/src/migrations.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  */
11
11
 
12
12
  import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
13
+ import type { ContractIR } from '@prisma-next/contract/ir';
13
14
  import type { Result } from '@prisma-next/utils/result';
14
15
  import type { ControlDriverInstance, ControlFamilyInstance } from './types';
15
16
 
@@ -49,6 +50,10 @@ export interface MigrationPlanOperation {
49
50
  readonly operationClass: MigrationOperationClass;
50
51
  }
51
52
 
53
+ // ============================================================================
54
+ // Plan Types (Display-Oriented)
55
+ // ============================================================================
56
+
52
57
  /**
53
58
  * A migration plan for display purposes.
54
59
  * Contains only the fields needed for CLI output (summary, JSON envelope).
@@ -56,9 +61,17 @@ export interface MigrationPlanOperation {
56
61
  export interface MigrationPlan {
57
62
  /** The target ID this plan is for (e.g., 'postgres'). */
58
63
  readonly targetId: string;
64
+ /**
65
+ * Origin contract identity that the plan expects the database to currently be at.
66
+ * If omitted or null, the runner skips origin validation entirely.
67
+ */
68
+ readonly origin?: {
69
+ readonly storageHash: string;
70
+ readonly profileHash?: string;
71
+ } | null;
59
72
  /** Destination contract identity that the plan intends to reach. */
60
73
  readonly destination: {
61
- readonly coreHash: string;
74
+ readonly storageHash: string;
62
75
  readonly profileHash?: string;
63
76
  };
64
77
  /** Ordered list of operations to execute. */
@@ -244,4 +257,12 @@ export interface TargetMigrationsCapability<
244
257
  > {
245
258
  createPlanner(family: TFamilyInstance): MigrationPlanner<TFamilyId, TTargetId>;
246
259
  createRunner(family: TFamilyInstance): MigrationRunner<TFamilyId, TTargetId>;
260
+ /**
261
+ * Synthesizes a family-specific schema IR from a contract for offline planning.
262
+ * The returned schema can be passed to `planner.plan({ schema })` as the "from" state.
263
+ *
264
+ * @param contract - The contract to convert, or null for a new project (empty schema).
265
+ * @returns Family-specific schema IR (e.g., `SqlSchemaIR` for SQL targets).
266
+ */
267
+ contractToSchema(contract: ContractIR | null): unknown;
247
268
  }
package/src/stack.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type {
2
+ ControlAdapterDescriptor,
3
+ ControlDriverDescriptor,
4
+ ControlExtensionDescriptor,
5
+ ControlPlaneStack,
6
+ ControlTargetDescriptor,
7
+ } from './types';
8
+
9
+ /**
10
+ * Creates a ControlPlaneStack from component descriptors.
11
+ *
12
+ * Provides sensible defaults:
13
+ * - `driver` defaults to `undefined` (optional for commands that don't need DB connection)
14
+ * - `extensionPacks` defaults to `[]` (empty array)
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const stack = createControlPlaneStack({
19
+ * target: postgresTarget,
20
+ * adapter: postgresAdapter,
21
+ * driver: postgresDriver, // optional
22
+ * extensionPacks: [pgvector], // optional
23
+ * });
24
+ * ```
25
+ */
26
+ export function createControlPlaneStack<TFamilyId extends string, TTargetId extends string>(input: {
27
+ readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;
28
+ readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;
29
+ readonly driver?: ControlDriverDescriptor<TFamilyId, TTargetId> | undefined;
30
+ readonly extensionPacks?: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[] | undefined;
31
+ }): ControlPlaneStack<TFamilyId, TTargetId> {
32
+ return {
33
+ target: input.target,
34
+ adapter: input.adapter,
35
+ driver: input.driver,
36
+ extensionPacks: input.extensionPacks ?? [],
37
+ };
38
+ }
package/src/types.ts CHANGED
@@ -53,17 +53,17 @@ export interface ControlFamilyInstance<TFamilyId extends string, TSchemaIR = unk
53
53
  * Mappings are runtime-only and should not be part of ContractIR.
54
54
  *
55
55
  * Note: The returned ContractIR may include additional fields from the emitted contract
56
- * (like coreHash, profileHash) that are not part of the ContractIR type but are preserved
56
+ * (like storageHash/executionHash, profileHash) that are not part of the ContractIR type but are preserved
57
57
  * for use by verify/sign operations.
58
58
  */
59
59
  validateContractIR(contractJson: unknown): ContractIR;
60
60
 
61
61
  /**
62
62
  * Verifies the database marker against the contract.
63
- * Compares target, coreHash, and profileHash.
63
+ * Compares target, storageHash, and profileHash.
64
64
  *
65
65
  * @param options.contractIR - The validated contract (from validateContractIR). Must have
66
- * coreHash and target fields for verification. These fields are present in emitted
66
+ * storageHash and target fields for verification. These fields are present in emitted
67
67
  * contracts but not in the ContractIR type definition.
68
68
  */
69
69
  verify(options: {
@@ -236,6 +236,23 @@ export interface OperationContext {
236
236
  // Control*Descriptor Interfaces (ADR 151)
237
237
  // ============================================================================
238
238
 
239
+ /**
240
+ * A bundle of control-plane component descriptors for a specific family and target.
241
+ *
242
+ * This struct groups the target, adapter, driver (optional), and extension packs
243
+ * needed to create a family instance and run CLI commands. Use `createControlPlaneStack()`
244
+ * to construct with sensible defaults.
245
+ *
246
+ * @template TFamilyId - The family ID (e.g., 'sql', 'document')
247
+ * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
248
+ */
249
+ export interface ControlPlaneStack<TFamilyId extends string, TTargetId extends string> {
250
+ readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;
251
+ readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;
252
+ readonly driver: ControlDriverDescriptor<TFamilyId, TTargetId> | undefined;
253
+ readonly extensionPacks: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[];
254
+ }
255
+
239
256
  /**
240
257
  * Descriptor for a control-plane family (e.g., SQL).
241
258
  * Provides the family hook and factory method.
@@ -248,12 +265,7 @@ export interface ControlFamilyDescriptor<
248
265
  TFamilyInstance extends ControlFamilyInstance<TFamilyId> = ControlFamilyInstance<TFamilyId>,
249
266
  > extends FamilyDescriptor<TFamilyId> {
250
267
  readonly hook: TargetFamilyHook;
251
- create<TTargetId extends string>(options: {
252
- readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;
253
- readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;
254
- readonly driver: ControlDriverDescriptor<TFamilyId, TTargetId>;
255
- readonly extensionPacks: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[];
256
- }): TFamilyInstance;
268
+ create<TTargetId extends string>(stack: ControlPlaneStack<TFamilyId, TTargetId>): TFamilyInstance;
257
269
  }
258
270
 
259
271
  /**
@@ -304,9 +316,14 @@ export interface ControlAdapterDescriptor<
304
316
  /**
305
317
  * Descriptor for a control-plane driver component (e.g., Postgres driver).
306
318
  *
319
+ * The connection input type is driver-specific. For example:
320
+ * - Postgres uses a connection string (URL)
321
+ * - Other drivers may accept structured objects (e.g., file paths, credentials)
322
+ *
307
323
  * @template TFamilyId - The family ID (e.g., 'sql', 'document')
308
324
  * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
309
325
  * @template TDriverInstance - The driver instance type
326
+ * @template TConnection - The connection input type (defaults to `string` for URL-based drivers)
310
327
  */
311
328
  export interface ControlDriverDescriptor<
312
329
  TFamilyId extends string,
@@ -315,8 +332,9 @@ export interface ControlDriverDescriptor<
315
332
  TFamilyId,
316
333
  TTargetId
317
334
  >,
335
+ TConnection = string,
318
336
  > extends DriverDescriptor<TFamilyId, TTargetId> {
319
- create(url: string): Promise<TDriverInstance>;
337
+ create(connection: TConnection): Promise<TDriverInstance>;
320
338
  }
321
339
 
322
340
  /**
@@ -345,11 +363,11 @@ export interface VerifyDatabaseResult {
345
363
  readonly code?: string;
346
364
  readonly summary: string;
347
365
  readonly contract: {
348
- readonly coreHash: string;
366
+ readonly storageHash: string;
349
367
  readonly profileHash?: string;
350
368
  };
351
369
  readonly marker?: {
352
- readonly coreHash?: string;
370
+ readonly storageHash?: string;
353
371
  readonly profileHash?: string;
354
372
  };
355
373
  readonly target: {
@@ -381,15 +399,20 @@ export interface SchemaIssue {
381
399
  | 'extra_unique_constraint'
382
400
  | 'extra_index'
383
401
  | 'type_mismatch'
402
+ | 'type_missing'
403
+ | 'type_values_mismatch'
384
404
  | 'nullability_mismatch'
385
405
  | 'primary_key_mismatch'
386
406
  | 'foreign_key_mismatch'
387
407
  | 'unique_constraint_mismatch'
388
408
  | 'index_mismatch'
389
- | 'extension_missing';
409
+ | 'extension_missing'
410
+ | 'default_missing'
411
+ | 'default_mismatch';
390
412
  readonly table: string;
391
413
  readonly column?: string;
392
414
  readonly indexOrConstraint?: string;
415
+ readonly typeName?: string;
393
416
  readonly expected?: string;
394
417
  readonly actual?: string;
395
418
  readonly message: string;
@@ -419,7 +442,7 @@ export interface VerifyDatabaseSchemaResult {
419
442
  readonly code?: string;
420
443
  readonly summary: string;
421
444
  readonly contract: {
422
- readonly coreHash: string;
445
+ readonly storageHash: string;
423
446
  readonly profileHash?: string;
424
447
  };
425
448
  readonly target: {
@@ -452,7 +475,8 @@ export interface VerifyDatabaseSchemaResult {
452
475
  export interface EmitContractResult {
453
476
  readonly contractJson: string;
454
477
  readonly contractDts: string;
455
- readonly coreHash: string;
478
+ readonly storageHash: string;
479
+ readonly executionHash?: string;
456
480
  readonly profileHash: string;
457
481
  }
458
482
 
@@ -487,7 +511,7 @@ export interface SignDatabaseResult {
487
511
  readonly ok: boolean;
488
512
  readonly summary: string;
489
513
  readonly contract: {
490
- readonly coreHash: string;
514
+ readonly storageHash: string;
491
515
  readonly profileHash?: string;
492
516
  };
493
517
  readonly target: {
@@ -498,7 +522,7 @@ export interface SignDatabaseResult {
498
522
  readonly created: boolean;
499
523
  readonly updated: boolean;
500
524
  readonly previous?: {
501
- readonly coreHash?: string;
525
+ readonly storageHash?: string;
502
526
  readonly profileHash?: string;
503
527
  };
504
528
  };
@@ -1,229 +0,0 @@
1
- // src/errors.ts
2
- var CliStructuredError = class extends Error {
3
- code;
4
- domain;
5
- severity;
6
- why;
7
- fix;
8
- where;
9
- meta;
10
- docsUrl;
11
- constructor(code, summary, options) {
12
- super(summary);
13
- this.name = "CliStructuredError";
14
- this.code = code;
15
- this.domain = options?.domain ?? "CLI";
16
- this.severity = options?.severity ?? "error";
17
- this.why = options?.why;
18
- this.fix = options?.fix;
19
- this.where = options?.where ? {
20
- path: options.where.path,
21
- line: options.where.line
22
- } : void 0;
23
- this.meta = options?.meta;
24
- this.docsUrl = options?.docsUrl;
25
- }
26
- /**
27
- * Converts this error to a CLI error envelope for output formatting.
28
- */
29
- toEnvelope() {
30
- const codePrefix = this.domain === "CLI" ? "PN-CLI-" : "PN-RTM-";
31
- return {
32
- code: `${codePrefix}${this.code}`,
33
- domain: this.domain,
34
- severity: this.severity,
35
- summary: this.message,
36
- why: this.why,
37
- fix: this.fix,
38
- where: this.where,
39
- meta: this.meta,
40
- docsUrl: this.docsUrl
41
- };
42
- }
43
- };
44
- function errorConfigFileNotFound(configPath, options) {
45
- return new CliStructuredError("4001", "Config file not found", {
46
- domain: "CLI",
47
- ...options?.why ? { why: options.why } : { why: "Config file not found" },
48
- fix: "Run 'prisma-next init' to create a config file",
49
- docsUrl: "https://prisma-next.dev/docs/cli/config",
50
- ...configPath ? { where: { path: configPath } } : {}
51
- });
52
- }
53
- function errorContractConfigMissing(options) {
54
- return new CliStructuredError("4002", "Contract configuration missing", {
55
- domain: "CLI",
56
- why: options?.why ?? "The contract configuration is required for emit",
57
- fix: "Add contract configuration to your prisma-next.config.ts",
58
- docsUrl: "https://prisma-next.dev/docs/cli/contract-emit"
59
- });
60
- }
61
- function errorContractValidationFailed(reason, options) {
62
- return new CliStructuredError("4003", "Contract validation failed", {
63
- domain: "CLI",
64
- why: reason,
65
- fix: "Re-run `prisma-next contract emit`, or fix the contract file and try again",
66
- docsUrl: "https://prisma-next.dev/docs/contracts",
67
- ...options?.where ? { where: options.where } : {}
68
- });
69
- }
70
- function errorFileNotFound(filePath, options) {
71
- return new CliStructuredError("4004", "File not found", {
72
- domain: "CLI",
73
- why: options?.why ?? `File not found: ${filePath}`,
74
- fix: options?.fix ?? "Check that the file path is correct",
75
- where: { path: filePath },
76
- ...options?.docsUrl ? { docsUrl: options.docsUrl } : {}
77
- });
78
- }
79
- function errorDatabaseUrlRequired(options) {
80
- return new CliStructuredError("4005", "Database URL is required", {
81
- domain: "CLI",
82
- why: options?.why ?? "Database URL is required for this command",
83
- fix: 'Provide `--db <url>` or set `db: { url: "postgres://\u2026" }` in prisma-next.config.ts'
84
- });
85
- }
86
- function errorQueryRunnerFactoryRequired(options) {
87
- return new CliStructuredError("4006", "Query runner factory is required", {
88
- domain: "CLI",
89
- why: options?.why ?? "Config.db.queryRunnerFactory is required for db verify",
90
- fix: "Add db.queryRunnerFactory to prisma-next.config.ts",
91
- docsUrl: "https://prisma-next.dev/docs/cli/db-verify"
92
- });
93
- }
94
- function errorFamilyReadMarkerSqlRequired(options) {
95
- return new CliStructuredError("4007", "Family readMarker() is required", {
96
- domain: "CLI",
97
- why: options?.why ?? "Family verify.readMarker is required for db verify",
98
- fix: "Ensure family.verify.readMarker() is exported by your family package",
99
- docsUrl: "https://prisma-next.dev/docs/cli/db-verify"
100
- });
101
- }
102
- function errorJsonFormatNotSupported(options) {
103
- return new CliStructuredError("4008", "Unsupported JSON format", {
104
- domain: "CLI",
105
- why: `The ${options.command} command does not support --json ${options.format}`,
106
- fix: `Use --json ${options.supportedFormats.join(" or ")}, or omit --json for human output`,
107
- meta: {
108
- command: options.command,
109
- format: options.format,
110
- supportedFormats: options.supportedFormats
111
- }
112
- });
113
- }
114
- function errorDriverRequired(options) {
115
- return new CliStructuredError("4010", "Driver is required for DB-connected commands", {
116
- domain: "CLI",
117
- why: options?.why ?? "Config.driver is required for DB-connected commands",
118
- fix: "Add a control-plane driver to prisma-next.config.ts (e.g. import a driver descriptor and set `driver: postgresDriver`)",
119
- docsUrl: "https://prisma-next.dev/docs/cli/config"
120
- });
121
- }
122
- function errorContractMissingExtensionPacks(options) {
123
- const missing = [...options.missingExtensionPacks].sort();
124
- return new CliStructuredError("4011", "Missing extension packs in config", {
125
- domain: "CLI",
126
- why: missing.length === 1 ? `Contract requires extension pack '${missing[0]}', but CLI config does not provide a matching descriptor.` : `Contract requires extension packs ${missing.map((p) => `'${p}'`).join(", ")}, but CLI config does not provide matching descriptors.`,
127
- fix: "Add the missing extension descriptors to `extensions` in prisma-next.config.ts",
128
- docsUrl: "https://prisma-next.dev/docs/cli/config",
129
- meta: {
130
- missingExtensionPacks: missing,
131
- providedComponentIds: [...options.providedComponentIds].sort()
132
- }
133
- });
134
- }
135
- function errorMigrationPlanningFailed(options) {
136
- const conflictSummaries = options.conflicts.map((c) => c.summary);
137
- const computedWhy = options.why ?? conflictSummaries.join("\n");
138
- const conflictFixes = options.conflicts.map((c) => c.why).filter((why) => typeof why === "string");
139
- const computedFix = conflictFixes.length > 0 ? conflictFixes.join("\n") : "Use `db schema-verify` to inspect conflicts, or ensure the database is empty";
140
- return new CliStructuredError("4020", "Migration planning failed", {
141
- domain: "CLI",
142
- why: computedWhy,
143
- fix: computedFix,
144
- meta: { conflicts: options.conflicts },
145
- docsUrl: "https://prisma-next.dev/docs/cli/db-init"
146
- });
147
- }
148
- function errorTargetMigrationNotSupported(options) {
149
- return new CliStructuredError("4021", "Target does not support migrations", {
150
- domain: "CLI",
151
- why: options?.why ?? "The configured target does not provide migration planner/runner",
152
- fix: "Select a target that provides migrations (it must export `target.migrations` for db init)",
153
- docsUrl: "https://prisma-next.dev/docs/cli/db-init"
154
- });
155
- }
156
- function errorConfigValidation(field, options) {
157
- return new CliStructuredError("4001", "Config file not found", {
158
- domain: "CLI",
159
- why: options?.why ?? `Config must have a "${field}" field`,
160
- fix: "Run 'prisma-next init' to create a config file",
161
- docsUrl: "https://prisma-next.dev/docs/cli/config"
162
- });
163
- }
164
- function errorMarkerMissing(options) {
165
- return new CliStructuredError("3001", "Marker missing", {
166
- domain: "RTM",
167
- why: options?.why ?? "Contract marker not found in database",
168
- fix: "Run `prisma-next db sign --db <url>` to create marker"
169
- });
170
- }
171
- function errorHashMismatch(options) {
172
- return new CliStructuredError("3002", "Hash mismatch", {
173
- domain: "RTM",
174
- why: options?.why ?? "Contract hash does not match database marker",
175
- fix: "Migrate database or re-sign if intentional",
176
- ...options?.expected || options?.actual ? {
177
- meta: {
178
- ...options.expected ? { expected: options.expected } : {},
179
- ...options.actual ? { actual: options.actual } : {}
180
- }
181
- } : {}
182
- });
183
- }
184
- function errorTargetMismatch(expected, actual, options) {
185
- return new CliStructuredError("3003", "Target mismatch", {
186
- domain: "RTM",
187
- why: options?.why ?? `Contract target does not match config target (expected: ${expected}, actual: ${actual})`,
188
- fix: "Align contract target and config target",
189
- meta: { expected, actual }
190
- });
191
- }
192
- function errorRuntime(summary, options) {
193
- return new CliStructuredError("3000", summary, {
194
- domain: "RTM",
195
- ...options?.why ? { why: options.why } : { why: "Verification failed" },
196
- ...options?.fix ? { fix: options.fix } : { fix: "Check contract and database state" },
197
- ...options?.meta ? { meta: options.meta } : {}
198
- });
199
- }
200
- function errorUnexpected(message, options) {
201
- return new CliStructuredError("4999", "Unexpected error", {
202
- domain: "CLI",
203
- why: options?.why ?? message,
204
- fix: options?.fix ?? "Check the error message and try again"
205
- });
206
- }
207
-
208
- export {
209
- CliStructuredError,
210
- errorConfigFileNotFound,
211
- errorContractConfigMissing,
212
- errorContractValidationFailed,
213
- errorFileNotFound,
214
- errorDatabaseUrlRequired,
215
- errorQueryRunnerFactoryRequired,
216
- errorFamilyReadMarkerSqlRequired,
217
- errorJsonFormatNotSupported,
218
- errorDriverRequired,
219
- errorContractMissingExtensionPacks,
220
- errorMigrationPlanningFailed,
221
- errorTargetMigrationNotSupported,
222
- errorConfigValidation,
223
- errorMarkerMissing,
224
- errorHashMismatch,
225
- errorTargetMismatch,
226
- errorRuntime,
227
- errorUnexpected
228
- };
229
- //# sourceMappingURL=chunk-U5RYT6PT.js.map