@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
@@ -36,10 +36,10 @@ import {
36
36
  sqlTimestampDescriptor,
37
37
  sqlVarcharDescriptor,
38
38
  } from '@prisma-next/sql-relational-core/ast';
39
+ import { blindCast } from '@prisma-next/utils/casts';
39
40
  import type { StandardSchemaV1 } from '@standard-schema/spec';
40
41
  import { type as arktype } from 'arktype';
41
42
  import {
42
- pgEnumRenderOutputType,
43
43
  pgIntervalDecode,
44
44
  pgJsonbDecode,
45
45
  pgJsonbEncode,
@@ -59,7 +59,6 @@ import {
59
59
  PG_BOOL_CODEC_ID,
60
60
  PG_BYTEA_CODEC_ID,
61
61
  PG_CHAR_CODEC_ID,
62
- PG_ENUM_CODEC_ID,
63
62
  PG_FLOAT_CODEC_ID,
64
63
  PG_FLOAT4_CODEC_ID,
65
64
  PG_FLOAT8_CODEC_ID,
@@ -77,6 +76,7 @@ import {
77
76
  PG_TIMESTAMP_CODEC_ID,
78
77
  PG_TIMESTAMPTZ_CODEC_ID,
79
78
  PG_TIMETZ_CODEC_ID,
79
+ PG_UUID_CODEC_ID,
80
80
  PG_VARBIT_CODEC_ID,
81
81
  PG_VARCHAR_CODEC_ID,
82
82
  } from './codec-ids';
@@ -84,7 +84,6 @@ import {
84
84
  type LengthParams = { readonly length?: number };
85
85
  type PrecisionParams = { readonly precision?: number };
86
86
  type NumericParams = { readonly precision: number; readonly scale?: number };
87
- type EnumParams = { readonly values?: readonly string[] };
88
87
 
89
88
  const lengthParamsSchema = arktype({
90
89
  'length?': 'number.integer > 0',
@@ -789,64 +788,58 @@ export const pgByteaColumn = () =>
789
788
  pgByteaColumn satisfies ColumnHelperFor<PgByteaDescriptor>;
790
789
  pgByteaColumn satisfies ColumnHelperForStrict<PgByteaDescriptor>;
791
790
 
792
- export class PgIntervalCodec extends CodecImpl<
793
- typeof PG_INTERVAL_CODEC_ID,
791
+ const PG_UUID_META = { db: { sql: { postgres: { nativeType: 'uuid' } } } } as const;
792
+
793
+ export class PgUuidCodec extends CodecImpl<
794
+ typeof PG_UUID_CODEC_ID,
794
795
  readonly ['equality', 'order'],
795
- string | Record<string, unknown>,
796
+ string,
796
797
  string
797
798
  > {
798
799
  async encode(value: string, _ctx: CodecCallContext): Promise<string> {
799
800
  return value;
800
801
  }
801
- async decode(wire: string | Record<string, unknown>, _ctx: CodecCallContext): Promise<string> {
802
- return pgIntervalDecode(wire);
802
+ async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
803
+ return wire;
803
804
  }
804
805
  encodeJson(value: string): JsonValue {
805
806
  return value;
806
807
  }
807
808
  decodeJson(json: JsonValue): string {
808
- return json as string;
809
+ return blindCast<string, 'uuid columns serialize to JSON as their wire string form'>(json);
809
810
  }
810
811
  }
811
812
 
812
- export class PgIntervalDescriptor extends CodecDescriptorImpl<PrecisionParams> {
813
- override readonly codecId = PG_INTERVAL_CODEC_ID;
813
+ export class PgUuidDescriptor extends CodecDescriptorImpl<void> {
814
+ override readonly codecId = PG_UUID_CODEC_ID;
814
815
  override readonly traits = ['equality', 'order'] as const;
815
- override readonly targetTypes = ['interval'] as const;
816
- override readonly meta = PG_INTERVAL_META;
817
- override readonly paramsSchema =
818
- precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
819
- override renderOutputType(params: PrecisionParams): string | undefined {
820
- return renderPrecision('Interval', params as Record<string, unknown>);
821
- }
822
- override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgIntervalCodec {
823
- return () => new PgIntervalCodec(this);
816
+ override readonly targetTypes = ['uuid'] as const;
817
+ override readonly meta = PG_UUID_META;
818
+ override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
819
+ override factory(): (ctx: CodecInstanceContext) => PgUuidCodec {
820
+ return () => new PgUuidCodec(this);
824
821
  }
825
822
  }
826
823
 
827
- export const pgIntervalDescriptor = new PgIntervalDescriptor();
824
+ export const pgUuidDescriptor = new PgUuidDescriptor();
828
825
 
829
- export const pgIntervalColumn = (params: PrecisionParams = {}) =>
830
- column(pgIntervalDescriptor.factory(params), pgIntervalDescriptor.codecId, params, 'interval');
826
+ export const pgUuidColumn = () =>
827
+ column(pgUuidDescriptor.factory(), pgUuidDescriptor.codecId, undefined, 'uuid');
831
828
 
832
- pgIntervalColumn satisfies ColumnHelperFor<PgIntervalDescriptor>;
833
- pgIntervalColumn satisfies ColumnHelperForStrict<PgIntervalDescriptor>;
834
-
835
- const enumParamsSchema = arktype({
836
- 'values?': 'string[]',
837
- });
829
+ pgUuidColumn satisfies ColumnHelperFor<PgUuidDescriptor>;
830
+ pgUuidColumn satisfies ColumnHelperForStrict<PgUuidDescriptor>;
838
831
 
839
- export class PgEnumCodec extends CodecImpl<
840
- typeof PG_ENUM_CODEC_ID,
832
+ export class PgIntervalCodec extends CodecImpl<
833
+ typeof PG_INTERVAL_CODEC_ID,
841
834
  readonly ['equality', 'order'],
842
- string,
835
+ string | Record<string, unknown>,
843
836
  string
844
837
  > {
845
838
  async encode(value: string, _ctx: CodecCallContext): Promise<string> {
846
839
  return value;
847
840
  }
848
- async decode(wire: string, _ctx: CodecCallContext): Promise<string> {
849
- return wire;
841
+ async decode(wire: string | Record<string, unknown>, _ctx: CodecCallContext): Promise<string> {
842
+ return pgIntervalDecode(wire);
850
843
  }
851
844
  encodeJson(value: string): JsonValue {
852
845
  return value;
@@ -856,26 +849,28 @@ export class PgEnumCodec extends CodecImpl<
856
849
  }
857
850
  }
858
851
 
859
- export class PgEnumDescriptor extends CodecDescriptorImpl<EnumParams> {
860
- override readonly codecId = PG_ENUM_CODEC_ID;
852
+ export class PgIntervalDescriptor extends CodecDescriptorImpl<PrecisionParams> {
853
+ override readonly codecId = PG_INTERVAL_CODEC_ID;
861
854
  override readonly traits = ['equality', 'order'] as const;
862
- override readonly targetTypes = ['enum'] as const;
863
- override readonly paramsSchema = enumParamsSchema satisfies StandardSchemaV1<EnumParams>;
864
- override renderOutputType(params: EnumParams): string | undefined {
865
- return pgEnumRenderOutputType(params);
855
+ override readonly targetTypes = ['interval'] as const;
856
+ override readonly meta = PG_INTERVAL_META;
857
+ override readonly paramsSchema =
858
+ precisionParamsSchema satisfies StandardSchemaV1<PrecisionParams>;
859
+ override renderOutputType(params: PrecisionParams): string | undefined {
860
+ return renderPrecision('Interval', params as Record<string, unknown>);
866
861
  }
867
- override factory(_params: EnumParams): (ctx: CodecInstanceContext) => PgEnumCodec {
868
- return () => new PgEnumCodec(this);
862
+ override factory(_params: PrecisionParams): (ctx: CodecInstanceContext) => PgIntervalCodec {
863
+ return () => new PgIntervalCodec(this);
869
864
  }
870
865
  }
871
866
 
872
- export const pgEnumDescriptor = new PgEnumDescriptor();
867
+ export const pgIntervalDescriptor = new PgIntervalDescriptor();
873
868
 
874
- export const pgEnumColumn = (params: EnumParams = {}) =>
875
- column(pgEnumDescriptor.factory(params), pgEnumDescriptor.codecId, params, 'enum');
869
+ export const pgIntervalColumn = (params: PrecisionParams = {}) =>
870
+ column(pgIntervalDescriptor.factory(params), pgIntervalDescriptor.codecId, params, 'interval');
876
871
 
877
- pgEnumColumn satisfies ColumnHelperFor<PgEnumDescriptor>;
878
- pgEnumColumn satisfies ColumnHelperForStrict<PgEnumDescriptor>;
872
+ pgIntervalColumn satisfies ColumnHelperFor<PgIntervalDescriptor>;
873
+ pgIntervalColumn satisfies ColumnHelperForStrict<PgIntervalDescriptor>;
879
874
 
880
875
  export class PgJsonCodec extends CodecImpl<
881
876
  typeof PG_JSON_CODEC_ID,
@@ -1075,8 +1070,8 @@ export const codecDescriptors: readonly AnyCodecDescriptor[] = [
1075
1070
  pgBitDescriptor,
1076
1071
  pgVarbitDescriptor,
1077
1072
  pgByteaDescriptor,
1073
+ pgUuidDescriptor,
1078
1074
  pgIntervalDescriptor,
1079
- pgEnumDescriptor,
1080
1075
  pgJsonDescriptor,
1081
1076
  pgJsonbDescriptor,
1082
1077
  pgTextArrayDescriptor,
@@ -4,9 +4,44 @@ import {
4
4
  type DdlTableConstraint,
5
5
  } from '@prisma-next/sql-relational-core/ast';
6
6
 
7
+ // ---------------------------------------------------------------------------
8
+ // AlterTableAction — nested polymorphic hierarchy
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export interface AlterTableActionVisitor<R> {
12
+ addColumn(action: AddColumnAction): R;
13
+ }
14
+
15
+ export abstract class AlterTableAction {
16
+ abstract readonly kind: string;
17
+ abstract accept<R>(visitor: AlterTableActionVisitor<R>): R;
18
+ }
19
+
20
+ export class AddColumnAction extends AlterTableAction {
21
+ readonly kind = 'add-column' as const;
22
+ readonly column: DdlColumn;
23
+
24
+ constructor(column: DdlColumn) {
25
+ super();
26
+ this.column = column;
27
+ Object.freeze(this);
28
+ }
29
+
30
+ override accept<R>(visitor: AlterTableActionVisitor<R>): R {
31
+ return visitor.addColumn(this);
32
+ }
33
+ }
34
+
35
+ export type AnyAlterTableAction = AddColumnAction;
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Top-level DDL visitor
39
+ // ---------------------------------------------------------------------------
40
+
7
41
  export interface PostgresDdlVisitor<R> {
8
42
  createTable(node: PostgresCreateTable): R;
9
43
  createSchema(node: PostgresCreateSchema): R;
44
+ alterTable(node: PostgresAlterTable): R;
10
45
  }
11
46
 
12
47
  export abstract class PostgresDdlNode extends DdlNode {
@@ -69,4 +104,27 @@ export class PostgresCreateSchema extends PostgresDdlNode {
69
104
  }
70
105
  }
71
106
 
72
- export type AnyPostgresDdlNode = PostgresCreateTable | PostgresCreateSchema;
107
+ export class PostgresAlterTable extends PostgresDdlNode {
108
+ readonly kind = 'alter-table' as const;
109
+ readonly table: string;
110
+ readonly schema: string | undefined;
111
+ readonly actions: ReadonlyArray<AnyAlterTableAction>;
112
+
113
+ constructor(options: {
114
+ readonly table: string;
115
+ readonly schema?: string;
116
+ readonly actions: readonly AnyAlterTableAction[];
117
+ }) {
118
+ super();
119
+ this.table = options.table;
120
+ this.schema = options.schema;
121
+ this.actions = Object.freeze([...options.actions]);
122
+ this.freeze();
123
+ }
124
+
125
+ override accept<R>(visitor: PostgresDdlVisitor<R>): R {
126
+ return visitor.alterTable(this);
127
+ }
128
+ }
129
+
130
+ export type AnyPostgresDdlNode = PostgresCreateTable | PostgresCreateSchema | PostgresAlterTable;
@@ -1,12 +1,8 @@
1
1
  import type { Contract } from '@prisma-next/contract/types';
2
2
  import type { ControlPolicySubject } from '@prisma-next/family-sql/control';
3
3
  import type { SchemaIssue } from '@prisma-next/framework-components/control';
4
- import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
5
- import {
6
- isPostgresEnumStorageEntry,
7
- type SqlStorage,
8
- storageTableAt,
9
- } from '@prisma-next/sql-contract/types';
4
+ import { entityAt, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
5
+ import type { SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';
10
6
  import { ifDefined } from '@prisma-next/utils/defined';
11
7
  import { isPostgresSchema } from '../postgres-schema';
12
8
  import type { PostgresOpFactoryCall } from './op-factory-call';
@@ -24,7 +20,6 @@ import type { PostgresOpFactoryCall } from './op-factory-call';
24
20
  */
25
21
  const OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([
26
22
  'createTable',
27
- 'createEnumType',
28
23
  'createSchema',
29
24
  ]);
30
25
 
@@ -43,7 +38,11 @@ function resolveNamespaceIdForTable(
43
38
  ddlSchemaName: string | undefined,
44
39
  ): string {
45
40
  for (const namespaceId of Object.keys(contract.storage.namespaces)) {
46
- const table = storageTableAt(contract.storage, namespaceId, tableName);
41
+ const table = entityAt<StorageTable>(contract.storage, {
42
+ namespaceId,
43
+ entityKind: 'table',
44
+ entityName: tableName,
45
+ });
47
46
  if (!table) continue;
48
47
  if (
49
48
  ddlSchemaName === undefined ||
@@ -75,7 +74,6 @@ interface PostgresCallFields {
75
74
  readonly schemaName?: string;
76
75
  readonly tableName?: string;
77
76
  readonly columnName?: string;
78
- readonly typeName?: string;
79
77
  }
80
78
 
81
79
  function postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {
@@ -83,7 +81,6 @@ function postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {
83
81
  ...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),
84
82
  ...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),
85
83
  ...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),
86
- ...ifDefined('typeName', 'typeName' in call ? call.typeName : undefined),
87
84
  };
88
85
  }
89
86
 
@@ -96,10 +93,6 @@ export function formatPostgresControlPolicySubjectLabel(
96
93
  const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);
97
94
  return `${factoryName}(${ddlSchema}.${subject.table})`;
98
95
  }
99
- if (subject?.typeName) {
100
- const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);
101
- return `${factoryName}(${ddlSchema}.${subject.typeName})`;
102
- }
103
96
  return factoryName;
104
97
  }
105
98
 
@@ -117,29 +110,17 @@ export function resolvePostgresCallControlPolicySubject(
117
110
  };
118
111
  }
119
112
 
120
- if (callFields.typeName && call.factoryName !== 'addColumn') {
121
- const namespaceId = callFields.schemaName
122
- ? resolveNamespaceIdForDdlSchema(contract, callFields.schemaName)
123
- : UNBOUND_NAMESPACE_ID;
124
- const ns = contract.storage.namespaces[namespaceId];
125
- const rawEnum = isPostgresSchema(ns) ? ns.entries.type[callFields.typeName] : undefined;
126
- const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;
127
- return {
128
- namespaceId,
129
- ...ifDefined('explicitNodeControlPolicy', controlPolicy),
130
- typeName: callFields.typeName,
131
- createsNewObject,
132
- };
133
- }
134
-
135
113
  if (callFields.tableName) {
136
114
  const namespaceId = resolveNamespaceIdForTable(
137
115
  contract,
138
116
  callFields.tableName,
139
117
  callFields.schemaName,
140
118
  );
141
- const table = storageTableAt(contract.storage, namespaceId, callFields.tableName);
142
- const tableControlPolicy = table?.control;
119
+ const tableControlPolicy = entityAt<StorageTable>(contract.storage, {
120
+ namespaceId,
121
+ entityKind: 'table',
122
+ entityName: callFields.tableName,
123
+ })?.control;
143
124
  return {
144
125
  namespaceId,
145
126
  ...ifDefined('explicitNodeControlPolicy', tableControlPolicy),
@@ -170,7 +151,6 @@ export function resolvePostgresCallControlPolicySubject(
170
151
  const POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({
171
152
  missing_schema: 'createSchema',
172
153
  missing_table: 'createTable',
173
- type_missing: 'createEnumType',
174
154
  });
175
155
 
176
156
  export function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {
@@ -201,26 +181,16 @@ export function resolvePostgresIssueControlPolicySubject(
201
181
  return { namespaceId: issue.namespaceId, createsNewObject };
202
182
  }
203
183
 
204
- if ('typeName' in issue && issue.typeName) {
205
- const namespaceId =
206
- 'namespaceId' in issue && issue.namespaceId ? issue.namespaceId : UNBOUND_NAMESPACE_ID;
207
- const ns = contract.storage.namespaces[namespaceId];
208
- const rawEnum = isPostgresSchema(ns) ? ns.entries.type[issue.typeName] : undefined;
209
- const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;
210
- return {
211
- namespaceId,
212
- ...ifDefined('explicitNodeControlPolicy', controlPolicy),
213
- typeName: issue.typeName,
214
- createsNewObject,
215
- };
216
- }
217
-
218
184
  if ('table' in issue && issue.table) {
219
185
  const namespaceId =
220
186
  'namespaceId' in issue && issue.namespaceId
221
187
  ? issue.namespaceId
222
188
  : resolveNamespaceIdForTable(contract, issue.table, undefined);
223
- const table = storageTableAt(contract.storage, namespaceId, issue.table);
189
+ const table = entityAt<StorageTable>(contract.storage, {
190
+ namespaceId,
191
+ entityKind: 'table',
192
+ entityName: issue.table,
193
+ });
224
194
  return {
225
195
  namespaceId,
226
196
  ...ifDefined('explicitNodeControlPolicy', table?.control),
@@ -8,7 +8,7 @@
8
8
  * through `mapIssueToCall` for the default case.
9
9
  */
10
10
 
11
- import type { Contract } from '@prisma-next/contract/types';
11
+ import type { Contract, JsonValue } from '@prisma-next/contract/types';
12
12
  import type {
13
13
  CodecControlHooks,
14
14
  MigrationOperationPolicy,
@@ -19,26 +19,24 @@ import { arraysEqual } from '@prisma-next/family-sql/schema-verify';
19
19
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
20
20
  import type { SchemaIssue } from '@prisma-next/framework-components/control';
21
21
  import type {
22
- PostgresEnumStorageEntry,
23
22
  SqlStorage,
24
23
  StorageColumn,
25
24
  StorageTable,
26
25
  StorageTypeInstance,
27
26
  } from '@prisma-next/sql-contract/types';
28
- import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
27
+ import type { CodecRef, DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
29
28
  import * as contractFree from '@prisma-next/sql-relational-core/contract-free';
30
29
  import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
30
+ import { blindCast } from '@prisma-next/utils/casts';
31
+ import { ifDefined } from '@prisma-next/utils/defined';
31
32
  import type { Result } from '@prisma-next/utils/result';
32
33
  import { notOk, ok } from '@prisma-next/utils/result';
33
- import { PostgresEnumType } from '../postgres-enum-type';
34
- import { isPostgresSchema } from '../postgres-schema';
35
34
  import {
36
35
  AddColumnCall,
37
36
  AddForeignKeyCall,
38
37
  AddPrimaryKeyCall,
39
38
  AddUniqueCall,
40
39
  AlterColumnTypeCall,
41
- CreateEnumTypeCall,
42
40
  CreateIndexCall,
43
41
  CreateSchemaCall,
44
42
  CreateTableCall,
@@ -54,7 +52,7 @@ import {
54
52
  SetDefaultCall,
55
53
  SetNotNullCall,
56
54
  } from './op-factory-call';
57
- import type { ColumnSpec, ForeignKeySpec } from './operations/shared';
55
+ import type { ForeignKeySpec } from './operations/shared';
58
56
  import { buildColumnDefaultSql, buildColumnTypeSql } from './planner-ddl-builders';
59
57
  import { buildExpectedFormatType } from './planner-sql-checks';
60
58
  import {
@@ -65,22 +63,10 @@ import {
65
63
  type StrategyContext,
66
64
  tableAt,
67
65
  } from './planner-strategies';
66
+ import { resolveColumnTypeMetadata } from './planner-type-resolution';
68
67
 
69
68
  export type { CallMigrationStrategy, StrategyContext };
70
69
 
71
- /**
72
- * Finds a type entry by explicit namespace coordinate. Reads the named
73
- * namespace's `enum` slot directly — never scans other namespaces.
74
- */
75
- function locateNamespaceTypeInStorage(
76
- storage: SqlStorage,
77
- namespaceId: string,
78
- typeName: string,
79
- ): unknown {
80
- const ns = storage.namespaces[namespaceId];
81
- return isPostgresSchema(ns) ? ns.entries.type[typeName] : undefined;
82
- }
83
-
84
70
  // ============================================================================
85
71
  // Issue kind ordering (dependency order)
86
72
  // ============================================================================
@@ -165,7 +151,7 @@ export interface IssuePlannerOptions {
165
151
  readonly fromContract: Contract<SqlStorage> | null;
166
152
  readonly schemaName: string;
167
153
  readonly codecHooks: ReadonlyMap<string, CodecControlHooks>;
168
- readonly storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>;
154
+ readonly storageTypes: Readonly<Record<string, StorageTypeInstance>>;
169
155
  /**
170
156
  * Current database schema IR. Strategies read this to detect whether a
171
157
  * structure already exists (e.g. `buildSchemaLookupMap` for shared-temp-
@@ -192,31 +178,35 @@ export interface IssuePlannerValue {
192
178
  readonly calls: readonly PostgresOpFactoryCall[];
193
179
  }
194
180
 
195
- function toColumnSpec(
196
- name: string,
197
- column: StorageColumn,
198
- codecHooks: ReadonlyMap<string, CodecControlHooks>,
199
- storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,
200
- ): ColumnSpec {
201
- return {
202
- name,
203
- typeSql: buildColumnTypeSql(column, codecHooks, storageTypes),
204
- defaultSql: buildColumnDefaultSql(column.default, column),
205
- nullable: column.nullable,
206
- };
207
- }
208
-
209
181
  function toDdlColumn(
210
182
  name: string,
211
183
  column: StorageColumn,
212
184
  codecHooks: ReadonlyMap<string, CodecControlHooks>,
213
- storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,
185
+ storageTypes: Readonly<Record<string, StorageTypeInstance>>,
214
186
  ): DdlColumn {
215
187
  const typeSql = buildColumnTypeSql(column, codecHooks, storageTypes);
216
188
  const ddlDefault = postgresDefaultToDdlColumnDefault(column.default);
189
+ const resolved = resolveColumnTypeMetadata(
190
+ column,
191
+ storageTypes as Record<string, StorageTypeInstance>,
192
+ );
193
+ const codecRef: CodecRef | undefined = resolved.codecId
194
+ ? {
195
+ codecId: resolved.codecId,
196
+ ...(resolved.typeParams !== undefined
197
+ ? {
198
+ typeParams: blindCast<
199
+ JsonValue,
200
+ 'resolved.typeParams is JsonValue-shaped storage metadata; the narrowed (non-undefined) value lands in CodecRef.typeParams which is JsonValue'
201
+ >(resolved.typeParams),
202
+ }
203
+ : {}),
204
+ }
205
+ : undefined;
217
206
  return contractFree.col(name, typeSql, {
218
207
  ...(!column.nullable ? { notNull: true } : {}),
219
- ...(ddlDefault ? { default: ddlDefault } : {}),
208
+ ...ifDefined('default', ddlDefault),
209
+ ...ifDefined('codecRef', codecRef),
220
210
  });
221
211
  }
222
212
 
@@ -342,7 +332,7 @@ function mapIssueToCall(
342
332
  new AddColumnCall(
343
333
  tableSchema(issue),
344
334
  issue.table,
345
- toColumnSpec(issue.column, column, codecHooks, storageTypes),
335
+ toDdlColumn(issue.column, column, codecHooks, storageTypes),
346
336
  ),
347
337
  ]);
348
338
  }
@@ -475,10 +465,7 @@ function mapIssueToCall(
475
465
  ),
476
466
  );
477
467
  const hooksMap = codecHooks as Map<string, CodecControlHooks>;
478
- const typesMap = storageTypes as Record<
479
- string,
480
- StorageTypeInstance | PostgresEnumStorageEntry
481
- >;
468
+ const typesMap = storageTypes as Record<string, StorageTypeInstance>;
482
469
  const qualifiedTargetType = buildColumnTypeSql(column, hooksMap, typesMap, false);
483
470
  const formatTypeExpected = buildExpectedFormatType(column, hooksMap, typesMap);
484
471
  return ok([
@@ -666,14 +653,7 @@ function mapIssueToCall(
666
653
  case 'type_missing': {
667
654
  if (!issue.typeName)
668
655
  return notOk(issueConflict('unsupportedOperation', 'Type missing issue has no typeName'));
669
- // Codec aliases live in storage.types; enum types live in namespace.entries.type.
670
- // Check types first; fall back to the namespace-keyed enum slot using the
671
- // issue's namespace coordinate (populated by the verifier for enum-related
672
- // issues per the BaseSchemaIssue.namespaceId contract).
673
- const namespaceId = resolveNamespaceIdForIssue(issue);
674
- const typeInstance: unknown =
675
- ctx.toContract.storage.types?.[issue.typeName] ??
676
- locateNamespaceTypeInStorage(ctx.toContract.storage, namespaceId, issue.typeName);
656
+ const typeInstance = ctx.toContract.storage.types?.[issue.typeName];
677
657
  if (!typeInstance) {
678
658
  return notOk(
679
659
  issueConflict(
@@ -682,22 +662,10 @@ function mapIssueToCall(
682
662
  ),
683
663
  );
684
664
  }
685
- if (typeInstance instanceof PostgresEnumType) {
686
- const ddlSchema = resolveDdlSchemaForNamespace(ctx, namespaceId);
687
- return ok([
688
- new CreateEnumTypeCall(
689
- ddlSchema,
690
- issue.typeName,
691
- typeInstance.values,
692
- typeInstance.nativeType,
693
- ),
694
- ]);
695
- }
696
- const codecInstance = typeInstance as StorageTypeInstance;
697
665
  return notOk(
698
666
  issueConflict(
699
667
  'unsupportedOperation',
700
- `Type "${issue.typeName}" uses codec "${codecInstance.codecId}" — only enum types are supported`,
668
+ `Type "${issue.typeName}" uses codec "${typeInstance.codecId}" — only value-set types are supported`,
701
669
  ),
702
670
  );
703
671
  }
@@ -744,10 +712,6 @@ function classifyCall(call: PostgresOpFactoryCall): CallCategory {
744
712
  switch (call.factoryName) {
745
713
  case 'createExtension':
746
714
  case 'createSchema':
747
- case 'createEnumType':
748
- case 'addEnumValues':
749
- case 'dropEnumType':
750
- case 'renameType':
751
715
  return 'dep';
752
716
  case 'dropTable':
753
717
  case 'dropColumn':
@@ -971,10 +935,10 @@ export function planIssues(
971
935
  return notOk(conflicts);
972
936
  }
973
937
 
974
- // Recipe strategies (`nativeEnumPlanCallStrategy`,
975
- // `notNullBackfillCallStrategy`, etc.) emit a cohesive sequence that must
938
+ // Recipe strategies (`notNullBackfillCallStrategy`,
939
+ // `nullableTighteningCallStrategy`, etc.) emit a cohesive sequence that must
976
940
  // stay contiguous. They are inserted at a single pattern slot. Non-recipe
977
- // pattern strategies (`dependencyInstallCallStrategy`,
941
+ // pattern strategies (`checkConstraintPlanCallStrategy`,
978
942
  // `storageTypePlanCallStrategy`, `notNullAddColumnCallStrategy`) produce
979
943
  // individually classifiable calls that slot into DDL buckets alongside
980
944
  // default-mapped calls.