@prisma-next/target-postgres 0.11.0-dev.9 → 0.12.0-dev.1

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 (168) hide show
  1. package/dist/{codec-ids-D9fJ4HP5.d.mts → codec-ids-DliyCWPY.d.mts} +1 -1
  2. package/dist/{codec-ids-D9fJ4HP5.d.mts.map → codec-ids-DliyCWPY.d.mts.map} +1 -1
  3. package/dist/codec-ids.d.mts +1 -1
  4. package/dist/{codec-types-CRlHq7Cz.d.mts → codec-types-BF1DXTPs.d.mts} +2 -2
  5. package/dist/codec-types-BF1DXTPs.d.mts.map +1 -0
  6. package/dist/codec-types.d.mts +1 -1
  7. package/dist/{codecs-Dud5KDNk.d.mts → codecs-DuP3d9Au.d.mts} +2 -2
  8. package/dist/{codecs-Dud5KDNk.d.mts.map → codecs-DuP3d9Au.d.mts.map} +1 -1
  9. package/dist/codecs.d.mts +1 -1
  10. package/dist/codecs.d.mts.map +1 -1
  11. package/dist/codecs.mjs.map +1 -1
  12. package/dist/control.d.mts +1 -1
  13. package/dist/control.d.mts.map +1 -1
  14. package/dist/control.mjs +18 -41
  15. package/dist/control.mjs.map +1 -1
  16. package/dist/{data-transform-bmOKkygi.d.mts → data-transform-CAPmAdxS.d.mts} +2 -2
  17. package/dist/data-transform-CAPmAdxS.d.mts.map +1 -0
  18. package/dist/{data-transform-CdtGUWp2.mjs → data-transform-CRkv2T_U.mjs} +1 -1
  19. package/dist/{data-transform-CdtGUWp2.mjs.map → data-transform-CRkv2T_U.mjs.map} +1 -1
  20. package/dist/data-transform.d.mts +1 -1
  21. package/dist/data-transform.mjs +1 -1
  22. package/dist/{default-normalizer-DHCsbfjc.mjs → default-normalizer-DaAhmzBV.mjs} +1 -1
  23. package/dist/{default-normalizer-DHCsbfjc.mjs.map → default-normalizer-DaAhmzBV.mjs.map} +1 -1
  24. package/dist/default-normalizer.d.mts.map +1 -1
  25. package/dist/default-normalizer.mjs +1 -1
  26. package/dist/descriptor-meta-Dvr_77Z3.mjs +13 -0
  27. package/dist/descriptor-meta-Dvr_77Z3.mjs.map +1 -0
  28. package/dist/{descriptor-meta-DLA2xV6B.mjs → descriptor-meta-runtime-ByjztWgs.mjs} +81 -77
  29. package/dist/descriptor-meta-runtime-ByjztWgs.mjs.map +1 -0
  30. package/dist/enum-planning-DrNWCtCp.mjs +0 -0
  31. package/dist/enum-planning-DrNWCtCp.mjs.map +1 -0
  32. package/dist/enum-planning.d.mts +42 -4
  33. package/dist/enum-planning.d.mts.map +1 -1
  34. package/dist/enum-planning.mjs +2 -2
  35. package/dist/{errors--zafB5_n.mjs → errors-BbnITmAD.mjs} +1 -1
  36. package/dist/{errors--zafB5_n.mjs.map → errors-BbnITmAD.mjs.map} +1 -1
  37. package/dist/errors.d.mts.map +1 -1
  38. package/dist/errors.mjs +1 -1
  39. package/dist/{issue-planner-Ct9xNqbr.mjs → issue-planner-2RgYsjUJ.mjs} +113 -56
  40. package/dist/issue-planner-2RgYsjUJ.mjs.map +1 -0
  41. package/dist/issue-planner.d.mts +1 -1
  42. package/dist/issue-planner.d.mts.map +1 -1
  43. package/dist/issue-planner.mjs +1 -1
  44. package/dist/migration.d.mts +3 -3
  45. package/dist/migration.d.mts.map +1 -1
  46. package/dist/migration.mjs +3 -3
  47. package/dist/migration.mjs.map +1 -1
  48. package/dist/{native-type-normalizer-DMikJJ1V.mjs → native-type-normalizer-BNEQ9VDs.mjs} +1 -1
  49. package/dist/{native-type-normalizer-DMikJJ1V.mjs.map → native-type-normalizer-BNEQ9VDs.mjs.map} +1 -1
  50. package/dist/native-type-normalizer.d.mts.map +1 -1
  51. package/dist/native-type-normalizer.mjs +1 -1
  52. package/dist/{op-factory-call-Drccm_JD.d.mts → op-factory-call-CDlImOF_.d.mts} +3 -3
  53. package/dist/op-factory-call-CDlImOF_.d.mts.map +1 -0
  54. package/dist/{op-factory-call-CB6tPJ3f.mjs → op-factory-call-C_K5ibAY.mjs} +2 -2
  55. package/dist/{op-factory-call-CB6tPJ3f.mjs.map → op-factory-call-C_K5ibAY.mjs.map} +1 -1
  56. package/dist/op-factory-call.d.mts +1 -1
  57. package/dist/op-factory-call.mjs +1 -1
  58. package/dist/pack.d.mts +9 -8
  59. package/dist/pack.d.mts.map +1 -1
  60. package/dist/pack.mjs +1 -1
  61. package/dist/{planner-DlhK35aV.mjs → planner-CC3r_uNJ.mjs} +17 -25
  62. package/dist/planner-CC3r_uNJ.mjs.map +1 -0
  63. package/dist/{planner-ddl-builders--0TmW6Ey.mjs → planner-ddl-builders-DgyqpFji.mjs} +3 -3
  64. package/dist/{planner-ddl-builders--0TmW6Ey.mjs.map → planner-ddl-builders-DgyqpFji.mjs.map} +1 -1
  65. package/dist/planner-ddl-builders.d.mts +1 -1
  66. package/dist/planner-ddl-builders.d.mts.map +1 -1
  67. package/dist/planner-ddl-builders.mjs +1 -1
  68. package/dist/{planner-identity-values-ojX-6cPV.mjs → planner-identity-values-nhVj0hp-.mjs} +1 -1
  69. package/dist/{planner-identity-values-ojX-6cPV.mjs.map → planner-identity-values-nhVj0hp-.mjs.map} +1 -1
  70. package/dist/planner-identity-values.d.mts.map +1 -1
  71. package/dist/planner-identity-values.mjs +1 -1
  72. package/dist/{planner-produced-postgres-migration-p-VKkCia.d.mts → planner-produced-postgres-migration-D02NOhVQ.d.mts} +3 -3
  73. package/dist/planner-produced-postgres-migration-D02NOhVQ.d.mts.map +1 -0
  74. package/dist/{planner-produced-postgres-migration-TJWH2m_x.mjs → planner-produced-postgres-migration-D_nsXbhl.mjs} +5 -7
  75. package/dist/planner-produced-postgres-migration-D_nsXbhl.mjs.map +1 -0
  76. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  77. package/dist/planner-produced-postgres-migration.mjs +1 -1
  78. package/dist/{planner-schema-lookup-BGyukuzG.mjs → planner-schema-lookup-CGxxYfnD.mjs} +1 -1
  79. package/dist/{planner-schema-lookup-BGyukuzG.mjs.map → planner-schema-lookup-CGxxYfnD.mjs.map} +1 -1
  80. package/dist/planner-schema-lookup.d.mts.map +1 -1
  81. package/dist/planner-schema-lookup.mjs +1 -1
  82. package/dist/{planner-sql-checks-BDtJQ9WD.mjs → planner-sql-checks-BMu3fiMc.mjs} +3 -3
  83. package/dist/{planner-sql-checks-BDtJQ9WD.mjs.map → planner-sql-checks-BMu3fiMc.mjs.map} +1 -1
  84. package/dist/planner-sql-checks.d.mts.map +1 -1
  85. package/dist/planner-sql-checks.mjs +1 -1
  86. package/dist/{planner-target-details-CIj61DUj.d.mts → planner-target-details-a_wuOiYf.d.mts} +1 -1
  87. package/dist/{planner-target-details-CIj61DUj.d.mts.map → planner-target-details-a_wuOiYf.d.mts.map} +1 -1
  88. package/dist/planner-target-details.d.mts +1 -1
  89. package/dist/planner.d.mts +2 -7
  90. package/dist/planner.d.mts.map +1 -1
  91. package/dist/planner.mjs +1 -1
  92. package/dist/{postgres-contract-serializer-CYct4Y7O.mjs → postgres-contract-serializer-C0UtIDB8.mjs} +3 -3
  93. package/dist/postgres-contract-serializer-C0UtIDB8.mjs.map +1 -0
  94. package/dist/{postgres-enum-type-CNhPTDhy.d.mts → postgres-enum-type-5MBoKsIj.d.mts} +1 -1
  95. package/dist/postgres-enum-type-5MBoKsIj.d.mts.map +1 -0
  96. package/dist/postgres-enum-type-DS-KLVRH.mjs.map +1 -1
  97. package/dist/{postgres-migration-uADmx0dW.mjs → postgres-migration-BatbEvU6.mjs} +3 -3
  98. package/dist/{postgres-migration-uADmx0dW.mjs.map → postgres-migration-BatbEvU6.mjs.map} +1 -1
  99. package/dist/{postgres-migration-Fd4fQkBw.d.mts → postgres-migration-DRY8V-bQ.d.mts} +3 -3
  100. package/dist/{postgres-migration-Fd4fQkBw.d.mts.map → postgres-migration-DRY8V-bQ.d.mts.map} +1 -1
  101. package/dist/{postgres-schema-BL0RAvew.mjs → postgres-schema-vp5rvbYg.mjs} +12 -19
  102. package/dist/postgres-schema-vp5rvbYg.mjs.map +1 -0
  103. package/dist/{render-ops-BC2PtCkj.mjs → render-ops-XhICjX_P.mjs} +1 -1
  104. package/dist/{render-ops-BC2PtCkj.mjs.map → render-ops-XhICjX_P.mjs.map} +1 -1
  105. package/dist/render-ops.d.mts +1 -1
  106. package/dist/render-ops.d.mts.map +1 -1
  107. package/dist/render-ops.mjs +1 -1
  108. package/dist/{render-typescript-CI1wbgUc.mjs → render-typescript-K125n-RZ.mjs} +2 -3
  109. package/dist/render-typescript-K125n-RZ.mjs.map +1 -0
  110. package/dist/render-typescript.d.mts +0 -1
  111. package/dist/render-typescript.d.mts.map +1 -1
  112. package/dist/render-typescript.mjs +1 -1
  113. package/dist/runtime.d.mts.map +1 -1
  114. package/dist/runtime.mjs +3 -3
  115. package/dist/runtime.mjs.map +1 -1
  116. package/dist/{shared-ByhSooBS.d.mts → shared-Do_a5ymU.d.mts} +2 -2
  117. package/dist/shared-Do_a5ymU.d.mts.map +1 -0
  118. package/dist/{sql-utils-BewXAnsG.mjs → sql-utils-CggjWNij.mjs} +1 -1
  119. package/dist/{sql-utils-BewXAnsG.mjs.map → sql-utils-CggjWNij.mjs.map} +1 -1
  120. package/dist/sql-utils.d.mts.map +1 -1
  121. package/dist/sql-utils.mjs +1 -1
  122. package/dist/{statement-builders-vImtdfmM.mjs → statement-builders-DVI5IVAa.mjs} +1 -1
  123. package/dist/statement-builders-DVI5IVAa.mjs.map +1 -0
  124. package/dist/statement-builders.d.mts +1 -1
  125. package/dist/statement-builders.d.mts.map +1 -1
  126. package/dist/statement-builders.mjs +1 -1
  127. package/dist/{tables-Vhh4k5yz.mjs → tables-C8RrPLUq.mjs} +3 -3
  128. package/dist/{tables-Vhh4k5yz.mjs.map → tables-C8RrPLUq.mjs.map} +1 -1
  129. package/dist/{types-D-XIpzHA.d.mts → types-O40IcFV9.d.mts} +1 -1
  130. package/dist/types-O40IcFV9.d.mts.map +1 -0
  131. package/dist/types.d.mts +12 -16
  132. package/dist/types.d.mts.map +1 -1
  133. package/dist/types.mjs +1 -1
  134. package/package.json +29 -18
  135. package/src/core/authoring.ts +1 -1
  136. package/src/core/descriptor-meta-runtime.ts +28 -0
  137. package/src/core/descriptor-meta.ts +2 -6
  138. package/src/core/migrations/enum-planning.ts +134 -14
  139. package/src/core/migrations/issue-planner.ts +20 -11
  140. package/src/core/migrations/planner-produced-postgres-migration.ts +0 -2
  141. package/src/core/migrations/planner-strategies.ts +138 -40
  142. package/src/core/migrations/planner.ts +9 -21
  143. package/src/core/migrations/render-typescript.ts +1 -5
  144. package/src/core/migrations/runner.ts +20 -61
  145. package/src/core/migrations/statement-builders.ts +1 -1
  146. package/src/core/migrations/verify-postgres-namespaces.ts +6 -6
  147. package/src/core/postgres-contract-serializer.ts +4 -4
  148. package/src/core/postgres-schema.ts +10 -20
  149. package/src/exports/control.ts +16 -0
  150. package/src/exports/enum-planning.ts +5 -0
  151. package/src/exports/runtime.ts +2 -2
  152. package/dist/codec-types-CRlHq7Cz.d.mts.map +0 -1
  153. package/dist/data-transform-bmOKkygi.d.mts.map +0 -1
  154. package/dist/descriptor-meta-DLA2xV6B.mjs.map +0 -1
  155. package/dist/enum-planning-Bqp96iIw.mjs +0 -63
  156. package/dist/enum-planning-Bqp96iIw.mjs.map +0 -1
  157. package/dist/issue-planner-Ct9xNqbr.mjs.map +0 -1
  158. package/dist/op-factory-call-Drccm_JD.d.mts.map +0 -1
  159. package/dist/planner-DlhK35aV.mjs.map +0 -1
  160. package/dist/planner-produced-postgres-migration-TJWH2m_x.mjs.map +0 -1
  161. package/dist/planner-produced-postgres-migration-p-VKkCia.d.mts.map +0 -1
  162. package/dist/postgres-contract-serializer-CYct4Y7O.mjs.map +0 -1
  163. package/dist/postgres-enum-type-CNhPTDhy.d.mts.map +0 -1
  164. package/dist/postgres-schema-BL0RAvew.mjs.map +0 -1
  165. package/dist/render-typescript-CI1wbgUc.mjs.map +0 -1
  166. package/dist/shared-ByhSooBS.d.mts.map +0 -1
  167. package/dist/statement-builders-vImtdfmM.mjs.map +0 -1
  168. package/dist/types-D-XIpzHA.d.mts.map +0 -1
@@ -1,7 +1,6 @@
1
1
  import type { ContractMarkerRecord } from '@prisma-next/contract/types';
2
2
  import type {
3
3
  MigrationOperationPolicy,
4
- MultiSpaceRunnerResult,
5
4
  SqlControlFamilyInstance,
6
5
  SqlMigrationPlanContractInfo,
7
6
  SqlMigrationPlanOperation,
@@ -14,15 +13,19 @@ import type {
14
13
  } from '@prisma-next/family-sql/control';
15
14
  import { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';
16
15
  import { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';
17
- import type { ControlDriverInstance } from '@prisma-next/framework-components/control';
16
+ import type {
17
+ ControlDriverInstance,
18
+ MigrationRunnerResult,
19
+ } from '@prisma-next/framework-components/control';
18
20
  import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
21
+ import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
19
22
  import { SqlQueryError } from '@prisma-next/sql-errors';
20
23
  import { ifDefined } from '@prisma-next/utils/defined';
21
24
  import type { Result } from '@prisma-next/utils/result';
22
25
  import { notOk, ok, okVoid } from '@prisma-next/utils/result';
23
26
  import { parsePostgresDefault } from '../default-normalizer';
24
27
  import { normalizeSchemaNativeType } from '../native-type-normalizer';
25
- import { readExistingEnumValues } from './enum-planning';
28
+ import { createResolveExistingEnumValues } from './enum-planning';
26
29
  import type { PostgresPlanTargetDetails } from './planner-target-details';
27
30
  import {
28
31
  buildLedgerInsertStatement,
@@ -33,19 +36,11 @@ import {
33
36
  type SqlStatement,
34
37
  } from './statement-builders';
35
38
 
36
- interface RunnerConfig {
37
- readonly defaultSchema: string;
38
- }
39
-
40
39
  interface ApplyPlanSuccessValue {
41
40
  readonly operationsExecuted: number;
42
41
  readonly executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[];
43
42
  }
44
43
 
45
- const DEFAULT_CONFIG: RunnerConfig = {
46
- defaultSchema: 'public',
47
- };
48
-
49
44
  const LOCK_DOMAIN = 'prisma_next.contract.marker';
50
45
 
51
46
  /**
@@ -58,13 +53,10 @@ function cloneAndFreezeRecord<T extends Record<string, unknown>>(value: T): T {
58
53
  if (val === null || val === undefined) {
59
54
  cloned[key] = val;
60
55
  } else if (Array.isArray(val)) {
61
- // Clone array (shallow clone of array elements)
62
56
  cloned[key] = Object.freeze([...val]);
63
57
  } else if (typeof val === 'object') {
64
- // Recursively clone nested objects
65
58
  cloned[key] = cloneAndFreezeRecord(val as Record<string, unknown>);
66
59
  } else {
67
- // Primitives are copied as-is
68
60
  cloned[key] = val;
69
61
  }
70
62
  }
@@ -73,61 +65,27 @@ function cloneAndFreezeRecord<T extends Record<string, unknown>>(value: T): T {
73
65
 
74
66
  export function createPostgresMigrationRunner(
75
67
  family: SqlControlFamilyInstance,
76
- config: Partial<RunnerConfig> = {},
77
68
  ): SqlMigrationRunner<PostgresPlanTargetDetails> {
78
- return new PostgresMigrationRunner(family, { ...DEFAULT_CONFIG, ...config });
69
+ return new PostgresMigrationRunner(family);
79
70
  }
80
71
 
81
72
  class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDetails> {
82
- constructor(
83
- private readonly family: SqlControlFamilyInstance,
84
- private readonly config: RunnerConfig,
85
- ) {}
86
-
87
- async execute(
88
- options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
89
- ): Promise<SqlMigrationRunnerResult> {
90
- const driver = options.driver;
91
-
92
- // Static checks fail fast before any transaction work — no point
93
- // burning a BEGIN/ROLLBACK round-trip on a destination-contract
94
- // mismatch the caller can fix locally.
95
- const destinationCheck = this.ensurePlanMatchesDestinationContract(
96
- options.plan.destination,
97
- options.destinationContract,
98
- );
99
- if (!destinationCheck.ok) return destinationCheck;
100
-
101
- const policyCheck = this.enforcePolicyCompatibility(options.policy, options.plan.operations);
102
- if (!policyCheck.ok) return policyCheck;
103
-
104
- await this.beginTransaction(driver);
105
- let committed = false;
106
- try {
107
- const result = await this.executeOnConnection(options);
108
- if (!result.ok) {
109
- return result;
110
- }
111
- await this.commitTransaction(driver);
112
- committed = true;
113
- return result;
114
- } finally {
115
- if (!committed) {
116
- await this.rollbackTransaction(driver);
117
- }
118
- }
119
- }
73
+ constructor(private readonly family: SqlControlFamilyInstance) {}
120
74
 
121
75
  /**
122
76
  * Body of the migration runner without transaction management. The
123
- * caller (single-space `execute(...)` above, or the multi-space
124
- * outer-tx orchestrator at the SQL family level) owns the
77
+ * caller ({@link PostgresMigrationRunner.execute}) owns the
125
78
  * `BEGIN`/`COMMIT`/`ROLLBACK` lifecycle.
126
79
  */
127
80
  async executeOnConnection(
128
81
  options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,
129
82
  ): Promise<SqlMigrationRunnerResult> {
130
- const schema = options.schemaName ?? this.config.defaultSchema;
83
+ const schema =
84
+ options.schemaName ??
85
+ Object.keys(options.destinationContract.storage.namespaces).find(
86
+ (id) => id !== UNBOUND_NAMESPACE_ID,
87
+ ) ??
88
+ UNBOUND_NAMESPACE_ID;
131
89
  const driver = options.driver;
132
90
  if (options.space !== undefined && options.space !== options.plan.spaceId) {
133
91
  throw new Error(
@@ -188,8 +146,9 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
188
146
  frameworkComponents: options.frameworkComponents,
189
147
  normalizeDefault: parsePostgresDefault,
190
148
  normalizeNativeType: normalizeSchemaNativeType,
191
- resolveExistingEnumValues: (schema, enumType) =>
192
- readExistingEnumValues(schema, enumType.nativeType),
149
+ resolveExistingEnumValues: createResolveExistingEnumValues(
150
+ options.destinationContract.storage,
151
+ ),
193
152
  });
194
153
  if (!schemaVerifyResult.ok) {
195
154
  return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {
@@ -216,12 +175,12 @@ class PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDe
216
175
  });
217
176
  }
218
177
 
219
- async executeAcrossSpaces(options: {
178
+ async execute(options: {
220
179
  readonly driver: ControlDriverInstance<'sql', string>;
221
180
  readonly perSpaceOptions: ReadonlyArray<
222
181
  SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>
223
182
  >;
224
- }): Promise<MultiSpaceRunnerResult> {
183
+ }): Promise<MigrationRunnerResult> {
225
184
  const driver = options.driver;
226
185
  const perSpaceOptions = options.perSpaceOptions;
227
186
 
@@ -56,7 +56,7 @@ export interface MergeMarkerInput {
56
56
  * Logical space identifier for this marker row. Required at every
57
57
  * call site so the type system surfaces every place that needs to
58
58
  * thread the value (rather than letting an `?? APP_SPACE_ID`
59
- * fall-through silently collapse multi-space markers onto the
59
+ * fall-through silently collapse per-space markers onto the
60
60
  * `'app'` row). App-plan callers pass {@link APP_SPACE_ID}
61
61
  * (`'app'`); per-extension callers (planner / runner / verifier
62
62
  * extensions over contract spaces) pass the extension's space id.
@@ -52,12 +52,12 @@ function existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {
52
52
  *
53
53
  * A namespace's live container is the schema returned by its
54
54
  * polymorphic `ddlSchemaName(storage)` method — named schemas resolve
55
- * to their own id, the unbound singleton projects to `public` (sibling
56
- * present) or the framework sentinel (sibling absent). Issues are
57
- * emitted only when the resolved name is a real, creatable schema
58
- * (not the unbound sentinel) and is missing from the introspected
59
- * list. `public` is suppressed implicitly because the introspection
60
- * (or its sensible default) always carries it.
55
+ * to their own id; the unbound singleton returns `UNBOUND_NAMESPACE_ID`
56
+ * and is skipped explicitly (late-bound namespaces have no fixed DDL
57
+ * schema). Issues are emitted only when the resolved name is a real,
58
+ * creatable schema (not the unbound sentinel) and is missing from the
59
+ * introspected list. `public` is suppressed implicitly because the
60
+ * introspection (or its sensible default) always carries it.
61
61
  *
62
62
  * Each emitted issue stamps `namespaceId` with the contract namespace
63
63
  * coordinate so the downstream `mapIssueToCall` re-resolves the DDL
@@ -117,10 +117,10 @@ export class PostgresContractSerializer extends SqlContractSerializerBase<Contra
117
117
  if (isPostgresSchema(ns)) {
118
118
  namespacesJson[nsId] = this.serializePostgresNamespace(ns, ns.id === UNBOUND_NAMESPACE_ID);
119
119
  } else {
120
- // Family-level SqlNamespacePayload / SqlUnboundNamespace haven't
121
- // been promoted to a PostgresSchema instance yet (e.g. they came
122
- // straight from the TS builder, which uses the family-shared
123
- // SqlStorage constructor). Serialise them as postgres-schema /
120
+ // Family-level SqlUnboundNamespace or other family-built SQL
121
+ // namespaces haven't been promoted to a PostgresSchema instance
122
+ // yet (e.g. they came straight from the TS builder before a target
123
+ // `createNamespace` factory ran). Serialise them as postgres-schema /
124
124
  // postgres-unbound-schema so the round-trip through
125
125
  // deserializeContract hydrates them back into PostgresSchema
126
126
  // instances.
@@ -120,10 +120,11 @@ export class PostgresSchema extends NamespaceBase {
120
120
  * statements that need to identify this namespace in the live
121
121
  * database (e.g. `CREATE TABLE "<ddlSchemaName>"."<table>" …`,
122
122
  * catalog filters, planner conflict lookups). Named schemas resolve
123
- * to their own id; the unbound singleton overrides this to project
124
- * to `'public'` when a sibling public namespace exists in the same
125
- * contract and falls back to the framework sentinel otherwise so
126
- * the planner can detect the missing-projection case explicitly.
123
+ * to their own id. The `PostgresUnboundSchema` singleton inherits
124
+ * this and returns `UNBOUND_NAMESPACE_ID` callers that dispatch
125
+ * through `qualifyTableName` / `toRegclassLiteral` route through the
126
+ * polymorphic `PostgresUnboundSchema` overrides and produce
127
+ * unqualified (search-path-resolved) output automatically.
127
128
  */
128
129
  ddlSchemaName(_storage: SqlStorage): string {
129
130
  return this.id;
@@ -143,6 +144,11 @@ export class PostgresSchema extends NamespaceBase {
143
144
  * sentinel; Postgres decides what late-bound means here (the table
144
145
  * name, naked — the schema is supplied by the live connection's
145
146
  * `search_path`).
147
+ *
148
+ * `ddlSchemaName` is inherited from `PostgresSchema` and returns
149
+ * `UNBOUND_NAMESPACE_ID`. Downstream helpers (`qualifyTableName`,
150
+ * `toRegclassLiteral`) route through the polymorphic factory and
151
+ * produce unqualified output automatically.
146
152
  */
147
153
  export class PostgresUnboundSchema extends PostgresSchema {
148
154
  static readonly instance: PostgresUnboundSchema = new PostgresUnboundSchema();
@@ -162,22 +168,6 @@ export class PostgresUnboundSchema extends PostgresSchema {
162
168
  override schemaSqlExpression(): string {
163
169
  return 'current_schema()';
164
170
  }
165
-
166
- /**
167
- * The unbound slot has no schema name of its own, so DDL emission
168
- * projects it onto a sibling when one is available: if the contract
169
- * carries a `public` namespace, the late-bound slot resolves to
170
- * `'public'` (the default Postgres landing schema); otherwise it
171
- * resolves to the framework sentinel `UNBOUND_NAMESPACE_ID` so the
172
- * planner can recognise the unprojected case and route accordingly
173
- * (e.g. emit a conflict instead of silently picking a schema).
174
- */
175
- override ddlSchemaName(storage: SqlStorage): string {
176
- if (storage.namespaces['public'] !== undefined) {
177
- return 'public';
178
- }
179
- return UNBOUND_NAMESPACE_ID;
180
- }
181
171
  }
182
172
 
183
173
  PostgresSchema.unbound = PostgresUnboundSchema.instance;
@@ -12,6 +12,10 @@ import type {
12
12
  import type { SqlStorage, StorageColumn } from '@prisma-next/sql-contract/types';
13
13
  import { ifDefined } from '@prisma-next/utils/defined';
14
14
  import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
15
+ import {
16
+ enumStorageCompoundKey,
17
+ resolveDdlSchemaForNamespaceStorage,
18
+ } from '../core/migrations/enum-planning';
15
19
  import { createPostgresMigrationPlanner } from '../core/migrations/planner';
16
20
  import { renderDefaultLiteral } from '../core/migrations/planner-ddl-builders';
17
21
  import type { PostgresPlanTargetDetails } from '../core/migrations/planner-target-details';
@@ -78,6 +82,18 @@ const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresP
78
82
  annotationNamespace: 'pg',
79
83
  ...ifDefined('expandNativeType', expander),
80
84
  renderDefault: postgresRenderDefault,
85
+ // Schema-qualify enum annotation keys so the projected "from" IR's
86
+ // `storageTypes` match `readExistingEnumValues` on the read side
87
+ // (the contract-to-contract `migration plan` path). The DDL-schema
88
+ // resolution + compound-key format stay here in the target layer;
89
+ // the family projector treats the returned string as opaque.
90
+ // `undefined` schema IR ⇒ the unbound coordinate resolves to the
91
+ // default `public` landing schema, matching the read-side fallback.
92
+ resolveEnumStorageKey: (storage, namespaceId, nativeType) =>
93
+ enumStorageCompoundKey(
94
+ resolveDdlSchemaForNamespaceStorage(storage, namespaceId, undefined),
95
+ nativeType,
96
+ ),
81
97
  });
82
98
  },
83
99
  },
@@ -1,6 +1,11 @@
1
1
  export {
2
+ createResolveExistingEnumValues,
2
3
  determineEnumDiff,
3
4
  type EnumDiff,
5
+ enumStorageCompoundKey,
4
6
  getDesiredEnumValues,
7
+ type PostgresSchemaIrAnnotations,
5
8
  readExistingEnumValues,
9
+ readPostgresSchemaIrAnnotations,
10
+ resolveDdlSchemaForNamespaceStorage,
6
11
  } from '../core/migrations/enum-planning';
@@ -3,7 +3,7 @@ import type {
3
3
  RuntimeTargetDescriptor,
4
4
  RuntimeTargetInstance,
5
5
  } from '@prisma-next/framework-components/execution';
6
- import { postgresTargetDescriptorMeta } from '../core/descriptor-meta';
6
+ import { postgresTargetDescriptorMetaRuntime } from '../core/descriptor-meta-runtime';
7
7
 
8
8
  export { PostgresContractSerializer } from '../core/postgres-contract-serializer';
9
9
 
@@ -22,7 +22,7 @@ const postgresRuntimeTargetDescriptor: RuntimeTargetDescriptor<
22
22
  > & {
23
23
  readonly codecs: () => readonly AnyCodecDescriptor[];
24
24
  } = {
25
- ...postgresTargetDescriptorMeta,
25
+ ...postgresTargetDescriptorMetaRuntime,
26
26
  codecs: () => [],
27
27
  create(): PostgresRuntimeTargetInstance {
28
28
  return {
@@ -1 +0,0 @@
1
- {"version":3,"file":"codec-types-CRlHq7Cz.d.mts","names":[],"sources":["../src/core/codec-type-map.ts","../src/exports/codec-types.ts"],"mappings":";;;;;;cA4Ca,kBAAA;EAAA,eA8BH,uCAAA,CAAA,iBAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEE,OAAA,6BAAoC,CAAA,0BAA2B,CAAA,CAAE,CAAA,IAAK,CAAA,CAAE,CAAA,EAAG,CAAA;AAAA,KAE3E,kBAAA,UAA4B,kBAAA;AAAA,KAE5B,mBAAA,GAAsB,iBAAA,CAAkB,kBAAA;;;KCrExC,UAAA,GAAa,OAAA,CAAQ,mBAAA;AAAA,KAI5B,OAAA,kBAAyB,MAAA,qBAA2B,CAAA,0BAClC,KAAA,GAAQ,KAAA,CAAM,CAAA;AAAA,KAGhC,aAAA,eAA4B,MAAA,qBAA2B,OAAA,SAAgB,KAAA;AAAA,KAEhE,IAAA,qBAAyB,aAAA;EAAgB,YAAA,EAAc,CAAA;AAAA;AAAA,KACvD,OAAA,qBAA4B,aAAA;EAAgB,eAAA,EAAiB,CAAA;AAAA;AAAA,KAC7D,OAAA,+DAAsE,aAAA;EAChF,kBAAA,EAAoB,CAAA;EACpB,cAAA,EAAgB,CAAA;AAAA;AAAA,KAEN,GAAA,qBAAwB,aAAA;EAAgB,WAAA,EAAa,CAAA;AAAA;AAAA,KACrD,MAAA,qBAA2B,aAAA;EAAgB,cAAA,EAAgB,CAAA;AAAA;AAAA,KAC3D,SAAA,6CAAsD,aAAA;EAChE,oBAAA,EAAsB,CAAA;AAAA;AAAA,KAEZ,WAAA,6CAAwD,aAAA;EAClE,sBAAA,EAAwB,CAAA;AAAA;AAAA,KAEd,IAAA,6CAAiD,aAAA;EAAgB,eAAA,EAAiB,CAAA;AAAA;AAAA,KAClF,MAAA,6CAAmD,aAAA;EAC7D,iBAAA,EAAmB,CAAA;AAAA;AAAA,KAET,QAAA,6CAAqD,aAAA;EAC/D,mBAAA,EAAqB,CAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-transform-bmOKkygi.d.mts","names":[],"sources":["../src/core/migrations/operations/data-transform.ts"],"mappings":";;;;;;;;UAqEU,SAAA;EACR,KAAA,IAAS,YAAA,CAAa,CAAA;AAAA;;;;;KAOZ,oBAAA,SAA6B,YAAA,GAAe,SAAA;AAAA,UAEvC,oBAAA;;;;;;WAMN,WAAA;;;;;;;;WAQA,KAAA,GAAQ,oBAAA;;WAER,GAAA,EAAK,oBAAA,YAAgC,oBAAA;AAAA;AAAA,iBAGhC,aAAA,mBAAgC,QAAA,CAAS,UAAA,EAAA,CACvD,QAAA,EAAU,SAAA,EACV,IAAA,UACA,OAAA,EAAS,oBAAA,EACT,OAAA,EAAS,iBAAA,eACR,yBAAA,CAA0B,yBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"descriptor-meta-DLA2xV6B.mjs","names":[],"sources":["../src/core/authoring.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import { temporalAuthoringPresets } from '@prisma-next/family-sql/control';\nimport type {\n AuthoringEntityTypeNamespace,\n AuthoringFieldNamespace,\n AuthoringTypeNamespace,\n} from '@prisma-next/framework-components/authoring';\nimport type { PostgresEnumStorageEntry } from '@prisma-next/sql-contract/types';\nimport { PostgresEnumTypeSchema } from '@prisma-next/sql-contract/validators';\nimport { PostgresEnumType, type PostgresEnumTypeInput } from './postgres-enum-type';\n\nexport const postgresAuthoringTypes = {} as const satisfies AuthoringTypeNamespace;\n\n/**\n * Entity type contributions surface as top-level helpers on the\n * composed-helpers shape (e.g. `helpers.enum({...})`), flattened\n * alongside the built-in `model` / `rel` helpers. Pack contributions\n * still ship via the contribution data structure\n * `authoring.entityTypes.<name>`; the composed-helpers template\n * performs the rename in the type system.\n *\n * `enum` is the first real consumer of the entities-namespace mechanism:\n * the factory constructs a `PostgresEnumType` IR-class instance from\n * the user-supplied input. Both authoring runtimes (TS DSL and PSL)\n * dispatch through this single contribution — PSL `enum Status { … }`\n * declarations are lowered by the interpreter into a factory call\n * with the parsed name + value list; TS DSL `helpers.enum({...})`\n * resolves through the same path. Removing this contribution makes\n * both surfaces fail with a \"no entity helper named `enum`\" type\n * error at the contract-definition site.\n */\n/**\n * The factory constructs a `PostgresEnumType` instance natively — the\n * `SqlStorage.types` slot accepts polymorphic IR (the framework\n * `StorageType` alphabet), so no cast is needed at the contribution\n * surface. The declared return type is the structural\n * `PostgresEnumStorageEntry` so the inferred contract type stays\n * portable (it names a type exported from\n * `@prisma-next/sql-contract/types`, a public surface every consumer\n * already imports). Sharpening the inferred contract type to surface\n * enum-specific narrowing through `EntityHelperFunction` is a\n * separable refinement and lives outside this PR.\n */\nexport const postgresAuthoringEntityTypes = {\n enum: {\n kind: 'entity',\n discriminator: 'postgres-enum',\n validatorSchema: PostgresEnumTypeSchema,\n output: {\n factory: (input: PostgresEnumTypeInput): PostgresEnumStorageEntry =>\n new PostgresEnumType(input),\n },\n },\n} as const satisfies AuthoringEntityTypeNamespace;\n\n/**\n * Field presets contributed by the Postgres target pack.\n *\n * These mirror the PSL scalar-to-codec mapping used by the Postgres adapter\n * (see `createPostgresPslScalarTypeDescriptors`), so that authoring a field\n * via the TS callback surface (e.g. `field.int()`) and via the PSL scalar\n * surface (e.g. `Int`) lowers to byte-identical contracts.\n */\nexport const postgresAuthoringFieldPresets = {\n text: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/text@1',\n nativeType: 'text',\n },\n },\n int: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/int4@1',\n nativeType: 'int4',\n },\n },\n bigint: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/int8@1',\n nativeType: 'int8',\n },\n },\n float: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/float8@1',\n nativeType: 'float8',\n },\n },\n decimal: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/numeric@1',\n nativeType: 'numeric',\n },\n },\n boolean: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/bool@1',\n nativeType: 'bool',\n },\n },\n json: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/jsonb@1',\n nativeType: 'jsonb',\n },\n },\n bytes: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/bytea@1',\n nativeType: 'bytea',\n },\n },\n dateTime: {\n kind: 'fieldPreset',\n output: {\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n },\n },\n temporal: temporalAuthoringPresets({\n codecId: 'pg/timestamptz@1',\n nativeType: 'timestamptz',\n }),\n} as const satisfies AuthoringFieldNamespace;\n","import type { CodecTypes } from '../exports/codec-types';\nimport {\n postgresAuthoringEntityTypes,\n postgresAuthoringFieldPresets,\n postgresAuthoringTypes,\n} from './authoring';\n\nconst postgresTargetDescriptorMetaBase = {\n kind: 'target',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {},\n authoring: {\n type: postgresAuthoringTypes,\n field: postgresAuthoringFieldPresets,\n entityTypes: postgresAuthoringEntityTypes,\n },\n} as const;\n\nexport const postgresTargetDescriptorMeta: typeof postgresTargetDescriptorMetaBase & {\n readonly __codecTypes?: CodecTypes;\n} = postgresTargetDescriptorMetaBase;\n"],"mappings":";;;;AAUA,MAAa,yBAAyB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCxC,MAAa,+BAA+B,EAC1C,MAAM;CACJ,MAAM;CACN,eAAe;CACf,iBAAiB;CACjB,QAAQ,EACN,UAAU,UACR,IAAI,iBAAiB,MAAM,EAC9B;CACF,EACF;AC/BD,MAAa,+BAET;CAfF,MAAM;CACN,UAAU;CACV,UAAU;CACV,IAAI;CACJ,SAAS;CACT,cAAc,EAAE;CAChB,WAAW;EACT,MAAM;EACN,OAAO;GD+CT,MAAM;IACJ,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,KAAK;IACH,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,QAAQ;IACN,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,OAAO;IACL,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,SAAS;IACP,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,SAAS;IACP,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,MAAM;IACJ,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,OAAO;IACL,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,UAAU;IACR,MAAM;IACN,QAAQ;KACN,SAAS;KACT,YAAY;KACb;IACF;GACD,UAAU,yBAAyB;IACjC,SAAS;IACT,YAAY;IACb,CAAC;GCjHO;EACP,aAAa;EACd;CAKC"}
@@ -1,63 +0,0 @@
1
- import "./codec-ids-C5qzBqus.mjs";
2
- import { arraysEqual } from "@prisma-next/family-sql/schema-verify";
3
- //#region src/core/migrations/enum-planning.ts
4
- /**
5
- * Pure planning helpers for Postgres enum types: the diff/rebuild logic
6
- * that the verifier and planner use to walk `PostgresEnumType` instances
7
- * natively. Op builders live in `./operations/enums.ts`.
8
- */
9
- /**
10
- * Reads existing enum values for `nativeType` from the
11
- * Postgres-introspected `schema.annotations.pg.storageTypes` map.
12
- *
13
- * Schema IR's `storageTypes` slots are always codec-typed
14
- * (`{codecId: PG_ENUM_CODEC_ID, typeParams.values}`): the introspector
15
- * writes that shape, and the Contract→Schema IR projector resolves
16
- * `PostgresEnumType` instances down to the same codec-typed triple before
17
- * they ever land in Schema IR. There is no second on-disk shape to
18
- * accept here.
19
- *
20
- * Returns `null` when no enum entry exists for the given native type.
21
- */
22
- function readExistingEnumValues(schema, nativeType) {
23
- const existing = ((schema.annotations?.["pg"])?.["storageTypes"])?.[nativeType];
24
- if (!existing || existing.codecId !== "pg/enum@1") return null;
25
- const enumValues = existing.typeParams?.values;
26
- if (!Array.isArray(enumValues) || !enumValues.every((v) => typeof v === "string")) return null;
27
- return enumValues;
28
- }
29
- /**
30
- * Determines what changes are needed to transform existing enum values to
31
- * desired values.
32
- *
33
- * Postgres enums can only have values added (not removed or reordered)
34
- * without a full type rebuild involving temp type creation and column
35
- * migration; `'rebuild'` covers the value-removal and reorder cases.
36
- */
37
- function determineEnumDiff(existing, desired) {
38
- if (arraysEqual(existing, desired)) return { kind: "unchanged" };
39
- const existingSet = new Set(existing);
40
- const desiredSet = new Set(desired);
41
- const missingValues = desired.filter((value) => !existingSet.has(value));
42
- const removedValues = existing.filter((value) => !desiredSet.has(value));
43
- const orderMismatch = missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);
44
- if (removedValues.length > 0 || orderMismatch) return {
45
- kind: "rebuild",
46
- removedValues
47
- };
48
- return {
49
- kind: "add_values",
50
- values: missingValues
51
- };
52
- }
53
- /**
54
- * Convenience accessor — returns the enum's desired values from a
55
- * `PostgresEnumType` IR instance.
56
- */
57
- function getDesiredEnumValues(typeInstance) {
58
- return typeInstance.values;
59
- }
60
- //#endregion
61
- export { getDesiredEnumValues as n, readExistingEnumValues as r, determineEnumDiff as t };
62
-
63
- //# sourceMappingURL=enum-planning-Bqp96iIw.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"enum-planning-Bqp96iIw.mjs","names":[],"sources":["../src/core/migrations/enum-planning.ts"],"sourcesContent":["/**\n * Pure planning helpers for Postgres enum types: the diff/rebuild logic\n * that the verifier and planner use to walk `PostgresEnumType` instances\n * natively. Op builders live in `./operations/enums.ts`.\n */\n\nimport { arraysEqual } from '@prisma-next/family-sql/schema-verify';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { PG_ENUM_CODEC_ID } from '../codec-ids';\nimport type { PostgresEnumType } from '../postgres-enum-type';\n\n/**\n * Categorisation of how an existing enum type's values relate to the\n * desired set in the contract.\n */\nexport type EnumDiff =\n | { readonly kind: 'unchanged' }\n | { readonly kind: 'add_values'; readonly values: readonly string[] }\n | { readonly kind: 'rebuild'; readonly removedValues: readonly string[] };\n\n/**\n * Reads existing enum values for `nativeType` from the\n * Postgres-introspected `schema.annotations.pg.storageTypes` map.\n *\n * Schema IR's `storageTypes` slots are always codec-typed\n * (`{codecId: PG_ENUM_CODEC_ID, typeParams.values}`): the introspector\n * writes that shape, and the Contract→Schema IR projector resolves\n * `PostgresEnumType` instances down to the same codec-typed triple before\n * they ever land in Schema IR. There is no second on-disk shape to\n * accept here.\n *\n * Returns `null` when no enum entry exists for the given native type.\n */\nexport function readExistingEnumValues(\n schema: SqlSchemaIR,\n nativeType: string,\n): readonly string[] | null {\n const storageTypes = (schema.annotations?.['pg'] as Record<string, unknown> | undefined)?.[\n 'storageTypes'\n ] as\n | Record<\n string,\n {\n codecId?: string;\n typeParams?: { values?: unknown };\n }\n >\n | undefined;\n const existing = storageTypes?.[nativeType];\n if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {\n return null;\n }\n const enumValues = existing.typeParams?.values;\n if (!Array.isArray(enumValues) || !enumValues.every((v) => typeof v === 'string')) {\n return null;\n }\n return enumValues as readonly string[];\n}\n\n/**\n * Determines what changes are needed to transform existing enum values to\n * desired values.\n *\n * Postgres enums can only have values added (not removed or reordered)\n * without a full type rebuild involving temp type creation and column\n * migration; `'rebuild'` covers the value-removal and reorder cases.\n */\nexport function determineEnumDiff(\n existing: readonly string[],\n desired: readonly string[],\n): EnumDiff {\n if (arraysEqual(existing, desired)) {\n return { kind: 'unchanged' };\n }\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n const missingValues = desired.filter((value) => !existingSet.has(value));\n const removedValues = existing.filter((value) => !desiredSet.has(value));\n const orderMismatch =\n missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);\n if (removedValues.length > 0 || orderMismatch) {\n return { kind: 'rebuild', removedValues };\n }\n return { kind: 'add_values', values: missingValues };\n}\n\n/**\n * Convenience accessor — returns the enum's desired values from a\n * `PostgresEnumType` IR instance.\n */\nexport function getDesiredEnumValues(typeInstance: PostgresEnumType): readonly string[] {\n return typeInstance.values;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,uBACd,QACA,YAC0B;CAY1B,MAAM,aAXgB,OAAO,cAAc,SACzC,mBAU8B;CAChC,IAAI,CAAC,YAAY,SAAS,YAAA,aACxB,OAAO;CAET,MAAM,aAAa,SAAS,YAAY;CACxC,IAAI,CAAC,MAAM,QAAQ,WAAW,IAAI,CAAC,WAAW,OAAO,MAAM,OAAO,MAAM,SAAS,EAC/E,OAAO;CAET,OAAO;;;;;;;;;;AAWT,SAAgB,kBACd,UACA,SACU;CACV,IAAI,YAAY,UAAU,QAAQ,EAChC,OAAO,EAAE,MAAM,aAAa;CAE9B,MAAM,cAAc,IAAI,IAAI,SAAS;CACrC,MAAM,aAAa,IAAI,IAAI,QAAQ;CACnC,MAAM,gBAAgB,QAAQ,QAAQ,UAAU,CAAC,YAAY,IAAI,MAAM,CAAC;CACxE,MAAM,gBAAgB,SAAS,QAAQ,UAAU,CAAC,WAAW,IAAI,MAAM,CAAC;CACxE,MAAM,gBACJ,cAAc,WAAW,KAAK,cAAc,WAAW,KAAK,CAAC,YAAY,UAAU,QAAQ;CAC7F,IAAI,cAAc,SAAS,KAAK,eAC9B,OAAO;EAAE,MAAM;EAAW;EAAe;CAE3C,OAAO;EAAE,MAAM;EAAc,QAAQ;EAAe;;;;;;AAOtD,SAAgB,qBAAqB,cAAmD;CACtF,OAAO,aAAa"}