@prisma-next/target-postgres 0.13.0 → 0.14.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 (190) hide show
  1. package/dist/{codec-ids-CTikp1if.mjs → codec-ids-BvytN2P8.mjs} +3 -3
  2. package/dist/codec-ids-BvytN2P8.mjs.map +1 -0
  3. package/dist/{codec-ids-B1vOchLE.d.mts → codec-ids-CnXu9Qy3.d.mts} +3 -3
  4. package/dist/codec-ids-CnXu9Qy3.d.mts.map +1 -0
  5. package/dist/codec-ids.d.mts +2 -2
  6. package/dist/codec-ids.mjs +2 -2
  7. package/dist/{codec-types-CnFiNML4.d.mts → codec-types-DHCkwPKE.d.mts} +3 -3
  8. package/dist/{codec-types-CnFiNML4.d.mts.map → codec-types-DHCkwPKE.d.mts.map} +1 -1
  9. package/dist/codec-types.d.mts +1 -1
  10. package/dist/{codecs-CBpEv4s5.d.mts → codecs--0A5_4Bq.d.mts} +26 -23
  11. package/dist/codecs--0A5_4Bq.d.mts.map +1 -0
  12. package/dist/codecs.d.mts +2 -2
  13. package/dist/codecs.mjs +28 -35
  14. package/dist/codecs.mjs.map +1 -1
  15. package/dist/contract-free.d.mts +163 -15
  16. package/dist/contract-free.d.mts.map +1 -1
  17. package/dist/contract-free.mjs +4 -17
  18. package/dist/contract-free.mjs.map +1 -1
  19. package/dist/control.d.mts.map +1 -1
  20. package/dist/control.mjs +21 -27
  21. package/dist/control.mjs.map +1 -1
  22. package/dist/{data-transform-D25tLeYU.mjs → data-transform-BOWpliq8.mjs} +9 -17
  23. package/dist/data-transform-BOWpliq8.mjs.map +1 -0
  24. package/dist/{data-transform-DGOqcLrf.d.mts → data-transform-DDgWdB5o.d.mts} +2 -2
  25. package/dist/data-transform-DDgWdB5o.d.mts.map +1 -0
  26. package/dist/data-transform.d.mts +1 -1
  27. package/dist/data-transform.mjs +1 -1
  28. package/dist/ddl-QDyOSeLc.mjs +251 -0
  29. package/dist/ddl-QDyOSeLc.mjs.map +1 -0
  30. package/dist/ddl.d.mts +2 -2
  31. package/dist/ddl.mjs +2 -2
  32. package/dist/descriptor-meta-CpGygXpI.mjs +140 -0
  33. package/dist/descriptor-meta-CpGygXpI.mjs.map +1 -0
  34. package/dist/{issue-planner-Br0pt1Ea.mjs → issue-planner-DL6g3CmE.mjs} +52 -366
  35. package/dist/issue-planner-DL6g3CmE.mjs.map +1 -0
  36. package/dist/issue-planner.d.mts +8 -11
  37. package/dist/issue-planner.d.mts.map +1 -1
  38. package/dist/issue-planner.mjs +1 -1
  39. package/dist/migration.d.mts +5 -92
  40. package/dist/migration.d.mts.map +1 -1
  41. package/dist/migration.mjs +4 -4
  42. package/dist/{nodes-DZk2JZG3.mjs → nodes-Bbhs2rwj.mjs} +31 -2
  43. package/dist/nodes-Bbhs2rwj.mjs.map +1 -0
  44. package/dist/{nodes-779hmCfL.d.mts → nodes-pLeLgdis.d.mts} +30 -3
  45. package/dist/nodes-pLeLgdis.d.mts.map +1 -0
  46. package/dist/{op-factory-call-D2aAUhmS.mjs → op-factory-call-D_p5vxwt.mjs} +601 -418
  47. package/dist/op-factory-call-D_p5vxwt.mjs.map +1 -0
  48. package/dist/{op-factory-call-DMA86_2D.d.mts → op-factory-call-DmQEc3XV.d.mts} +119 -72
  49. package/dist/op-factory-call-DmQEc3XV.d.mts.map +1 -0
  50. package/dist/op-factory-call.d.mts +2 -2
  51. package/dist/op-factory-call.mjs +2 -2
  52. package/dist/pack.d.mts +36 -15
  53. package/dist/pack.d.mts.map +1 -1
  54. package/dist/pack.mjs +1 -1
  55. package/dist/{planner-CAYPJObw.mjs → planner-Bs_baQax.mjs} +25 -45
  56. package/dist/planner-Bs_baQax.mjs.map +1 -0
  57. package/dist/{planner-ddl-builders-Cw2n2llW.mjs → planner-ddl-builders-B2wOwLqI.mjs} +2 -2
  58. package/dist/planner-ddl-builders-B2wOwLqI.mjs.map +1 -0
  59. package/dist/planner-ddl-builders.d.mts +4 -4
  60. package/dist/planner-ddl-builders.d.mts.map +1 -1
  61. package/dist/planner-ddl-builders.mjs +1 -1
  62. package/dist/{planner-identity-values-BIpa5p2I.mjs → planner-identity-values-CJPha2Sz.mjs} +3 -9
  63. package/dist/planner-identity-values-CJPha2Sz.mjs.map +1 -0
  64. package/dist/planner-identity-values.d.mts +1 -1
  65. package/dist/planner-identity-values.d.mts.map +1 -1
  66. package/dist/planner-identity-values.mjs +1 -1
  67. package/dist/{planner-produced-postgres-migration-NSEhWL0L.mjs → planner-produced-postgres-migration-Cji5vxUf.mjs} +6 -4
  68. package/dist/planner-produced-postgres-migration-Cji5vxUf.mjs.map +1 -0
  69. package/dist/{planner-produced-postgres-migration-B4EDvLdz.d.mts → planner-produced-postgres-migration-QqHa2C2l.d.mts} +5 -6
  70. package/dist/planner-produced-postgres-migration-QqHa2C2l.d.mts.map +1 -0
  71. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  72. package/dist/planner-produced-postgres-migration.mjs +1 -1
  73. package/dist/planner-sql-checks-jqUUGyQR.mjs +152 -0
  74. package/dist/planner-sql-checks-jqUUGyQR.mjs.map +1 -0
  75. package/dist/planner-sql-checks.d.mts +3 -49
  76. package/dist/planner-sql-checks.d.mts.map +1 -1
  77. package/dist/planner-sql-checks.mjs +2 -2
  78. package/dist/{planner-type-resolution-836DExFN.mjs → planner-type-resolution-Bt2f_q-F.mjs} +1 -6
  79. package/dist/planner-type-resolution-Bt2f_q-F.mjs.map +1 -0
  80. package/dist/planner.d.mts +4 -4
  81. package/dist/planner.d.mts.map +1 -1
  82. package/dist/planner.mjs +1 -1
  83. package/dist/{postgres-contract-serializer-DYTyXjPf.mjs → postgres-contract-serializer-k3TAcPMY.mjs} +30 -37
  84. package/dist/postgres-contract-serializer-k3TAcPMY.mjs.map +1 -0
  85. package/dist/postgres-migration-B5jKrXv3.mjs +145 -0
  86. package/dist/postgres-migration-B5jKrXv3.mjs.map +1 -0
  87. package/dist/postgres-migration-Y4YBJqkS.d.mts +181 -0
  88. package/dist/postgres-migration-Y4YBJqkS.d.mts.map +1 -0
  89. package/dist/{postgres-schema-BuxCxbvB.mjs → postgres-schema-COGZ1ark.mjs} +82 -23
  90. package/dist/postgres-schema-COGZ1ark.mjs.map +1 -0
  91. package/dist/{render-ops-BpjstrKQ.mjs → render-ops-BREh1kHe.mjs} +10 -5
  92. package/dist/render-ops-BREh1kHe.mjs.map +1 -0
  93. package/dist/render-ops.d.mts +2 -2
  94. package/dist/render-ops.d.mts.map +1 -1
  95. package/dist/render-ops.mjs +1 -1
  96. package/dist/runtime.d.mts +1 -0
  97. package/dist/runtime.d.mts.map +1 -1
  98. package/dist/runtime.mjs +2 -2
  99. package/dist/table-source-BvFo7gVs.d.mts +15 -0
  100. package/dist/table-source-BvFo7gVs.d.mts.map +1 -0
  101. package/dist/types.d.mts +34 -19
  102. package/dist/types.d.mts.map +1 -1
  103. package/dist/types.mjs +2 -3
  104. package/package.json +17 -18
  105. package/src/contract-free/checks.ts +363 -0
  106. package/src/contract-free/ddl.ts +28 -1
  107. package/src/core/authoring.ts +43 -44
  108. package/src/core/codec-helpers.ts +0 -17
  109. package/src/core/codec-ids.ts +1 -1
  110. package/src/core/codec-type-map.ts +2 -2
  111. package/src/core/codecs.ts +43 -48
  112. package/src/core/ddl/nodes.ts +59 -1
  113. package/src/core/migrations/control-policy.ts +17 -47
  114. package/src/core/migrations/issue-planner.ts +34 -70
  115. package/src/core/migrations/op-factory-call.ts +486 -215
  116. package/src/core/migrations/operations/columns.ts +175 -140
  117. package/src/core/migrations/operations/constraints.ts +79 -108
  118. package/src/core/migrations/operations/data-transform.ts +15 -18
  119. package/src/core/migrations/operations/dependencies.ts +16 -14
  120. package/src/core/migrations/operations/indexes.ts +31 -28
  121. package/src/core/migrations/operations/shared.ts +2 -2
  122. package/src/core/migrations/operations/tables.ts +13 -14
  123. package/src/core/migrations/planner-ddl-builders.ts +3 -4
  124. package/src/core/migrations/planner-identity-values.ts +4 -28
  125. package/src/core/migrations/planner-produced-postgres-migration.ts +15 -7
  126. package/src/core/migrations/planner-recipes.ts +44 -39
  127. package/src/core/migrations/planner-sql-checks.ts +3 -178
  128. package/src/core/migrations/planner-strategies.ts +76 -449
  129. package/src/core/migrations/planner-type-resolution.ts +2 -20
  130. package/src/core/migrations/planner.ts +6 -6
  131. package/src/core/migrations/postgres-migration.ts +287 -7
  132. package/src/core/migrations/render-ops.ts +26 -13
  133. package/src/core/migrations/runner.ts +26 -20
  134. package/src/core/postgres-contract-serializer.ts +37 -54
  135. package/src/core/postgres-enum-type-schema.ts +17 -0
  136. package/src/core/postgres-schema.ts +86 -46
  137. package/src/exports/codecs.ts +2 -2
  138. package/src/exports/contract-free.ts +22 -1
  139. package/src/exports/control.ts +0 -22
  140. package/src/exports/ddl.ts +4 -0
  141. package/src/exports/migration.ts +1 -29
  142. package/src/exports/op-factory-call.ts +0 -4
  143. package/src/exports/planner-sql-checks.ts +0 -7
  144. package/src/exports/types.ts +0 -1
  145. package/dist/codec-ids-B1vOchLE.d.mts.map +0 -1
  146. package/dist/codec-ids-CTikp1if.mjs.map +0 -1
  147. package/dist/codecs-CBpEv4s5.d.mts.map +0 -1
  148. package/dist/data-transform-D25tLeYU.mjs.map +0 -1
  149. package/dist/data-transform-DGOqcLrf.d.mts.map +0 -1
  150. package/dist/ddl-77SyXgFt.mjs +0 -30
  151. package/dist/ddl-77SyXgFt.mjs.map +0 -1
  152. package/dist/descriptor-meta-DKmj-IMN.mjs +0 -14
  153. package/dist/descriptor-meta-DKmj-IMN.mjs.map +0 -1
  154. package/dist/descriptor-meta-runtime-My8_s4cs.mjs +0 -130
  155. package/dist/descriptor-meta-runtime-My8_s4cs.mjs.map +0 -1
  156. package/dist/enum-planning-BCyvlFHk.mjs +0 -0
  157. package/dist/enum-planning-BCyvlFHk.mjs.map +0 -1
  158. package/dist/enum-planning.d.mts +0 -86
  159. package/dist/enum-planning.d.mts.map +0 -1
  160. package/dist/enum-planning.mjs +0 -2
  161. package/dist/issue-planner-Br0pt1Ea.mjs.map +0 -1
  162. package/dist/nodes-779hmCfL.d.mts.map +0 -1
  163. package/dist/nodes-DZk2JZG3.mjs.map +0 -1
  164. package/dist/op-factory-call-D2aAUhmS.mjs.map +0 -1
  165. package/dist/op-factory-call-DMA86_2D.d.mts.map +0 -1
  166. package/dist/planner-CAYPJObw.mjs.map +0 -1
  167. package/dist/planner-ddl-builders-Cw2n2llW.mjs.map +0 -1
  168. package/dist/planner-identity-values-BIpa5p2I.mjs.map +0 -1
  169. package/dist/planner-produced-postgres-migration-B4EDvLdz.d.mts.map +0 -1
  170. package/dist/planner-produced-postgres-migration-NSEhWL0L.mjs.map +0 -1
  171. package/dist/planner-sql-checks-DAdhnI2c.mjs +0 -272
  172. package/dist/planner-sql-checks-DAdhnI2c.mjs.map +0 -1
  173. package/dist/planner-type-resolution-836DExFN.mjs.map +0 -1
  174. package/dist/postgres-contract-serializer-DYTyXjPf.mjs.map +0 -1
  175. package/dist/postgres-enum-type-BVn63a89.d.mts +0 -72
  176. package/dist/postgres-enum-type-BVn63a89.d.mts.map +0 -1
  177. package/dist/postgres-enum-type-DPKqCBem.mjs +0 -62
  178. package/dist/postgres-enum-type-DPKqCBem.mjs.map +0 -1
  179. package/dist/postgres-migration-COore9Mz.mjs +0 -71
  180. package/dist/postgres-migration-COore9Mz.mjs.map +0 -1
  181. package/dist/postgres-migration-DZ_gLUOW.d.mts +0 -72
  182. package/dist/postgres-migration-DZ_gLUOW.d.mts.map +0 -1
  183. package/dist/postgres-schema-BuxCxbvB.mjs.map +0 -1
  184. package/dist/render-ops-BpjstrKQ.mjs.map +0 -1
  185. package/dist/shared-DarONYBZ.d.mts +0 -43
  186. package/dist/shared-DarONYBZ.d.mts.map +0 -1
  187. package/src/core/migrations/enum-planning.ts +0 -213
  188. package/src/core/migrations/operations/enums.ts +0 -114
  189. package/src/core/postgres-enum-type.ts +0 -89
  190. package/src/exports/enum-planning.ts +0 -11
@@ -1,9 +1,4 @@
1
- import {
2
- isPostgresEnumStorageEntry,
3
- type PostgresEnumStorageEntry,
4
- type StorageColumn,
5
- type StorageTypeInstance,
6
- } from '@prisma-next/sql-contract/types';
1
+ import type { StorageColumn, StorageTypeInstance } from '@prisma-next/sql-contract/types';
7
2
 
8
3
  export type ResolvedColumnTypeMetadata = Pick<
9
4
  StorageColumn,
@@ -12,7 +7,7 @@ export type ResolvedColumnTypeMetadata = Pick<
12
7
 
13
8
  export function resolveColumnTypeMetadata(
14
9
  column: StorageColumn,
15
- storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,
10
+ storageTypes: Readonly<Record<string, StorageTypeInstance>>,
16
11
  ): ResolvedColumnTypeMetadata {
17
12
  if (!column.typeRef) {
18
13
  return column;
@@ -23,19 +18,6 @@ export function resolveColumnTypeMetadata(
23
18
  return column;
24
19
  }
25
20
 
26
- if (isPostgresEnumStorageEntry(referencedType)) {
27
- // Enum types are referenced by name (`quoteIdentifier(nativeType)`),
28
- // not via parameterised codec expansion. The structural shape
29
- // carries `codecId` as an enumerable property (mirroring the
30
- // codec-typed view); `typeParams` is intentionally omitted here so
31
- // `expandParameterizedTypeSql` does not try to look up a
32
- // (deliberately absent) `expandNativeType` hook for `pg/enum@*`.
33
- return {
34
- codecId: referencedType.codecId,
35
- nativeType: referencedType.nativeType,
36
- };
37
- }
38
-
39
21
  return {
40
22
  codecId: referencedType.codecId,
41
23
  nativeType: referencedType.nativeType,
@@ -12,7 +12,7 @@ import {
12
12
  planFieldEventOperations,
13
13
  plannerFailure,
14
14
  } from '@prisma-next/family-sql/control';
15
- import type { Lowerer } from '@prisma-next/family-sql/control-adapter';
15
+ import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
16
16
  import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
17
17
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
18
18
  import type {
@@ -31,7 +31,6 @@ import {
31
31
  resolvePostgresIssueControlPolicySubject,
32
32
  resolvePostgresIssueCreationFactoryName,
33
33
  } from './control-policy';
34
- import { createResolveExistingEnumValues } from './enum-planning';
35
34
  import { planIssues } from './issue-planner';
36
35
  import type { PostgresOpFactoryCall } from './op-factory-call';
37
36
  import { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';
@@ -52,7 +51,9 @@ type VerifySqlSchemaOptionsWithComponents = Parameters<typeof verifySqlSchema>[0
52
51
  readonly frameworkComponents: PlannerFrameworkComponents;
53
52
  };
54
53
 
55
- export function createPostgresMigrationPlanner(lowerer: Lowerer): PostgresMigrationPlanner {
54
+ export function createPostgresMigrationPlanner(
55
+ lowerer: ExecuteRequestLowerer,
56
+ ): PostgresMigrationPlanner {
56
57
  return new PostgresMigrationPlanner(lowerer);
57
58
  }
58
59
 
@@ -88,9 +89,9 @@ export type PostgresPlanResult =
88
89
  * authoring surface.
89
90
  */
90
91
  export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgres'> {
91
- readonly #lowerer: Lowerer | undefined;
92
+ readonly #lowerer: ExecuteRequestLowerer | undefined;
92
93
 
93
- constructor(lowerer?: Lowerer) {
94
+ constructor(lowerer?: ExecuteRequestLowerer) {
94
95
  this.#lowerer = lowerer;
95
96
  }
96
97
 
@@ -266,7 +267,6 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
266
267
  frameworkComponents: options.frameworkComponents,
267
268
  normalizeDefault: parsePostgresDefault,
268
269
  normalizeNativeType: normalizeSchemaNativeType,
269
- resolveExistingEnumValues: createResolveExistingEnumValues(options.contract.storage),
270
270
  };
271
271
  const verifyResult = verifySqlSchema(verifyOptions);
272
272
  // Schema presence is a Postgres-specific concern (no equivalent in
@@ -3,12 +3,34 @@ import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control'
3
3
  import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
4
4
  import { Migration as SqlMigration } from '@prisma-next/family-sql/migration';
5
5
  import type { ControlStack } from '@prisma-next/framework-components/control';
6
- import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
7
6
  import type { SqlStorage } from '@prisma-next/sql-contract/types';
8
7
  import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
9
8
  import { errorPostgresMigrationStackMissing } from '../errors';
10
- import { CreateSchemaCall, CreateTableCall } from './op-factory-call';
9
+ import {
10
+ AddCheckConstraintCall,
11
+ AddColumnCall,
12
+ AddForeignKeyCall,
13
+ AddPrimaryKeyCall,
14
+ AddUniqueCall,
15
+ AlterColumnTypeCall,
16
+ type AlterColumnTypeOptions,
17
+ CreateIndexCall,
18
+ CreateSchemaCall,
19
+ CreateTableCall,
20
+ DropCheckConstraintCall,
21
+ DropColumnCall,
22
+ DropConstraintCall,
23
+ DropDefaultCall,
24
+ DropIndexCall,
25
+ DropNotNullCall,
26
+ DropTableCall,
27
+ SetDefaultCall,
28
+ SetNotNullCall,
29
+ } from './op-factory-call';
11
30
  import { type DataTransformOptions, dataTransform } from './operations/data-transform';
31
+ import { installExtension } from './operations/dependencies';
32
+ import type { CreateIndexExtras } from './operations/indexes';
33
+ import type { ForeignKeySpec } from './operations/shared';
12
34
  import type { PostgresPlanTargetDetails } from './planner-target-details';
13
35
 
14
36
  /**
@@ -30,6 +52,13 @@ import type { PostgresPlanTargetDetails } from './planner-target-details';
30
52
  * instance method forwards to the free `dataTransform` factory with that
31
53
  * stored adapter, so user migrations can write `this.dataTransform(...)`
32
54
  * without threading the adapter through every call.
55
+ *
56
+ * Every method requires an explicit `schema`. Postgres migrations name their
57
+ * schema deliberately — there is no default and no `search_path`-relative
58
+ * option. A migration that left the schema unspecified would resolve against
59
+ * whatever `search_path` the connection happened to carry, and that ambiguity
60
+ * is an antipattern in a migration. (The unbound/unspecified namespace concept
61
+ * remains for SQLite, which has no schemas, and for Mongo's connection `db`.)
33
62
  */
34
63
  export abstract class PostgresMigration extends SqlMigration<
35
64
  PostgresPlanTargetDetails,
@@ -64,7 +93,7 @@ export abstract class PostgresMigration extends SqlMigration<
64
93
  contract: TContract,
65
94
  name: string,
66
95
  options: DataTransformOptions,
67
- ): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {
96
+ ): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
68
97
  if (!this.controlAdapter) {
69
98
  throw errorPostgresMigrationStackMissing();
70
99
  }
@@ -77,17 +106,17 @@ export abstract class PostgresMigration extends SqlMigration<
77
106
  * Throws if no adapter is present (i.e. migration instantiated without a stack).
78
107
  */
79
108
  protected createTable(options: {
80
- readonly schema?: string;
109
+ readonly schema: string;
81
110
  readonly table: string;
82
111
  readonly ifNotExists?: boolean;
83
112
  readonly columns: readonly DdlColumn[];
84
113
  readonly constraints?: readonly DdlTableConstraint[];
85
- }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {
114
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
86
115
  if (!this.controlAdapter) {
87
116
  throw errorPostgresMigrationStackMissing();
88
117
  }
89
118
  return new CreateTableCall(
90
- options.schema ?? UNBOUND_NAMESPACE_ID,
119
+ options.schema,
91
120
  options.table,
92
121
  options.columns,
93
122
  options.constraints,
@@ -102,10 +131,261 @@ export abstract class PostgresMigration extends SqlMigration<
102
131
  protected createSchema(options: {
103
132
  readonly schema: string;
104
133
  readonly ifNotExists?: boolean;
105
- }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {
134
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
106
135
  if (!this.controlAdapter) {
107
136
  throw errorPostgresMigrationStackMissing();
108
137
  }
109
138
  return new CreateSchemaCall(options.schema).toOp(this.controlAdapter);
110
139
  }
140
+
141
+ protected addColumn(options: {
142
+ readonly schema: string;
143
+ readonly table: string;
144
+ readonly column: DdlColumn;
145
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
146
+ if (!this.controlAdapter) {
147
+ throw errorPostgresMigrationStackMissing();
148
+ }
149
+ return new AddColumnCall(options.schema, options.table, options.column).toOp(
150
+ this.controlAdapter,
151
+ );
152
+ }
153
+
154
+ protected addPrimaryKey(options: {
155
+ readonly schema: string;
156
+ readonly table: string;
157
+ readonly constraint: string;
158
+ readonly columns: readonly string[];
159
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
160
+ if (!this.controlAdapter) {
161
+ throw errorPostgresMigrationStackMissing();
162
+ }
163
+ return new AddPrimaryKeyCall(
164
+ options.schema,
165
+ options.table,
166
+ options.constraint,
167
+ options.columns,
168
+ ).toOp(this.controlAdapter);
169
+ }
170
+
171
+ protected addUnique(options: {
172
+ readonly schema: string;
173
+ readonly table: string;
174
+ readonly constraint: string;
175
+ readonly columns: readonly string[];
176
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
177
+ if (!this.controlAdapter) {
178
+ throw errorPostgresMigrationStackMissing();
179
+ }
180
+ return new AddUniqueCall(
181
+ options.schema,
182
+ options.table,
183
+ options.constraint,
184
+ options.columns,
185
+ ).toOp(this.controlAdapter);
186
+ }
187
+
188
+ protected addForeignKey(options: {
189
+ readonly schema: string;
190
+ readonly table: string;
191
+ readonly foreignKey: ForeignKeySpec;
192
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
193
+ if (!this.controlAdapter) {
194
+ throw errorPostgresMigrationStackMissing();
195
+ }
196
+ return new AddForeignKeyCall(options.schema, options.table, options.foreignKey).toOp(
197
+ this.controlAdapter,
198
+ );
199
+ }
200
+
201
+ protected addCheckConstraint(options: {
202
+ readonly schema: string;
203
+ readonly table: string;
204
+ readonly constraint: string;
205
+ readonly column: string;
206
+ readonly values: readonly string[];
207
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
208
+ if (!this.controlAdapter) {
209
+ throw errorPostgresMigrationStackMissing();
210
+ }
211
+ return new AddCheckConstraintCall(
212
+ options.schema,
213
+ options.table,
214
+ options.constraint,
215
+ options.column,
216
+ options.values,
217
+ ).toOp(this.controlAdapter);
218
+ }
219
+
220
+ protected dropCheckConstraint(options: {
221
+ readonly schema: string;
222
+ readonly table: string;
223
+ readonly constraint: string;
224
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
225
+ if (!this.controlAdapter) {
226
+ throw errorPostgresMigrationStackMissing();
227
+ }
228
+ return new DropCheckConstraintCall(options.schema, options.table, options.constraint).toOp(
229
+ this.controlAdapter,
230
+ );
231
+ }
232
+
233
+ protected dropConstraint(options: {
234
+ readonly schema: string;
235
+ readonly table: string;
236
+ readonly constraint: string;
237
+ readonly kind?: 'foreignKey' | 'unique' | 'primaryKey';
238
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
239
+ if (!this.controlAdapter) {
240
+ throw errorPostgresMigrationStackMissing();
241
+ }
242
+ return new DropConstraintCall(
243
+ options.schema,
244
+ options.table,
245
+ options.constraint,
246
+ options.kind ?? 'unique',
247
+ ).toOp(this.controlAdapter);
248
+ }
249
+
250
+ protected dropTable(options: {
251
+ readonly schema: string;
252
+ readonly table: string;
253
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
254
+ if (!this.controlAdapter) {
255
+ throw errorPostgresMigrationStackMissing();
256
+ }
257
+ return new DropTableCall(options.schema, options.table).toOp(this.controlAdapter);
258
+ }
259
+
260
+ protected dropColumn(options: {
261
+ readonly schema: string;
262
+ readonly table: string;
263
+ readonly column: string;
264
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
265
+ if (!this.controlAdapter) {
266
+ throw errorPostgresMigrationStackMissing();
267
+ }
268
+ return new DropColumnCall(options.schema, options.table, options.column).toOp(
269
+ this.controlAdapter,
270
+ );
271
+ }
272
+
273
+ protected alterColumnType(options: {
274
+ readonly schema: string;
275
+ readonly table: string;
276
+ readonly column: string;
277
+ readonly options: AlterColumnTypeOptions;
278
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
279
+ if (!this.controlAdapter) {
280
+ throw errorPostgresMigrationStackMissing();
281
+ }
282
+ return new AlterColumnTypeCall(
283
+ options.schema,
284
+ options.table,
285
+ options.column,
286
+ options.options,
287
+ ).toOp(this.controlAdapter);
288
+ }
289
+
290
+ protected setNotNull(options: {
291
+ readonly schema: string;
292
+ readonly table: string;
293
+ readonly column: string;
294
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
295
+ if (!this.controlAdapter) {
296
+ throw errorPostgresMigrationStackMissing();
297
+ }
298
+ return new SetNotNullCall(options.schema, options.table, options.column).toOp(
299
+ this.controlAdapter,
300
+ );
301
+ }
302
+
303
+ protected dropNotNull(options: {
304
+ readonly schema: string;
305
+ readonly table: string;
306
+ readonly column: string;
307
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
308
+ if (!this.controlAdapter) {
309
+ throw errorPostgresMigrationStackMissing();
310
+ }
311
+ return new DropNotNullCall(options.schema, options.table, options.column).toOp(
312
+ this.controlAdapter,
313
+ );
314
+ }
315
+
316
+ protected setDefault(options: {
317
+ readonly schema: string;
318
+ readonly table: string;
319
+ readonly column: string;
320
+ readonly defaultSql: string;
321
+ readonly operationClass?: 'additive' | 'widening';
322
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
323
+ if (!this.controlAdapter) {
324
+ throw errorPostgresMigrationStackMissing();
325
+ }
326
+ return new SetDefaultCall(
327
+ options.schema,
328
+ options.table,
329
+ options.column,
330
+ options.defaultSql,
331
+ options.operationClass,
332
+ ).toOp(this.controlAdapter);
333
+ }
334
+
335
+ protected dropDefault(options: {
336
+ readonly schema: string;
337
+ readonly table: string;
338
+ readonly column: string;
339
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
340
+ if (!this.controlAdapter) {
341
+ throw errorPostgresMigrationStackMissing();
342
+ }
343
+ return new DropDefaultCall(options.schema, options.table, options.column).toOp(
344
+ this.controlAdapter,
345
+ );
346
+ }
347
+
348
+ protected createIndex(options: {
349
+ readonly schema: string;
350
+ readonly table: string;
351
+ readonly index: string;
352
+ readonly columns: readonly string[];
353
+ readonly extras?: CreateIndexExtras;
354
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
355
+ if (!this.controlAdapter) {
356
+ throw errorPostgresMigrationStackMissing();
357
+ }
358
+ return new CreateIndexCall(
359
+ options.schema,
360
+ options.table,
361
+ options.index,
362
+ options.columns,
363
+ options.extras,
364
+ ).toOp(this.controlAdapter);
365
+ }
366
+
367
+ protected dropIndex(options: {
368
+ readonly schema: string;
369
+ readonly table: string;
370
+ readonly index: string;
371
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
372
+ if (!this.controlAdapter) {
373
+ throw errorPostgresMigrationStackMissing();
374
+ }
375
+ return new DropIndexCall(options.schema, options.table, options.index).toOp(
376
+ this.controlAdapter,
377
+ );
378
+ }
379
+
380
+ protected installExtension(options: {
381
+ readonly extensionName: string;
382
+ readonly invariantId: string;
383
+ readonly id: string;
384
+ readonly label?: string;
385
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
386
+ if (!this.controlAdapter) {
387
+ throw errorPostgresMigrationStackMissing();
388
+ }
389
+ return installExtension(options, this.controlAdapter);
390
+ }
111
391
  }
@@ -1,7 +1,11 @@
1
1
  import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';
2
- import type { Lowerer } from '@prisma-next/family-sql/control-adapter';
3
- import type { OpFactoryCall } from '@prisma-next/framework-components/control';
2
+ import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
3
+ import type {
4
+ MigrationPlanOperation,
5
+ OpFactoryCall,
6
+ } from '@prisma-next/framework-components/control';
4
7
  import { blindCast } from '@prisma-next/utils/casts';
8
+ import { isThenable } from '@prisma-next/utils/promise';
5
9
  import type { PostgresPlanTargetDetails } from './planner-target-details';
6
10
 
7
11
  type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
@@ -13,11 +17,11 @@ type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
13
17
  * silently flow through to postgres-shaped renderers — exactly the
14
18
  * place to fail loudly with op metadata (`id` + `target.id`).
15
19
  */
16
- function assertPostgresOp(
17
- op: ReturnType<OpFactoryCall['toOp']>,
18
- callFactoryName: string,
19
- ): asserts op is Op {
20
- const targetId = (op as Partial<Op>).target?.id;
20
+ function assertPostgresOp(op: MigrationPlanOperation, callFactoryName: string): asserts op is Op {
21
+ const targetId = blindCast<
22
+ { target?: { id?: string } },
23
+ 'op.target is present on concrete SqlMigrationPlanOperation but absent on the framework MigrationPlanOperation base'
24
+ >(op).target?.id;
21
25
  if (targetId !== 'postgres') {
22
26
  throw new Error(
23
27
  `renderOps: expected postgres op but got target.id="${String(targetId)}" for op.id="${op.id}" (factoryName="${callFactoryName}"). An OpFactoryCall produced an op for a different target on the postgres planner path; check the call's target binding.`,
@@ -25,13 +29,22 @@ function assertPostgresOp(
25
29
  }
26
30
  }
27
31
 
28
- export function renderOps(calls: readonly OpFactoryCall[], lowerer?: Lowerer): Op[] {
32
+ export function renderOps(
33
+ calls: readonly OpFactoryCall[],
34
+ lowerer?: ExecuteRequestLowerer,
35
+ ): (Op | Promise<Op>)[] {
29
36
  return calls.map((c) => {
30
- const op = blindCast<
31
- { toOp(lowerer?: Lowerer): ReturnType<OpFactoryCall['toOp']> },
32
- 'PG OpFactoryCall.toOp accepts an optional Lowerer; the framework interface omits it because not all targets need a lowerer — the PG target overrides with this extended signature'
37
+ const opOrPromise = blindCast<
38
+ { toOp(lowerer?: ExecuteRequestLowerer): Op | Promise<Op> },
39
+ 'PG OpFactoryCall.toOp accepts an optional ExecuteRequestLowerer; the framework interface omits it because not all targets need a lowerer — the PG target overrides with this extended signature'
33
40
  >(c).toOp(lowerer);
34
- assertPostgresOp(op, c.factoryName);
35
- return op;
41
+ if (isThenable(opOrPromise)) {
42
+ return opOrPromise.then((op) => {
43
+ assertPostgresOp(op, c.factoryName);
44
+ return op;
45
+ });
46
+ }
47
+ assertPostgresOp(opOrPromise, c.factoryName);
48
+ return opOrPromise;
36
49
  });
37
50
  }
@@ -18,13 +18,13 @@ import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
18
18
  import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
19
19
  import type { SqlControlDriverInstance, SqlStorage } from '@prisma-next/sql-contract/types';
20
20
  import { SqlQueryError } from '@prisma-next/sql-errors';
21
- import type { LoweredStatement } from '@prisma-next/sql-relational-core/ast';
21
+ import type { SqlExecuteRequest } from '@prisma-next/sql-relational-core/ast';
22
+ import { blindCast } from '@prisma-next/utils/casts';
22
23
  import { ifDefined } from '@prisma-next/utils/defined';
23
24
  import type { Result } from '@prisma-next/utils/result';
24
25
  import { notOk, ok, okVoid } from '@prisma-next/utils/result';
25
26
  import { parsePostgresDefault } from '../default-normalizer';
26
27
  import { normalizeSchemaNativeType } from '../native-type-normalizer';
27
- import { createResolveExistingEnumValues } from './enum-planning';
28
28
  import type { PostgresPlanTargetDetails } from './planner-target-details';
29
29
 
30
30
  interface ApplyPlanSuccessValue {
@@ -86,6 +86,12 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
86
86
  const space = options.plan.spaceId;
87
87
  const lockKey = `${LOCK_DOMAIN}:${schema}:${space}`;
88
88
 
89
+ // Materialize any async ops before running checks or executing.
90
+ const planOps = blindCast<
91
+ readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
92
+ 'ops were produced by the PG planner and are SqlMigrationPlanOperation<PostgresPlanTargetDetails>; MigrationPlan.operations uses the wider framework type to accommodate Promise covariance'
93
+ >(await Promise.all(options.plan.operations));
94
+
89
95
  // Static checks (idempotent — safe to run again when the caller is
90
96
  // `execute(...)` because the cost is a single object comparison).
91
97
  const destinationCheck = this.ensurePlanMatchesDestinationContract(
@@ -94,7 +100,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
94
100
  );
95
101
  if (!destinationCheck.ok) return destinationCheck;
96
102
 
97
- const policyCheck = this.enforcePolicyCompatibility(options.policy, options.plan.operations);
103
+ const policyCheck = this.enforcePolicyCompatibility(options.policy, planOps);
98
104
  if (!policyCheck.ok) return policyCheck;
99
105
 
100
106
  await this.acquireLock(driver, lockKey);
@@ -113,7 +119,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
113
119
  if (skipOperations) {
114
120
  applyValue = { operationsExecuted: 0, executedOperations: [] };
115
121
  } else {
116
- const applyResult = await this.applyPlan(driver, options);
122
+ const applyResult = await this.applyPlan(driver, options, planOps);
117
123
  if (!applyResult.ok) return applyResult;
118
124
  applyValue = applyResult.value;
119
125
  }
@@ -137,9 +143,6 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
137
143
  frameworkComponents: options.frameworkComponents,
138
144
  normalizeDefault: parsePostgresDefault,
139
145
  normalizeNativeType: normalizeSchemaNativeType,
140
- resolveExistingEnumValues: createResolveExistingEnumValues(
141
- options.destinationContract.storage,
142
- ),
143
146
  });
144
147
  if (!schemaVerifyResult.ok) {
145
148
  return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
@@ -158,11 +161,16 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
158
161
  if (!isSelfEdgeNoOp) {
159
162
  const markerResult = await this.upsertMarker(driver, options, existingMarker, space);
160
163
  if (!markerResult.ok) return markerResult;
161
- await this.recordLedgerEntries(driver, options, applyValue.executedOperations);
164
+ await this.recordLedgerEntries(
165
+ driver,
166
+ options,
167
+ applyValue.executedOperations,
168
+ planOps.length,
169
+ );
162
170
  }
163
171
 
164
172
  return runnerSuccess({
165
- operationsPlanned: options.plan.operations.length,
173
+ operationsPlanned: planOps.length,
166
174
  operationsExecuted: applyValue.operationsExecuted,
167
175
  });
168
176
  }
@@ -209,6 +217,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
209
217
  private async applyPlan(
210
218
  driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
211
219
  options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
220
+ ops: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
212
221
  ): Promise<Result<ApplyPlanSuccessValue, SqlMigrationRunnerFailure>> {
213
222
  const checks = options.executionChecks;
214
223
  const runPrechecks = checks?.prechecks !== false; // Default true
@@ -217,7 +226,7 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
217
226
 
218
227
  let operationsExecuted = 0;
219
228
  const executedOperations: Array<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> = [];
220
- for (const operation of options.plan.operations) {
229
+ for (const operation of ops) {
221
230
  options.callbacks?.onOperationStart?.(operation);
222
231
  try {
223
232
  // Idempotency probe: only run if both postchecks and idempotency checks are enabled
@@ -282,13 +291,13 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
282
291
  if (schemaQuery === undefined) {
283
292
  throw new Error('Postgres control-table bootstrap must include CREATE SCHEMA');
284
293
  }
285
- await this.executeStatement(driver, this.family.lowerAst(schemaQuery, lowererContext));
294
+ await this.executeStatement(driver, await this.family.lowerAst(schemaQuery, lowererContext));
286
295
  const legacyDetection = await this.detectLegacyMarkerShape(driver);
287
296
  if (!legacyDetection.ok) {
288
297
  return legacyDetection;
289
298
  }
290
299
  for (const query of tableQueries) {
291
- await this.executeStatement(driver, this.family.lowerAst(query, lowererContext));
300
+ await this.executeStatement(driver, await this.family.lowerAst(query, lowererContext));
292
301
  }
293
302
  return okVoid();
294
303
  }
@@ -629,14 +638,15 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
629
638
  driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
630
639
  options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
631
640
  executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],
641
+ planOpsLength: number,
632
642
  ): Promise<void> {
633
643
  const plan = options.plan;
634
644
  const space = plan.spaceId;
635
645
  const edges = options.migrationEdges;
636
646
  const totalEdgeOps = edges.reduce((sum, edge) => sum + edge.operationCount, 0);
637
- if (totalEdgeOps !== plan.operations.length) {
647
+ if (totalEdgeOps !== planOpsLength) {
638
648
  throw new Error(
639
- `Ledger write: plan.operations length (${plan.operations.length}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`,
649
+ `Ledger write: plan.operations length (${planOpsLength}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`,
640
650
  );
641
651
  }
642
652
  // The ledger records the operations as executed — idempotency-skipped ops
@@ -688,12 +698,8 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
688
698
 
689
699
  private async executeStatement(
690
700
  driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],
691
- statement: LoweredStatement,
701
+ statement: SqlExecuteRequest,
692
702
  ): Promise<void> {
693
- if (statement.params.length > 0) {
694
- await driver.query(statement.sql, statement.params);
695
- return;
696
- }
697
- await driver.query(statement.sql);
703
+ await driver.query(statement.sql, statement.params);
698
704
  }
699
705
  }