@prisma-next/target-postgres 0.3.0-pr.99.5 → 0.3.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.
Files changed (66) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +17 -8
  3. package/dist/control.d.mts +19 -0
  4. package/dist/control.d.mts.map +1 -0
  5. package/dist/control.mjs +5382 -0
  6. package/dist/control.mjs.map +1 -0
  7. package/dist/descriptor-meta-CAf16lsJ.mjs +32 -0
  8. package/dist/descriptor-meta-CAf16lsJ.mjs.map +1 -0
  9. package/dist/migration-builders.d.mts +88 -0
  10. package/dist/migration-builders.d.mts.map +1 -0
  11. package/dist/migration-builders.mjs +3 -0
  12. package/dist/operation-descriptors-CxymFSgK.mjs +52 -0
  13. package/dist/operation-descriptors-CxymFSgK.mjs.map +1 -0
  14. package/dist/pack.d.mts +45 -0
  15. package/dist/pack.d.mts.map +1 -0
  16. package/dist/pack.mjs +9 -0
  17. package/dist/pack.mjs.map +1 -0
  18. package/dist/runtime.d.mts +9 -0
  19. package/dist/runtime.d.mts.map +1 -0
  20. package/dist/runtime.mjs +20 -0
  21. package/dist/runtime.mjs.map +1 -0
  22. package/package.json +30 -28
  23. package/src/core/authoring.ts +15 -0
  24. package/src/core/descriptor-meta.ts +5 -0
  25. package/src/core/migrations/descriptor-planner.ts +466 -0
  26. package/src/core/migrations/operation-descriptors.ts +166 -0
  27. package/src/core/migrations/operation-resolver.ts +929 -0
  28. package/src/core/migrations/planner-ddl-builders.ts +256 -0
  29. package/src/core/migrations/planner-identity-values.ts +135 -0
  30. package/src/core/migrations/planner-recipes.ts +91 -0
  31. package/src/core/migrations/planner-reconciliation.ts +798 -0
  32. package/src/core/migrations/planner-schema-lookup.ts +54 -0
  33. package/src/core/migrations/planner-sql-checks.ts +322 -0
  34. package/src/core/migrations/planner-strategies.ts +262 -0
  35. package/src/core/migrations/planner-target-details.ts +38 -0
  36. package/src/core/migrations/planner-type-resolution.ts +26 -0
  37. package/src/core/migrations/planner.ts +410 -460
  38. package/src/core/migrations/runner.ts +134 -38
  39. package/src/core/migrations/statement-builders.ts +6 -6
  40. package/src/core/types.ts +5 -0
  41. package/src/exports/control.ts +182 -12
  42. package/src/exports/migration-builders.ts +56 -0
  43. package/src/exports/pack.ts +7 -3
  44. package/src/exports/runtime.ts +6 -12
  45. package/dist/chunk-RKEXRSSI.js +0 -14
  46. package/dist/chunk-RKEXRSSI.js.map +0 -1
  47. package/dist/core/descriptor-meta.d.ts +0 -9
  48. package/dist/core/descriptor-meta.d.ts.map +0 -1
  49. package/dist/core/migrations/planner.d.ts +0 -14
  50. package/dist/core/migrations/planner.d.ts.map +0 -1
  51. package/dist/core/migrations/runner.d.ts +0 -8
  52. package/dist/core/migrations/runner.d.ts.map +0 -1
  53. package/dist/core/migrations/statement-builders.d.ts +0 -30
  54. package/dist/core/migrations/statement-builders.d.ts.map +0 -1
  55. package/dist/exports/control.d.ts +0 -8
  56. package/dist/exports/control.d.ts.map +0 -1
  57. package/dist/exports/control.js +0 -1260
  58. package/dist/exports/control.js.map +0 -1
  59. package/dist/exports/pack.d.ts +0 -4
  60. package/dist/exports/pack.d.ts.map +0 -1
  61. package/dist/exports/pack.js +0 -11
  62. package/dist/exports/pack.js.map +0 -1
  63. package/dist/exports/runtime.d.ts +0 -12
  64. package/dist/exports/runtime.d.ts.map +0 -1
  65. package/dist/exports/runtime.js +0 -19
  66. package/dist/exports/runtime.js.map +0 -1
@@ -1,3 +1,7 @@
1
+ import {
2
+ normalizeSchemaNativeType,
3
+ parsePostgresDefault,
4
+ } from '@prisma-next/adapter-postgres/control';
1
5
  import type { ContractMarkerRecord } from '@prisma-next/contract/types';
2
6
  import type {
3
7
  MigrationOperationPolicy,
@@ -13,10 +17,12 @@ import type {
13
17
  import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
14
18
  import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
15
19
  import { readMarker } from '@prisma-next/family-sql/verify';
20
+ import type { DataTransformOperation } from '@prisma-next/framework-components/control';
16
21
  import { SqlQueryError } from '@prisma-next/sql-errors';
22
+ import { ifDefined } from '@prisma-next/utils/defined';
17
23
  import type { Result } from '@prisma-next/utils/result';
18
24
  import { ok, okVoid } from '@prisma-next/utils/result';
19
- import type { PostgresPlanTargetDetails } from './planner';
25
+ import type { PostgresPlanTargetDetails } from './planner-target-details';
20
26
  import {
21
27
  buildLedgerInsertStatement,
22
28
  buildWriteMarkerStatements,
@@ -41,6 +47,18 @@ const DEFAULT_CONFIG: RunnerConfig = {
41
47
 
42
48
  const LOCK_DOMAIN = 'prisma_next.contract.marker';
43
49
 
50
+ function isDataTransformOperation(op: unknown): op is DataTransformOperation {
51
+ return (
52
+ typeof op === 'object' &&
53
+ op !== null &&
54
+ 'operationClass' in op &&
55
+ (op as { operationClass: string }).operationClass === 'data' &&
56
+ 'name' in op &&
57
+ 'check' in op &&
58
+ 'run' in op
59
+ );
60
+ }
61
+
44
62
  /**
45
63
  * Deep clones and freezes a record object to prevent mutation.
46
64
  * Recursively clones nested objects and arrays to ensure complete isolation.
@@ -112,11 +130,12 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
112
130
  return markerCheck;
113
131
  }
114
132
 
115
- // Apply plan operations or skip if marker already at destination
133
+ // db update (origin: null) always applies; migration-apply (origin set) skips if marker matches.
116
134
  const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);
135
+ const skipOperations = markerAtDestination && options.plan.origin != null;
117
136
  let applyValue: ApplyPlanSuccessValue;
118
137
 
119
- if (markerAtDestination) {
138
+ if (skipOperations) {
120
139
  applyValue = { operationsExecuted: 0, executedOperations: [] };
121
140
  } else {
122
141
  const applyResult = await this.applyPlan(driver, options);
@@ -130,7 +149,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
130
149
  // Step 1: Introspect live schema (DB I/O, family-owned)
131
150
  const schemaIR = await this.family.introspect({
132
151
  driver,
133
- contractIR: options.destinationContract,
152
+ contract: options.destinationContract,
134
153
  });
135
154
 
136
155
  // Step 2: Pure verification (no DB I/O)
@@ -141,6 +160,8 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
141
160
  context: options.context ?? {},
142
161
  typeMetadataRegistry: this.family.typeMetadataRegistry,
143
162
  frameworkComponents: options.frameworkComponents,
163
+ normalizeDefault: parsePostgresDefault,
164
+ normalizeNativeType: normalizeSchemaNativeType,
144
165
  });
145
166
  if (!schemaVerifyResult.ok) {
146
167
  return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
@@ -182,6 +203,19 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
182
203
  for (const operation of options.plan.operations) {
183
204
  options.callbacks?.onOperationStart?.(operation);
184
205
  try {
206
+ // Data transform operations have a different execution lifecycle
207
+ if (operation.operationClass === 'data' && isDataTransformOperation(operation)) {
208
+ const dtResult = await this.executeDataTransform(driver, operation, {
209
+ runIdempotency,
210
+ });
211
+ if (!dtResult.ok) {
212
+ return dtResult;
213
+ }
214
+ executedOperations.push(operation);
215
+ operationsExecuted += 1;
216
+ continue;
217
+ }
218
+
185
219
  // Idempotency probe: only run if both postchecks and idempotency checks are enabled
186
220
  if (runPostchecks && runIdempotency) {
187
221
  const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(
@@ -234,6 +268,80 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
234
268
  return ok({ operationsExecuted, executedOperations });
235
269
  }
236
270
 
271
+ /**
272
+ * Executes a data transform operation with the check → (skip or run) → check lifecycle.
273
+ *
274
+ * 1. If check is a query AST: render to SQL, execute. Empty result = already applied (skip).
275
+ * 2. If check is `true`: always skip. If `false`: always run.
276
+ * 3. Execute run ASTs (rendered to SQL) sequentially.
277
+ * 4. Re-execute check as post-run validation. If violations remain, fail.
278
+ */
279
+ private async executeDataTransform(
280
+ driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
281
+ op: DataTransformOperation,
282
+ options: { runIdempotency: boolean },
283
+ ): Promise<Result<void, SqlMigrationRunnerFailure>> {
284
+ // Step 1: Check (skip guard)
285
+ if (op.check === true) {
286
+ // Always skip, regardless of idempotency setting
287
+ return okVoid();
288
+ }
289
+ if (options.runIdempotency && op.check !== null && op.check !== false) {
290
+ const checkResult = await driver.query(op.check.sql, op.check.params);
291
+ if (checkResult.rows.length === 0) {
292
+ // No violations — already applied, skip
293
+ return okVoid();
294
+ }
295
+ }
296
+
297
+ // Step 2: Execute run steps
298
+ if (op.run) {
299
+ for (const plan of op.run) {
300
+ try {
301
+ await driver.query(plan.sql, plan.params);
302
+ } catch (error: unknown) {
303
+ if (SqlQueryError.is(error)) {
304
+ return runnerFailure(
305
+ 'EXECUTION_FAILED',
306
+ `Data transform "${op.name}" failed: ${error.message}`,
307
+ {
308
+ why: error.message,
309
+ meta: {
310
+ operationId: op.id,
311
+ dataTransformName: op.name,
312
+ sql: plan.sql,
313
+ sqlState: error.sqlState,
314
+ },
315
+ },
316
+ );
317
+ }
318
+ throw error;
319
+ }
320
+ }
321
+ }
322
+
323
+ // Step 3: Post-run validation (check again)
324
+ if (op.check !== null && op.check !== false) {
325
+ const checkResult = await driver.query(op.check.sql, op.check.params);
326
+ if (checkResult.rows.length > 0) {
327
+ return runnerFailure(
328
+ 'POSTCHECK_FAILED',
329
+ `Data transform "${op.name}" did not resolve all violations (${checkResult.rows.length} remaining)`,
330
+ {
331
+ why: `After executing the data transform, the check query still returns ${checkResult.rows.length} violation(s).`,
332
+ meta: {
333
+ operationId: op.id,
334
+ dataTransformName: op.name,
335
+ remainingViolations: checkResult.rows.length,
336
+ },
337
+ },
338
+ );
339
+ }
340
+ }
341
+
342
+ return okVoid();
343
+ }
344
+
237
345
  private async ensureControlTables(
238
346
  driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
239
347
  ): Promise<void> {
@@ -371,13 +479,13 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
371
479
  return Object.freeze({
372
480
  id: operation.id,
373
481
  label: operation.label,
374
- ...(operation.summary ? { summary: operation.summary } : {}),
482
+ ...ifDefined('summary', operation.summary),
375
483
  operationClass: operation.operationClass,
376
484
  target: operation.target, // Already frozen from plan creation
377
485
  precheck: Object.freeze([]),
378
486
  execute: Object.freeze([]),
379
487
  postcheck: frozenPostcheck,
380
- ...(operation.meta || mergedMeta ? { meta: mergedMeta } : {}),
488
+ ...ifDefined('meta', operation.meta || mergedMeta ? mergedMeta : undefined),
381
489
  });
382
490
  }
383
491
 
@@ -388,7 +496,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
388
496
  if (!marker) {
389
497
  return false;
390
498
  }
391
- if (marker.coreHash !== plan.destination.coreHash) {
499
+ if (marker.storageHash !== plan.destination.storageHash) {
392
500
  return false;
393
501
  }
394
502
  if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {
@@ -427,43 +535,31 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
427
535
  ): Result<void, SqlMigrationRunnerFailure> {
428
536
  const origin = plan.origin ?? null;
429
537
  if (!origin) {
430
- if (!marker) {
431
- return okVoid();
432
- }
433
- if (this.markerMatchesDestination(marker, plan)) {
434
- return okVoid();
435
- }
436
- return runnerFailure(
437
- 'MARKER_ORIGIN_MISMATCH',
438
- `Existing contract marker (${marker.coreHash}) does not match plan origin (no marker expected).`,
439
- {
440
- meta: {
441
- markerCoreHash: marker.coreHash,
442
- expectedOrigin: null,
443
- },
444
- },
445
- );
538
+ // No origin assertion on the plan — the caller does not want origin validation.
539
+ // This is the case for `db update`, which introspects the live schema and does not
540
+ // rely on marker continuity. `db init` handles its own marker checks before the runner.
541
+ return okVoid();
446
542
  }
447
543
 
448
544
  if (!marker) {
449
545
  return runnerFailure(
450
546
  'MARKER_ORIGIN_MISMATCH',
451
- `Missing contract marker: expected origin core hash ${origin.coreHash}.`,
547
+ `Missing contract marker: expected origin storage hash ${origin.storageHash}.`,
452
548
  {
453
549
  meta: {
454
- expectedOriginCoreHash: origin.coreHash,
550
+ expectedOriginStorageHash: origin.storageHash,
455
551
  },
456
552
  },
457
553
  );
458
554
  }
459
- if (marker.coreHash !== origin.coreHash) {
555
+ if (marker.storageHash !== origin.storageHash) {
460
556
  return runnerFailure(
461
557
  'MARKER_ORIGIN_MISMATCH',
462
- `Existing contract marker (${marker.coreHash}) does not match plan origin (${origin.coreHash}).`,
558
+ `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`,
463
559
  {
464
560
  meta: {
465
- markerCoreHash: marker.coreHash,
466
- expectedOriginCoreHash: origin.coreHash,
561
+ markerStorageHash: marker.storageHash,
562
+ expectedOriginStorageHash: origin.storageHash,
467
563
  },
468
564
  },
469
565
  );
@@ -487,14 +583,14 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
487
583
  destination: SqlMigrationPlanContractInfo,
488
584
  contract: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['destinationContract'],
489
585
  ): Result<void, SqlMigrationRunnerFailure> {
490
- if (destination.coreHash !== contract.coreHash) {
586
+ if (destination.storageHash !== contract.storage.storageHash) {
491
587
  return runnerFailure(
492
588
  'DESTINATION_CONTRACT_MISMATCH',
493
- `Plan destination core hash (${destination.coreHash}) does not match provided contract core hash (${contract.coreHash}).`,
589
+ `Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storage.storageHash}).`,
494
590
  {
495
591
  meta: {
496
- planCoreHash: destination.coreHash,
497
- contractCoreHash: contract.coreHash,
592
+ planStorageHash: destination.storageHash,
593
+ contractStorageHash: contract.storage.storageHash,
498
594
  },
499
595
  },
500
596
  );
@@ -524,11 +620,11 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
524
620
  existingMarker: ContractMarkerRecord | null,
525
621
  ): Promise<void> {
526
622
  const writeStatements = buildWriteMarkerStatements({
527
- coreHash: options.plan.destination.coreHash,
623
+ storageHash: options.plan.destination.storageHash,
528
624
  profileHash:
529
625
  options.plan.destination.profileHash ??
530
626
  options.destinationContract.profileHash ??
531
- options.plan.destination.coreHash,
627
+ options.plan.destination.storageHash,
532
628
  contractJson: options.destinationContract,
533
629
  canonicalVersion: null,
534
630
  meta: {},
@@ -544,13 +640,13 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
544
640
  executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
545
641
  ): Promise<void> {
546
642
  const ledgerStatement = buildLedgerInsertStatement({
547
- originCoreHash: existingMarker?.coreHash ?? null,
643
+ originStorageHash: existingMarker?.storageHash ?? null,
548
644
  originProfileHash: existingMarker?.profileHash ?? null,
549
- destinationCoreHash: options.plan.destination.coreHash,
645
+ destinationStorageHash: options.plan.destination.storageHash,
550
646
  destinationProfileHash:
551
647
  options.plan.destination.profileHash ??
552
648
  options.destinationContract.profileHash ??
553
- options.plan.destination.coreHash,
649
+ options.plan.destination.storageHash,
554
650
  contractJsonBefore: existingMarker?.contractJson ?? null,
555
651
  contractJsonAfter: options.destinationContract,
556
652
  operations: executedOperations,
@@ -38,7 +38,7 @@ export const ensureLedgerTableStatement: SqlStatement = {
38
38
  };
39
39
 
40
40
  export interface WriteMarkerInput {
41
- readonly coreHash: string;
41
+ readonly storageHash: string;
42
42
  readonly profileHash: string;
43
43
  readonly contractJson?: unknown;
44
44
  readonly canonicalVersion?: number | null;
@@ -52,7 +52,7 @@ export function buildWriteMarkerStatements(input: WriteMarkerInput): {
52
52
  } {
53
53
  const params: readonly unknown[] = [
54
54
  1,
55
- input.coreHash,
55
+ input.storageHash,
56
56
  input.profileHash,
57
57
  jsonParam(input.contractJson),
58
58
  input.canonicalVersion ?? null,
@@ -99,9 +99,9 @@ export function buildWriteMarkerStatements(input: WriteMarkerInput): {
99
99
  }
100
100
 
101
101
  export interface LedgerInsertInput {
102
- readonly originCoreHash?: string | null;
102
+ readonly originStorageHash?: string | null;
103
103
  readonly originProfileHash?: string | null;
104
- readonly destinationCoreHash: string;
104
+ readonly destinationStorageHash: string;
105
105
  readonly destinationProfileHash?: string | null;
106
106
  readonly contractJsonBefore?: unknown;
107
107
  readonly contractJsonAfter?: unknown;
@@ -128,9 +128,9 @@ export function buildLedgerInsertStatement(input: LedgerInsertInput): SqlStateme
128
128
  $7::jsonb
129
129
  )`,
130
130
  params: [
131
- input.originCoreHash ?? null,
131
+ input.originStorageHash ?? null,
132
132
  input.originProfileHash ?? null,
133
- input.destinationCoreHash,
133
+ input.destinationStorageHash,
134
134
  input.destinationProfileHash ?? null,
135
135
  jsonParam(input.contractJsonBefore),
136
136
  jsonParam(input.contractJsonAfter),
@@ -0,0 +1,5 @@
1
+ import type { ColumnDefault } from '@prisma-next/contract/types';
2
+
3
+ export type PostgresColumnDefault =
4
+ | ColumnDefault
5
+ | { readonly kind: 'sequence'; readonly name: string };
@@ -1,28 +1,130 @@
1
- import type {
2
- ControlTargetInstance,
3
- MigrationPlanner,
4
- MigrationRunner,
5
- } from '@prisma-next/core-control-plane/types';
1
+ import {
2
+ normalizeSchemaNativeType,
3
+ parsePostgresDefault,
4
+ } from '@prisma-next/adapter-postgres/control';
5
+ import type { ColumnDefault, Contract } from '@prisma-next/contract/types';
6
6
  import type {
7
7
  SqlControlFamilyInstance,
8
8
  SqlControlTargetDescriptor,
9
9
  } from '@prisma-next/family-sql/control';
10
+ import {
11
+ collectInitDependencies,
12
+ contractToSchemaIR,
13
+ extractCodecControlHooks,
14
+ } from '@prisma-next/family-sql/control';
15
+ import { MigrationDescriptorArraySchema } from '@prisma-next/family-sql/operation-descriptors';
16
+ import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
17
+ import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
18
+ import type {
19
+ ControlTargetInstance,
20
+ MigrationPlanner,
21
+ MigrationRunner,
22
+ OperationDescriptor,
23
+ } from '@prisma-next/framework-components/control';
24
+ import { sql } from '@prisma-next/sql-builder/runtime';
25
+ import type { SqlStorage, StorageColumn } from '@prisma-next/sql-contract/types';
26
+ import type { SqlOperationEntry } from '@prisma-next/sql-operations';
27
+ import { ifDefined } from '@prisma-next/utils/defined';
28
+ import { type } from 'arktype';
10
29
  import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
11
- import type { PostgresPlanTargetDetails } from '../core/migrations/planner';
30
+ import { planDescriptors } from '../core/migrations/descriptor-planner';
31
+ import { resolveOperations } from '../core/migrations/operation-resolver';
12
32
  import { createPostgresMigrationPlanner } from '../core/migrations/planner';
33
+ import { renderDefaultLiteral } from '../core/migrations/planner-ddl-builders';
34
+ import type { PostgresPlanTargetDetails } from '../core/migrations/planner-target-details';
13
35
  import { createPostgresMigrationRunner } from '../core/migrations/runner';
14
36
 
37
+ function parseDescriptors(descriptors: readonly OperationDescriptor[]) {
38
+ const result = MigrationDescriptorArraySchema([...descriptors]);
39
+ if (result instanceof type.errors) {
40
+ throw new Error(`Invalid migration descriptors:\n${result.summary}`);
41
+ }
42
+ return result;
43
+ }
44
+
45
+ function collectQueryOperationTypes(
46
+ frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', 'postgres'>>,
47
+ ): Readonly<Record<string, SqlOperationEntry>> {
48
+ const entries: Record<string, SqlOperationEntry> = {};
49
+ if (!frameworkComponents) return entries;
50
+ for (const component of frameworkComponents) {
51
+ const ops = (
52
+ component as {
53
+ queryOperations?: () => ReadonlyArray<{ method: string } & SqlOperationEntry>;
54
+ }
55
+ ).queryOperations?.();
56
+ if (!ops) continue;
57
+ for (const { method, ...entry } of ops) {
58
+ entries[method] = entry;
59
+ }
60
+ }
61
+ return entries;
62
+ }
63
+
15
64
  /**
16
- * Postgres target descriptor for CLI config.
65
+ * Creates a SQL DSL client for migration authoring.
66
+ * Only the fields used by the builder are populated — operations, codecs,
67
+ * and types are unused by sql() and stubbed to satisfy the ExecutionContext type.
17
68
  */
69
+ function createMigrationClient(
70
+ toContract: Contract<SqlStorage>,
71
+ frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', 'postgres'>>,
72
+ ) {
73
+ const queryOperationTypes = collectQueryOperationTypes(frameworkComponents);
74
+ // sql() only reads contract, queryOperations.entries(), and applyMutationDefaults
75
+ // from the context. The other fields are for runtime execution, not query building.
76
+ return sql({
77
+ context: {
78
+ contract: toContract,
79
+ queryOperations: { entries: () => queryOperationTypes },
80
+ applyMutationDefaults: () => [],
81
+ } as never,
82
+ });
83
+ }
84
+
85
+ function buildNativeTypeExpander(
86
+ frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', 'postgres'>>,
87
+ ) {
88
+ if (!frameworkComponents) {
89
+ return undefined;
90
+ }
91
+ const codecHooks = extractCodecControlHooks(frameworkComponents);
92
+ return (input: {
93
+ readonly nativeType: string;
94
+ readonly codecId?: string;
95
+ readonly typeParams?: Record<string, unknown>;
96
+ }) => {
97
+ if (!input.typeParams) return input.nativeType;
98
+
99
+ if (!input.codecId) {
100
+ throw new Error(
101
+ `Column declares typeParams for nativeType "${input.nativeType}" but has no codecId. ` +
102
+ 'Ensure the column is associated with a codec.',
103
+ );
104
+ }
105
+
106
+ const hooks = codecHooks.get(input.codecId);
107
+ if (!hooks?.expandNativeType) {
108
+ throw new Error(
109
+ `Column declares typeParams for nativeType "${input.nativeType}" ` +
110
+ `but no expandNativeType hook is registered for codecId "${input.codecId}". ` +
111
+ 'Ensure the extension providing this codec is included in extensionPacks.',
112
+ );
113
+ }
114
+ return hooks.expandNativeType(input);
115
+ };
116
+ }
117
+
118
+ export function postgresRenderDefault(def: ColumnDefault, column: StorageColumn): string {
119
+ if (def.kind === 'function') {
120
+ return def.expression;
121
+ }
122
+ return renderDefaultLiteral(def.value, column);
123
+ }
124
+
18
125
  const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails> =
19
126
  {
20
127
  ...postgresTargetDescriptorMeta,
21
- /**
22
- * Migrations capability for CLI to access planner/runner via core types.
23
- * The SQL-specific planner/runner types are compatible with the generic
24
- * MigrationPlanner/MigrationRunner interfaces at runtime.
25
- */
26
128
  migrations: {
27
129
  createPlanner(_family: SqlControlFamilyInstance) {
28
130
  return createPostgresMigrationPlanner() as MigrationPlanner<'sql', 'postgres'>;
@@ -30,6 +132,74 @@ const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresP
30
132
  createRunner(family) {
31
133
  return createPostgresMigrationRunner(family) as MigrationRunner<'sql', 'postgres'>;
32
134
  },
135
+ contractToSchema(contract, frameworkComponents) {
136
+ const expander = buildNativeTypeExpander(frameworkComponents);
137
+ return contractToSchemaIR(contract as Contract<SqlStorage> | null, {
138
+ annotationNamespace: 'pg',
139
+ ...ifDefined('expandNativeType', expander),
140
+ renderDefault: postgresRenderDefault,
141
+ frameworkComponents: frameworkComponents ?? [],
142
+ });
143
+ },
144
+ planWithDescriptors(context) {
145
+ const toContract = context.toContract as Contract<SqlStorage>;
146
+ const fromContract = context.fromContract as Contract<SqlStorage> | null;
147
+
148
+ // Synthesize schema IR from the fromContract (same as contractToSchema flow)
149
+ const expander = buildNativeTypeExpander(context.frameworkComponents);
150
+ const fromSchemaIR = contractToSchemaIR(fromContract, {
151
+ annotationNamespace: 'pg',
152
+ ...ifDefined('expandNativeType', expander),
153
+ renderDefault: postgresRenderDefault,
154
+ frameworkComponents: context.frameworkComponents ?? [],
155
+ });
156
+
157
+ // Collect schema issues via verifier
158
+ const verifyResult = verifySqlSchema({
159
+ contract: toContract,
160
+ schema: fromSchemaIR,
161
+ strict: true,
162
+ typeMetadataRegistry: new Map(),
163
+ frameworkComponents: context.frameworkComponents ?? [],
164
+ normalizeDefault: parsePostgresDefault,
165
+ normalizeNativeType: normalizeSchemaNativeType,
166
+ });
167
+
168
+ // Run descriptor planner
169
+ const planResult = planDescriptors({
170
+ issues: verifyResult.schema.issues,
171
+ toContract,
172
+ fromContract,
173
+ });
174
+ if (!planResult.ok) {
175
+ return { ok: false as const, conflicts: planResult.failure };
176
+ }
177
+
178
+ return {
179
+ ok: true as const,
180
+ descriptors: planResult.value.descriptors,
181
+ needsDataMigration: planResult.value.needsDataMigration,
182
+ };
183
+ },
184
+
185
+ resolveDescriptors(descriptors, context) {
186
+ const validated = parseDescriptors(descriptors);
187
+ const codecHooks = context.frameworkComponents
188
+ ? extractCodecControlHooks(context.frameworkComponents)
189
+ : new Map();
190
+ const dependencies = context.frameworkComponents
191
+ ? collectInitDependencies(context.frameworkComponents)
192
+ : [];
193
+ const toContract = context.toContract as Contract<SqlStorage>;
194
+ const db = createMigrationClient(toContract, context.frameworkComponents);
195
+ return resolveOperations(validated, {
196
+ toContract,
197
+ schemaName: context.schemaName ?? 'public',
198
+ codecHooks,
199
+ dependencies,
200
+ db,
201
+ });
202
+ },
33
203
  },
34
204
  create(): ControlTargetInstance<'sql', 'postgres'> {
35
205
  return {
@@ -0,0 +1,56 @@
1
+ // Re-export everything from the local operation-descriptors module,
2
+ // which itself re-exports structural descriptors from sql-family
3
+ // and adds postgres-specific data transform support.
4
+ export {
5
+ type AddColumnDescriptor,
6
+ type AddEnumValuesDescriptor,
7
+ type AddForeignKeyDescriptor,
8
+ type AddPrimaryKeyDescriptor,
9
+ type AddUniqueDescriptor,
10
+ type AlterColumnTypeDescriptor,
11
+ addColumn,
12
+ addEnumValues,
13
+ addForeignKey,
14
+ addPrimaryKey,
15
+ addUnique,
16
+ alterColumnType,
17
+ type Buildable,
18
+ builders,
19
+ type CreateDependencyDescriptor,
20
+ type CreateEnumTypeDescriptor,
21
+ type CreateIndexDescriptor,
22
+ type CreateTableDescriptor,
23
+ createBuilders,
24
+ createDependency,
25
+ createEnumType,
26
+ createIndex,
27
+ createTable,
28
+ type DataTransformDescriptor,
29
+ type DropColumnDescriptor,
30
+ type DropConstraintDescriptor,
31
+ type DropDefaultDescriptor,
32
+ type DropEnumTypeDescriptor,
33
+ type DropIndexDescriptor,
34
+ type DropNotNullDescriptor,
35
+ type DropTableDescriptor,
36
+ dataTransform,
37
+ dropColumn,
38
+ dropConstraint,
39
+ dropDefault,
40
+ dropEnumType,
41
+ dropIndex,
42
+ dropNotNull,
43
+ dropTable,
44
+ type PostgresMigrationOpDescriptor,
45
+ type QueryPlanInput,
46
+ type RenameTypeDescriptor,
47
+ type RunInput,
48
+ renameType,
49
+ type SetDefaultDescriptor,
50
+ type SetNotNullDescriptor,
51
+ type SqlMigrationOpDescriptor,
52
+ setDefault,
53
+ setNotNull,
54
+ TODO,
55
+ type TodoMarker,
56
+ } from '../core/migrations/operation-descriptors';
@@ -1,6 +1,10 @@
1
- import type { TargetPackRef } from '@prisma-next/contract/framework-components';
1
+ import type { CodecTypes } from '@prisma-next/adapter-postgres/codec-types';
2
+ import type { TargetPackRef } from '@prisma-next/framework-components/components';
2
3
  import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
3
4
 
4
- const postgresPack: TargetPackRef<'sql', 'postgres'> = postgresTargetDescriptorMeta;
5
+ const postgresPack = postgresTargetDescriptorMeta;
5
6
 
6
- export default postgresPack;
7
+ export default postgresPack as typeof postgresTargetDescriptorMeta &
8
+ TargetPackRef<'sql', 'postgres'> & {
9
+ readonly __codecTypes?: CodecTypes;
10
+ };
@@ -1,23 +1,17 @@
1
- import type {
2
- RuntimeTargetDescriptor,
3
- RuntimeTargetInstance,
4
- } from '@prisma-next/core-execution-plane/types';
1
+ import type { RuntimeTargetInstance } from '@prisma-next/framework-components/execution';
2
+ import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
3
+ import type { SqlRuntimeTargetDescriptor } from '@prisma-next/sql-runtime';
5
4
  import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
6
5
 
7
- /**
8
- * Postgres runtime target instance interface.
9
- */
10
6
  export interface PostgresRuntimeTargetInstance extends RuntimeTargetInstance<'sql', 'postgres'> {}
11
7
 
12
- /**
13
- * Postgres target descriptor for runtime plane.
14
- */
15
- const postgresRuntimeTargetDescriptor: RuntimeTargetDescriptor<
16
- 'sql',
8
+ const postgresRuntimeTargetDescriptor: SqlRuntimeTargetDescriptor<
17
9
  'postgres',
18
10
  PostgresRuntimeTargetInstance
19
11
  > = {
20
12
  ...postgresTargetDescriptorMeta,
13
+ codecs: () => createCodecRegistry(),
14
+ parameterizedCodecs: () => [],
21
15
  create(): PostgresRuntimeTargetInstance {
22
16
  return {
23
17
  familyId: 'sql',
@@ -1,14 +0,0 @@
1
- // src/core/descriptor-meta.ts
2
- var postgresTargetDescriptorMeta = {
3
- kind: "target",
4
- familyId: "sql",
5
- targetId: "postgres",
6
- id: "postgres",
7
- version: "0.0.1",
8
- capabilities: {}
9
- };
10
-
11
- export {
12
- postgresTargetDescriptorMeta
13
- };
14
- //# sourceMappingURL=chunk-RKEXRSSI.js.map