@prisma-next/family-sql 0.9.0 → 0.10.0-dev.2

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.
@@ -1,6 +1,7 @@
1
1
  import { assertUniqueCodecOwner } from "@prisma-next/framework-components/control";
2
2
  import { ifDefined } from "@prisma-next/utils/defined";
3
- import { isPostgresEnumStorageEntry, isStorageTypeInstance } from "@prisma-next/sql-contract/types";
3
+ import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
4
+ import { StorageTable, isPostgresEnumStorageEntry, isStorageTypeInstance } from "@prisma-next/sql-contract/types";
4
5
  import { canonicalStringify } from "@prisma-next/utils/canonical-stringify";
5
6
  //#region src/core/assembly.ts
6
7
  function hasCodecControlHooks(descriptor) {
@@ -91,11 +92,12 @@ function isIndexSatisfied(indexes, uniques, columns) {
91
92
  * Uses semantic satisfaction: identity is based on (table + kind + columns).
92
93
  * Name differences are ignored by default (names are for DDL/diagnostics, not identity).
93
94
  */
94
- function verifyPrimaryKey(contractPK, schemaPK, tableName, issues) {
95
+ function verifyPrimaryKey(contractPK, schemaPK, tableName, namespaceId, issues) {
95
96
  if (!schemaPK) {
96
97
  issues.push({
97
98
  kind: "primary_key_mismatch",
98
99
  table: tableName,
100
+ namespaceId,
99
101
  expected: contractPK.columns.join(", "),
100
102
  message: `Table "${tableName}" is missing primary key`
101
103
  });
@@ -105,6 +107,7 @@ function verifyPrimaryKey(contractPK, schemaPK, tableName, issues) {
105
107
  issues.push({
106
108
  kind: "primary_key_mismatch",
107
109
  table: tableName,
110
+ namespaceId,
108
111
  expected: contractPK.columns.join(", "),
109
112
  actual: schemaPK.columns.join(", "),
110
113
  message: `Table "${tableName}" has primary key mismatch: expected columns [${contractPK.columns.join(", ")}], got [${schemaPK.columns.join(", ")}]`
@@ -120,24 +123,26 @@ function verifyPrimaryKey(contractPK, schemaPK, tableName, issues) {
120
123
  * Uses semantic satisfaction: identity is based on (table + columns + referenced table + referenced columns).
121
124
  * Name differences are ignored by default (names are for DDL/diagnostics, not identity).
122
125
  */
123
- function verifyForeignKeys(contractFKs, schemaFKs, tableName, tablePath, issues, strict) {
126
+ function verifyForeignKeys(contractFKs, schemaFKs, tableName, namespaceId, tablePath, issues, strict) {
124
127
  const nodes = [];
125
128
  for (const contractFK of contractFKs) {
126
- const fkPath = `${tablePath}.foreignKeys[${contractFK.columns.join(",")}]`;
129
+ const fkPath = `${tablePath}.foreignKeys[${contractFK.source.columns.join(",")}]`;
127
130
  const matchingFK = schemaFKs.find((fk) => {
128
- return arraysEqual(fk.columns, contractFK.columns) && fk.referencedTable === contractFK.references.table && arraysEqual(fk.referencedColumns, contractFK.references.columns);
131
+ const tablesMatch = fk.referencedSchema !== void 0 && contractFK.target.namespaceId !== UNBOUND_NAMESPACE_ID ? fk.referencedSchema === contractFK.target.namespaceId && fk.referencedTable === contractFK.target.tableName : fk.referencedTable === contractFK.target.tableName;
132
+ return arraysEqual(fk.columns, contractFK.source.columns) && tablesMatch && arraysEqual(fk.referencedColumns, contractFK.target.columns);
129
133
  });
130
134
  if (!matchingFK) {
131
135
  issues.push({
132
136
  kind: "foreign_key_mismatch",
133
137
  table: tableName,
134
- expected: `${contractFK.columns.join(", ")} -> ${contractFK.references.table}(${contractFK.references.columns.join(", ")})`,
135
- message: `Table "${tableName}" is missing foreign key: ${contractFK.columns.join(", ")} -> ${contractFK.references.table}(${contractFK.references.columns.join(", ")})`
138
+ namespaceId,
139
+ expected: `${contractFK.source.columns.join(", ")} -> ${contractFK.target.tableName}(${contractFK.target.columns.join(", ")})`,
140
+ message: `Table "${tableName}" is missing foreign key: ${contractFK.source.columns.join(", ")} -> ${contractFK.target.tableName}(${contractFK.target.columns.join(", ")})`
136
141
  });
137
142
  nodes.push({
138
143
  status: "fail",
139
144
  kind: "foreignKey",
140
- name: `foreignKey(${contractFK.columns.join(", ")})`,
145
+ name: `foreignKey(${contractFK.source.columns.join(", ")})`,
141
146
  contractPath: fkPath,
142
147
  code: "foreign_key_mismatch",
143
148
  message: "Foreign key missing",
@@ -154,15 +159,16 @@ function verifyForeignKeys(contractFKs, schemaFKs, tableName, tablePath, issues,
154
159
  issues.push({
155
160
  kind: "foreign_key_mismatch",
156
161
  table: tableName,
157
- indexOrConstraint: matchingFK.name ?? `fk(${contractFK.columns.join(",")})`,
162
+ namespaceId,
163
+ indexOrConstraint: matchingFK.name ?? `fk(${contractFK.source.columns.join(",")})`,
158
164
  expected: combinedExpected,
159
165
  actual: combinedActual,
160
- message: `Table "${tableName}" foreign key ${contractFK.columns.join(", ")} -> ${contractFK.references.table}: ${combinedMessage}`
166
+ message: `Table "${tableName}" foreign key ${contractFK.source.columns.join(", ")} -> ${contractFK.target.tableName}: ${combinedMessage}`
161
167
  });
162
168
  nodes.push({
163
169
  status: "fail",
164
170
  kind: "foreignKey",
165
- name: `foreignKey(${contractFK.columns.join(", ")})`,
171
+ name: `foreignKey(${contractFK.source.columns.join(", ")})`,
166
172
  contractPath: fkPath,
167
173
  code: "foreign_key_mismatch",
168
174
  message: combinedMessage,
@@ -173,7 +179,7 @@ function verifyForeignKeys(contractFKs, schemaFKs, tableName, tablePath, issues,
173
179
  } else nodes.push({
174
180
  status: "pass",
175
181
  kind: "foreignKey",
176
- name: `foreignKey(${contractFK.columns.join(", ")})`,
182
+ name: `foreignKey(${contractFK.source.columns.join(", ")})`,
177
183
  contractPath: fkPath,
178
184
  code: "",
179
185
  message: "",
@@ -185,11 +191,13 @@ function verifyForeignKeys(contractFKs, schemaFKs, tableName, tablePath, issues,
185
191
  }
186
192
  if (strict) {
187
193
  for (const schemaFK of schemaFKs) if (!contractFKs.find((fk) => {
188
- return arraysEqual(fk.columns, schemaFK.columns) && fk.references.table === schemaFK.referencedTable && arraysEqual(fk.references.columns, schemaFK.referencedColumns);
194
+ const tablesMatch = schemaFK.referencedSchema !== void 0 && fk.target.namespaceId !== UNBOUND_NAMESPACE_ID ? schemaFK.referencedSchema === fk.target.namespaceId && schemaFK.referencedTable === fk.target.tableName : schemaFK.referencedTable === fk.target.tableName;
195
+ return arraysEqual(fk.source.columns, schemaFK.columns) && tablesMatch && arraysEqual(fk.target.columns, schemaFK.referencedColumns);
189
196
  })) {
190
197
  issues.push({
191
198
  kind: "extra_foreign_key",
192
199
  table: tableName,
200
+ namespaceId,
193
201
  indexOrConstraint: schemaFK.name ?? `fk(${schemaFK.columns.join(",")})`,
194
202
  message: `Extra foreign key found in database (not in contract): ${schemaFK.columns.join(", ")} -> ${schemaFK.referencedTable}(${schemaFK.referencedColumns.join(", ")})`
195
203
  });
@@ -219,7 +227,7 @@ function verifyForeignKeys(contractFKs, schemaFKs, tableName, tablePath, issues,
219
227
  *
220
228
  * Name differences are ignored by default (names are for DDL/diagnostics, not identity).
221
229
  */
222
- function verifyUniqueConstraints(contractUniques, schemaUniques, schemaIndexes, tableName, tablePath, issues, strict) {
230
+ function verifyUniqueConstraints(contractUniques, schemaUniques, schemaIndexes, tableName, namespaceId, tablePath, issues, strict) {
223
231
  const nodes = [];
224
232
  for (const contractUnique of contractUniques) {
225
233
  const uniquePath = `${tablePath}.uniques[${contractUnique.columns.join(",")}]`;
@@ -229,6 +237,7 @@ function verifyUniqueConstraints(contractUniques, schemaUniques, schemaIndexes,
229
237
  issues.push({
230
238
  kind: "unique_constraint_mismatch",
231
239
  table: tableName,
240
+ namespaceId,
232
241
  expected: contractUnique.columns.join(", "),
233
242
  message: `Table "${tableName}" is missing unique constraint: ${contractUnique.columns.join(", ")}`
234
243
  });
@@ -260,6 +269,7 @@ function verifyUniqueConstraints(contractUniques, schemaUniques, schemaIndexes,
260
269
  issues.push({
261
270
  kind: "extra_unique_constraint",
262
271
  table: tableName,
272
+ namespaceId,
263
273
  indexOrConstraint: schemaUnique.name ?? `unique(${schemaUnique.columns.join(",")})`,
264
274
  message: `Extra unique constraint found in database (not in contract): ${schemaUnique.columns.join(", ")}`
265
275
  });
@@ -289,7 +299,7 @@ function verifyUniqueConstraints(contractUniques, schemaUniques, schemaIndexes,
289
299
  *
290
300
  * Name differences are ignored by default (names are for DDL/diagnostics, not identity).
291
301
  */
292
- function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName, tablePath, issues, strict) {
302
+ function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName, namespaceId, tablePath, issues, strict) {
293
303
  const nodes = [];
294
304
  for (const contractIndex of contractIndexes) {
295
305
  const indexPath = `${tablePath}.indexes[${contractIndex.columns.join(",")}]`;
@@ -299,6 +309,7 @@ function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName,
299
309
  issues.push({
300
310
  kind: "index_mismatch",
301
311
  table: tableName,
312
+ namespaceId,
302
313
  expected: contractIndex.columns.join(", "),
303
314
  message: `Table "${tableName}" is missing index: ${contractIndex.columns.join(", ")}`
304
315
  });
@@ -331,6 +342,7 @@ function verifyIndexes(contractIndexes, schemaIndexes, schemaUniques, tableName,
331
342
  issues.push({
332
343
  kind: "extra_index",
333
344
  table: tableName,
345
+ namespaceId,
334
346
  indexOrConstraint: schemaIndex.name ?? `idx(${schemaIndex.columns.join(",")})`,
335
347
  message: `Extra index found in database (not in contract): ${schemaIndex.columns.join(", ")}`
336
348
  });
@@ -421,7 +433,12 @@ function verifySqlSchema(options) {
421
433
  const startTime = Date.now();
422
434
  const codecHooks = extractCodecControlHooks(options.frameworkComponents);
423
435
  const { contractStorageHash, contractProfileHash, contractTarget } = extractContractMetadata(contract);
424
- const storageTypes = contract.storage.types ?? {};
436
+ const allStorageTypesMap = { ...contract.storage.types ?? {} };
437
+ for (const ns of Object.values(contract.storage.namespaces)) {
438
+ const nsTypes = ns.types;
439
+ if (nsTypes) for (const [k, v] of Object.entries(nsTypes)) allStorageTypesMap[k] = v;
440
+ }
441
+ const storageTypes = allStorageTypesMap;
425
442
  const { issues, rootChildren } = verifySchemaTables({
426
443
  contract,
427
444
  schema,
@@ -552,47 +569,55 @@ function verifySchemaTables(options) {
552
569
  const { contract, schema, strict, typeMetadataRegistry, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
553
570
  const issues = [];
554
571
  const rootChildren = [];
555
- const contractTables = contract.storage.tables;
556
572
  const schemaTables = schema.tables;
557
- for (const [tableName, contractTable] of Object.entries(contractTables)) {
558
- const schemaTable = schemaTables[tableName];
559
- const tablePath = `storage.tables.${tableName}`;
560
- if (!schemaTable) {
561
- issues.push({
562
- kind: "missing_table",
563
- table: tableName,
564
- message: `Table "${tableName}" is missing from database`
565
- });
566
- rootChildren.push({
567
- status: "fail",
568
- kind: "table",
569
- name: `table ${tableName}`,
570
- contractPath: tablePath,
571
- code: "missing_table",
572
- message: `Table "${tableName}" is missing`,
573
- expected: void 0,
574
- actual: void 0,
575
- children: []
573
+ const namespaceIds = Object.keys(contract.storage.namespaces).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
574
+ for (const namespaceId of namespaceIds) {
575
+ const ns = contract.storage.namespaces[namespaceId];
576
+ if (!ns) continue;
577
+ for (const [tableName, contractTableRaw] of Object.entries(ns.tables)) {
578
+ if (!(contractTableRaw instanceof StorageTable)) throw new Error(`verifySqlSchema: expected StorageTable at storage.namespaces.${namespaceId}.tables.${tableName}`);
579
+ const contractTable = contractTableRaw;
580
+ const schemaTable = schemaTables[tableName];
581
+ const tablePath = `storage.namespaces.${namespaceId}.tables.${tableName}`;
582
+ if (!schemaTable) {
583
+ issues.push({
584
+ kind: "missing_table",
585
+ table: tableName,
586
+ namespaceId,
587
+ message: `Table "${tableName}" is missing from database`
588
+ });
589
+ rootChildren.push({
590
+ status: "fail",
591
+ kind: "table",
592
+ name: `table ${tableName}`,
593
+ contractPath: tablePath,
594
+ code: "missing_table",
595
+ message: `Table "${tableName}" is missing`,
596
+ expected: void 0,
597
+ actual: void 0,
598
+ children: []
599
+ });
600
+ continue;
601
+ }
602
+ const tableChildren = verifyTableChildren({
603
+ contractTable,
604
+ schemaTable,
605
+ tableName,
606
+ namespaceId,
607
+ tablePath,
608
+ issues,
609
+ strict,
610
+ typeMetadataRegistry,
611
+ codecHooks,
612
+ storageTypes,
613
+ ...ifDefined("normalizeDefault", normalizeDefault),
614
+ ...ifDefined("normalizeNativeType", normalizeNativeType)
576
615
  });
577
- continue;
616
+ rootChildren.push(buildTableNode(tableName, tablePath, tableChildren));
578
617
  }
579
- const tableChildren = verifyTableChildren({
580
- contractTable,
581
- schemaTable,
582
- tableName,
583
- tablePath,
584
- issues,
585
- strict,
586
- typeMetadataRegistry,
587
- codecHooks,
588
- storageTypes,
589
- ...ifDefined("normalizeDefault", normalizeDefault),
590
- ...ifDefined("normalizeNativeType", normalizeNativeType)
591
- });
592
- rootChildren.push(buildTableNode(tableName, tablePath, tableChildren));
593
618
  }
594
619
  if (strict) {
595
- for (const tableName of Object.keys(schemaTables)) if (!contractTables[tableName]) {
620
+ for (const tableName of Object.keys(schemaTables)) if (!namespaceIds.some((namespaceId) => contract.storage.namespaces[namespaceId]?.tables[tableName] !== void 0)) {
596
621
  issues.push({
597
622
  kind: "extra_table",
598
623
  table: tableName,
@@ -602,7 +627,7 @@ function verifySchemaTables(options) {
602
627
  status: "fail",
603
628
  kind: "table",
604
629
  name: `table ${tableName}`,
605
- contractPath: `storage.tables.${tableName}`,
630
+ contractPath: `storage.namespaces.*.tables.${tableName}`,
606
631
  code: "extra_table",
607
632
  message: `Extra table "${tableName}" found`,
608
633
  expected: void 0,
@@ -617,12 +642,13 @@ function verifySchemaTables(options) {
617
642
  };
618
643
  }
619
644
  function verifyTableChildren(options) {
620
- const { contractTable, schemaTable, tableName, tablePath, issues, strict, typeMetadataRegistry, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
645
+ const { contractTable, schemaTable, tableName, namespaceId, tablePath, issues, strict, typeMetadataRegistry, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
621
646
  const tableChildren = [];
622
647
  const columnNodes = collectContractColumnNodes({
623
648
  contractTable,
624
649
  schemaTable,
625
650
  tableName,
651
+ namespaceId,
626
652
  tablePath,
627
653
  issues,
628
654
  strict,
@@ -637,11 +663,12 @@ function verifyTableChildren(options) {
637
663
  contractTable,
638
664
  schemaTable,
639
665
  tableName,
666
+ namespaceId,
640
667
  tablePath,
641
668
  issues,
642
669
  columnNodes
643
670
  });
644
- if (contractTable.primaryKey) if (verifyPrimaryKey(contractTable.primaryKey, schemaTable.primaryKey, tableName, issues) === "fail") tableChildren.push({
671
+ if (contractTable.primaryKey) if (verifyPrimaryKey(contractTable.primaryKey, schemaTable.primaryKey, tableName, namespaceId, issues) === "fail") tableChildren.push({
645
672
  status: "fail",
646
673
  kind: "primaryKey",
647
674
  name: `primary key: ${contractTable.primaryKey.columns.join(", ")}`,
@@ -667,6 +694,7 @@ function verifyTableChildren(options) {
667
694
  issues.push({
668
695
  kind: "extra_primary_key",
669
696
  table: tableName,
697
+ namespaceId,
670
698
  message: "Extra primary key found in database (not in contract)"
671
699
  });
672
700
  tableChildren.push({
@@ -683,18 +711,18 @@ function verifyTableChildren(options) {
683
711
  }
684
712
  const constraintFks = contractTable.foreignKeys.filter((fk) => fk.constraint === true);
685
713
  if (constraintFks.length > 0 || strict) {
686
- const fkStatuses = verifyForeignKeys(constraintFks, schemaTable.foreignKeys, tableName, tablePath, issues, strict);
714
+ const fkStatuses = verifyForeignKeys(constraintFks, schemaTable.foreignKeys, tableName, namespaceId, tablePath, issues, strict);
687
715
  tableChildren.push(...fkStatuses);
688
716
  }
689
- const uniqueStatuses = verifyUniqueConstraints(contractTable.uniques, schemaTable.uniques, schemaTable.indexes, tableName, tablePath, issues, strict);
717
+ const uniqueStatuses = verifyUniqueConstraints(contractTable.uniques, schemaTable.uniques, schemaTable.indexes, tableName, namespaceId, tablePath, issues, strict);
690
718
  tableChildren.push(...uniqueStatuses);
691
- const fkBackingIndexes = contractTable.foreignKeys.filter((fk) => fk.index === true && !contractTable.indexes.some((idx) => arraysEqual(idx.columns, fk.columns))).map((fk) => ({ columns: fk.columns }));
692
- const indexStatuses = verifyIndexes([...contractTable.indexes, ...fkBackingIndexes], schemaTable.indexes, schemaTable.uniques, tableName, tablePath, issues, strict);
719
+ const fkBackingIndexes = contractTable.foreignKeys.filter((fk) => fk.index === true && !contractTable.indexes.some((idx) => arraysEqual(idx.columns, fk.source.columns))).map((fk) => ({ columns: fk.source.columns }));
720
+ const indexStatuses = verifyIndexes([...contractTable.indexes, ...fkBackingIndexes], schemaTable.indexes, schemaTable.uniques, tableName, namespaceId, tablePath, issues, strict);
693
721
  tableChildren.push(...indexStatuses);
694
722
  return tableChildren;
695
723
  }
696
724
  function collectContractColumnNodes(options) {
697
- const { contractTable, schemaTable, tableName, tablePath, issues, strict, typeMetadataRegistry, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
725
+ const { contractTable, schemaTable, tableName, namespaceId, tablePath, issues, strict, typeMetadataRegistry, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
698
726
  const columnNodes = [];
699
727
  for (const [columnName, contractColumn] of Object.entries(contractTable.columns)) {
700
728
  const schemaColumn = schemaTable.columns[columnName];
@@ -703,6 +731,7 @@ function collectContractColumnNodes(options) {
703
731
  issues.push({
704
732
  kind: "missing_column",
705
733
  table: tableName,
734
+ namespaceId,
706
735
  column: columnName,
707
736
  message: `Column "${tableName}"."${columnName}" is missing from database`
708
737
  });
@@ -721,6 +750,7 @@ function collectContractColumnNodes(options) {
721
750
  }
722
751
  columnNodes.push(verifyColumn({
723
752
  tableName,
753
+ namespaceId,
724
754
  columnName,
725
755
  contractColumn,
726
756
  schemaColumn,
@@ -737,11 +767,12 @@ function collectContractColumnNodes(options) {
737
767
  return columnNodes;
738
768
  }
739
769
  function appendExtraColumnNodes(options) {
740
- const { contractTable, schemaTable, tableName, tablePath, issues, columnNodes } = options;
770
+ const { contractTable, schemaTable, tableName, namespaceId, tablePath, issues, columnNodes } = options;
741
771
  for (const [columnName, { nativeType }] of Object.entries(schemaTable.columns)) if (!contractTable.columns[columnName]) {
742
772
  issues.push({
743
773
  kind: "extra_column",
744
774
  table: tableName,
775
+ namespaceId,
745
776
  column: columnName,
746
777
  message: `Extra column "${tableName}"."${columnName}" found in database (not in contract)`
747
778
  });
@@ -759,7 +790,7 @@ function appendExtraColumnNodes(options) {
759
790
  }
760
791
  }
761
792
  function verifyColumn(options) {
762
- const { tableName, columnName, contractColumn, schemaColumn, columnPath, issues, strict, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
793
+ const { tableName, namespaceId, columnName, contractColumn, schemaColumn, columnPath, issues, strict, codecHooks, storageTypes, normalizeDefault, normalizeNativeType } = options;
763
794
  const columnChildren = [];
764
795
  let columnStatus = "pass";
765
796
  const resolvedContractColumn = resolveContractColumnTypeMetadata(contractColumn, storageTypes, {
@@ -775,6 +806,7 @@ function verifyColumn(options) {
775
806
  issues.push({
776
807
  kind: "type_mismatch",
777
808
  table: tableName,
809
+ namespaceId,
778
810
  column: columnName,
779
811
  expected: contractNativeType,
780
812
  actual: schemaNativeType,
@@ -822,6 +854,7 @@ function verifyColumn(options) {
822
854
  issues.push({
823
855
  kind: "nullability_mismatch",
824
856
  table: tableName,
857
+ namespaceId,
825
858
  column: columnName,
826
859
  expected: String(contractColumn.nullable),
827
860
  actual: String(schemaColumn.nullable),
@@ -846,6 +879,7 @@ function verifyColumn(options) {
846
879
  issues.push({
847
880
  kind: "default_missing",
848
881
  table: tableName,
882
+ namespaceId,
849
883
  column: columnName,
850
884
  expected: defaultDescription,
851
885
  message: `Column "${tableName}"."${columnName}" should have default ${defaultDescription} but database has no default`
@@ -868,6 +902,7 @@ function verifyColumn(options) {
868
902
  issues.push({
869
903
  kind: "default_mismatch",
870
904
  table: tableName,
905
+ namespaceId,
871
906
  column: columnName,
872
907
  expected: expectedDescription,
873
908
  actual: actualDescription,
@@ -890,6 +925,7 @@ function verifyColumn(options) {
890
925
  issues.push({
891
926
  kind: "extra_default",
892
927
  table: tableName,
928
+ namespaceId,
893
929
  column: columnName,
894
930
  actual: schemaColumn.default,
895
931
  message: `Column "${tableName}"."${columnName}" has default ${schemaColumn.default} in database but contract specifies no default`
@@ -1104,4 +1140,4 @@ function formatLiteralValue(value) {
1104
1140
  //#endregion
1105
1141
  export { extractCodecControlHooks as a, isUniqueConstraintSatisfied as i, arraysEqual as n, isIndexSatisfied as r, verifySqlSchema as t };
1106
1142
 
1107
- //# sourceMappingURL=verify-sql-schema-BXw7yx6L.mjs.map
1143
+ //# sourceMappingURL=verify-sql-schema-Bj4Wqe2c.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-sql-schema-Bj4Wqe2c.mjs","names":["d"],"sources":["../src/core/assembly.ts","../src/core/schema-verify/verify-helpers.ts","../src/core/schema-verify/verify-sql-schema.ts"],"sourcesContent":["import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport { assertUniqueCodecOwner } from '@prisma-next/framework-components/control';\nimport type { CodecControlHooks } from './migrations/types';\n\ntype CodecControlHooksMap = Record<string, CodecControlHooks>;\n\nfunction hasCodecControlHooks(descriptor: unknown): descriptor is {\n readonly id: string;\n readonly types: {\n readonly codecTypes: {\n readonly controlPlaneHooks: CodecControlHooksMap;\n };\n };\n} {\n if (typeof descriptor !== 'object' || descriptor === null) {\n return false;\n }\n const d = descriptor as { types?: { codecTypes?: { controlPlaneHooks?: unknown } } };\n const hooks = d.types?.codecTypes?.controlPlaneHooks;\n return hooks !== null && hooks !== undefined && typeof hooks === 'object';\n}\n\nexport function extractCodecControlHooks(\n descriptors: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>,\n): Map<string, CodecControlHooks> {\n const hooks = new Map<string, CodecControlHooks>();\n const owners = new Map<string, string>();\n\n for (const descriptor of descriptors) {\n if (typeof descriptor !== 'object' || descriptor === null) {\n continue;\n }\n if (!hasCodecControlHooks(descriptor)) {\n continue;\n }\n const controlPlaneHooks = descriptor.types.codecTypes.controlPlaneHooks;\n for (const [codecId, hook] of Object.entries(controlPlaneHooks)) {\n assertUniqueCodecOwner({\n codecId,\n owners,\n descriptorId: descriptor.id,\n entityLabel: 'control hooks',\n entityOwnershipLabel: 'owner',\n });\n hooks.set(codecId, hook);\n owners.set(codecId, descriptor.id);\n }\n }\n\n return hooks;\n}\n","/**\n * Pure verification helper functions for SQL schema verification.\n * These functions verify schema IR against contract requirements.\n */\n\nimport type {\n SchemaIssue,\n SchemaVerificationNode,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type {\n ForeignKey,\n Index,\n PrimaryKey,\n UniqueConstraint,\n} from '@prisma-next/sql-contract/types';\nimport type { SqlForeignKeyIR, SqlIndexIR, SqlUniqueIR } from '@prisma-next/sql-schema-ir/types';\n\nfunction indexOptionsLooselyEqual(\n a: Record<string, unknown> | undefined,\n b: Record<string, unknown> | undefined,\n): boolean {\n const aKeys = a ? Object.keys(a).sort() : [];\n const bKeys = b ? Object.keys(b).sort() : [];\n if (aKeys.length !== bKeys.length) return false;\n for (let i = 0; i < aKeys.length; i += 1) {\n if (aKeys[i] !== bKeys[i]) return false;\n }\n if (aKeys.length === 0) return true;\n for (const key of aKeys) {\n // Postgres introspection returns reloptions values as raw strings (e.g.\n // `'70'`, `'false'`), while contract option leaves are typed (number,\n // boolean, string). Compare via String() so a contract `fillfactor: 70`\n // matches an introspected `fillfactor: '70'` without a spurious mismatch.\n if (\n String((a as Record<string, unknown>)[key]) !== String((b as Record<string, unknown>)[key])\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction indexExtrasMatch(\n contractIndex: Index,\n schemaIndex: { readonly type?: string; readonly options?: Record<string, unknown> },\n): boolean {\n if ((contractIndex.type ?? null) !== (schemaIndex.type ?? null)) return false;\n return indexOptionsLooselyEqual(contractIndex.options, schemaIndex.options);\n}\n\n/**\n * Compares two arrays of strings for equality (order-sensitive).\n */\nexport function arraysEqual(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// Semantic Satisfaction Predicates\n// ============================================================================\n// These predicates implement the \"stronger satisfies weaker\" logic for storage\n// objects. They are used by both verification and migration planning to ensure\n// consistent behavior across the control plane.\n\n/**\n * Checks if a unique constraint requirement is satisfied by the given columns.\n *\n * Semantic satisfaction: a unique constraint requirement can be satisfied by:\n * - A unique constraint with the same columns, OR\n * - A unique index with the same columns\n *\n * @param uniques - The unique constraints in the schema table\n * @param indexes - The indexes in the schema table\n * @param columns - The columns required by the unique constraint\n * @returns true if the requirement is satisfied\n */\nexport function isUniqueConstraintSatisfied(\n uniques: readonly SqlUniqueIR[],\n indexes: readonly SqlIndexIR[],\n columns: readonly string[],\n): boolean {\n // Check for matching unique constraint\n const hasConstraint = uniques.some((unique) => arraysEqual(unique.columns, columns));\n if (hasConstraint) {\n return true;\n }\n // Check for matching unique index (semantic satisfaction)\n return indexes.some((index) => index.unique && arraysEqual(index.columns, columns));\n}\n\n/**\n * Checks if an index requirement is satisfied by the given columns.\n *\n * Semantic satisfaction: a non-unique index requirement can be satisfied by:\n * - Any index (unique or non-unique) with the same columns, OR\n * - A unique constraint with the same columns (stronger satisfies weaker)\n *\n * @param indexes - The indexes in the schema table\n * @param uniques - The unique constraints in the schema table\n * @param columns - The columns required by the index\n * @returns true if the requirement is satisfied\n */\nexport function isIndexSatisfied(\n indexes: readonly SqlIndexIR[],\n uniques: readonly SqlUniqueIR[],\n columns: readonly string[],\n): boolean {\n // Check for any matching index (unique or non-unique)\n const hasMatchingIndex = indexes.some((index) => arraysEqual(index.columns, columns));\n if (hasMatchingIndex) {\n return true;\n }\n // Check for matching unique constraint (semantic satisfaction)\n return uniques.some((unique) => arraysEqual(unique.columns, columns));\n}\n\n/**\n * Verifies primary key matches between contract and schema.\n * Returns 'pass' or 'fail'.\n *\n * Uses semantic satisfaction: identity is based on (table + kind + columns).\n * Name differences are ignored by default (names are for DDL/diagnostics, not identity).\n */\nexport function verifyPrimaryKey(\n contractPK: PrimaryKey,\n schemaPK: PrimaryKey | undefined,\n tableName: string,\n namespaceId: string,\n issues: SchemaIssue[],\n): 'pass' | 'fail' {\n if (!schemaPK) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\n namespaceId,\n expected: contractPK.columns.join(', '),\n message: `Table \"${tableName}\" is missing primary key`,\n });\n return 'fail';\n }\n\n if (!arraysEqual(contractPK.columns, schemaPK.columns)) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\n namespaceId,\n expected: contractPK.columns.join(', '),\n actual: schemaPK.columns.join(', '),\n message: `Table \"${tableName}\" has primary key mismatch: expected columns [${contractPK.columns.join(', ')}], got [${schemaPK.columns.join(', ')}]`,\n });\n return 'fail';\n }\n\n // Name differences are ignored for semantic satisfaction.\n // Names are persisted for deterministic DDL and diagnostics but are not identity.\n\n return 'pass';\n}\n\n/**\n * Verifies foreign keys match between contract and schema.\n * Returns verification nodes for the tree.\n *\n * Uses semantic satisfaction: identity is based on (table + columns + referenced table + referenced columns).\n * Name differences are ignored by default (names are for DDL/diagnostics, not identity).\n */\nexport function verifyForeignKeys(\n contractFKs: readonly ForeignKey[],\n schemaFKs: readonly SqlForeignKeyIR[],\n tableName: string,\n namespaceId: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract FK exists in schema\n for (const contractFK of contractFKs) {\n const fkPath = `${tablePath}.foreignKeys[${contractFK.source.columns.join(',')}]`;\n const matchingFK = schemaFKs.find((fk) => {\n // When the schema FK carries referencedSchema (populated by the Postgres\n // adapter for cross-schema FKs), compare the full (namespace, table) pair\n // against the contract FK's target coordinate. When referencedSchema is\n // absent (same-schema FKs, older introspection, or hand-crafted test\n // fixtures), fall back to table-name-only comparison so same-namespace\n // contracts continue to verify correctly.\n const tablesMatch =\n fk.referencedSchema !== undefined && contractFK.target.namespaceId !== UNBOUND_NAMESPACE_ID\n ? fk.referencedSchema === contractFK.target.namespaceId &&\n fk.referencedTable === contractFK.target.tableName\n : fk.referencedTable === contractFK.target.tableName;\n return (\n arraysEqual(fk.columns, contractFK.source.columns) &&\n tablesMatch &&\n arraysEqual(fk.referencedColumns, contractFK.target.columns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n namespaceId,\n expected: `${contractFK.source.columns.join(', ')} -> ${contractFK.target.tableName}(${contractFK.target.columns.join(', ')})`,\n message: `Table \"${tableName}\" is missing foreign key: ${contractFK.source.columns.join(', ')} -> ${contractFK.target.tableName}(${contractFK.target.columns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.source.columns.join(', ')})`,\n contractPath: fkPath,\n code: 'foreign_key_mismatch',\n message: 'Foreign key missing',\n expected: contractFK,\n actual: undefined,\n children: [],\n });\n } else {\n const actionMismatches = getReferentialActionMismatches(contractFK, matchingFK);\n if (actionMismatches.length > 0) {\n const combinedMessage = actionMismatches.map((m) => m.message).join('; ');\n const combinedExpected = actionMismatches.map((m) => m.expected).join(', ');\n const combinedActual = actionMismatches.map((m) => m.actual).join(', ');\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n namespaceId,\n // Set indexOrConstraint so the planner classifies this as a non-additive\n // conflict (existing FK with wrong actions cannot be fixed additively).\n indexOrConstraint: matchingFK.name ?? `fk(${contractFK.source.columns.join(',')})`,\n expected: combinedExpected,\n actual: combinedActual,\n message: `Table \"${tableName}\" foreign key ${contractFK.source.columns.join(', ')} -> ${contractFK.target.tableName}: ${combinedMessage}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.source.columns.join(', ')})`,\n contractPath: fkPath,\n code: 'foreign_key_mismatch',\n message: combinedMessage,\n expected: contractFK,\n actual: matchingFK,\n children: [],\n });\n } else {\n nodes.push({\n status: 'pass',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.source.columns.join(', ')})`,\n contractPath: fkPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n // Check for extra FKs in strict mode\n if (strict) {\n for (const schemaFK of schemaFKs) {\n const matchingFK = contractFKs.find((fk) => {\n const tablesMatch =\n schemaFK.referencedSchema !== undefined && fk.target.namespaceId !== UNBOUND_NAMESPACE_ID\n ? schemaFK.referencedSchema === fk.target.namespaceId &&\n schemaFK.referencedTable === fk.target.tableName\n : schemaFK.referencedTable === fk.target.tableName;\n return (\n arraysEqual(fk.source.columns, schemaFK.columns) &&\n tablesMatch &&\n arraysEqual(fk.target.columns, schemaFK.referencedColumns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'extra_foreign_key',\n table: tableName,\n namespaceId,\n indexOrConstraint: schemaFK.name ?? `fk(${schemaFK.columns.join(',')})`,\n message: `Extra foreign key found in database (not in contract): ${schemaFK.columns.join(', ')} -> ${schemaFK.referencedTable}(${schemaFK.referencedColumns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${schemaFK.columns.join(', ')})`,\n contractPath: `${tablePath}.foreignKeys[${schemaFK.columns.join(',')}]`,\n code: 'extra_foreign_key',\n message: 'Extra foreign key found',\n expected: undefined,\n actual: schemaFK,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Verifies unique constraints match between contract and schema.\n * Returns verification nodes for the tree.\n *\n * Uses semantic satisfaction: identity is based on (table + kind + columns).\n * A unique constraint requirement can be satisfied by either:\n * - A unique constraint with the same columns, or\n * - A unique index with the same columns\n *\n * Name differences are ignored by default (names are for DDL/diagnostics, not identity).\n */\nexport function verifyUniqueConstraints(\n contractUniques: readonly UniqueConstraint[],\n schemaUniques: readonly SqlUniqueIR[],\n schemaIndexes: readonly SqlIndexIR[],\n tableName: string,\n namespaceId: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract unique exists in schema\n for (const contractUnique of contractUniques) {\n const uniquePath = `${tablePath}.uniques[${contractUnique.columns.join(',')}]`;\n\n // First check for a matching unique constraint\n const matchingUnique = schemaUniques.find((u) =>\n arraysEqual(u.columns, contractUnique.columns),\n );\n\n // If no matching constraint, check for a unique index with the same columns\n const matchingUniqueIndex =\n !matchingUnique &&\n schemaIndexes.find((idx) => idx.unique && arraysEqual(idx.columns, contractUnique.columns));\n\n if (!matchingUnique && !matchingUniqueIndex) {\n issues.push({\n kind: 'unique_constraint_mismatch',\n table: tableName,\n namespaceId,\n expected: contractUnique.columns.join(', '),\n message: `Table \"${tableName}\" is missing unique constraint: ${contractUnique.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'unique',\n name: `unique(${contractUnique.columns.join(', ')})`,\n contractPath: uniquePath,\n code: 'unique_constraint_mismatch',\n message: 'Unique constraint missing',\n expected: contractUnique,\n actual: undefined,\n children: [],\n });\n } else {\n // Name differences are ignored for semantic satisfaction.\n // Names are persisted for deterministic DDL and diagnostics but are not identity.\n nodes.push({\n status: 'pass',\n kind: 'unique',\n name: `unique(${contractUnique.columns.join(', ')})`,\n contractPath: uniquePath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n\n // Check for extra uniques in strict mode\n if (strict) {\n for (const schemaUnique of schemaUniques) {\n const matchingUnique = contractUniques.find((u) =>\n arraysEqual(u.columns, schemaUnique.columns),\n );\n\n if (!matchingUnique) {\n issues.push({\n kind: 'extra_unique_constraint',\n table: tableName,\n namespaceId,\n indexOrConstraint: schemaUnique.name ?? `unique(${schemaUnique.columns.join(',')})`,\n message: `Extra unique constraint found in database (not in contract): ${schemaUnique.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'unique',\n name: `unique(${schemaUnique.columns.join(', ')})`,\n contractPath: `${tablePath}.uniques[${schemaUnique.columns.join(',')}]`,\n code: 'extra_unique_constraint',\n message: 'Extra unique constraint found',\n expected: undefined,\n actual: schemaUnique,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Verifies indexes match between contract and schema.\n * Returns verification nodes for the tree.\n *\n * Uses semantic satisfaction: identity is based on (table + kind + columns).\n * A non-unique index requirement can be satisfied by either:\n * - A non-unique index with the same columns, or\n * - A unique index with the same columns (stronger satisfies weaker)\n *\n * Name differences are ignored by default (names are for DDL/diagnostics, not identity).\n */\nexport function verifyIndexes(\n contractIndexes: readonly Index[],\n schemaIndexes: readonly SqlIndexIR[],\n schemaUniques: readonly SqlUniqueIR[],\n tableName: string,\n namespaceId: string,\n tablePath: string,\n issues: SchemaIssue[],\n strict: boolean,\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n // Check each contract index exists in schema\n for (const contractIndex of contractIndexes) {\n const indexPath = `${tablePath}.indexes[${contractIndex.columns.join(',')}]`;\n\n // Check for any matching index (unique or non-unique)\n // A unique index can satisfy a non-unique index requirement (stronger satisfies weaker)\n const matchingIndex = schemaIndexes.find(\n (idx) =>\n arraysEqual(idx.columns, contractIndex.columns) && indexExtrasMatch(contractIndex, idx),\n );\n\n // Also check if a unique constraint satisfies the index requirement.\n // Unique constraints carry no type/options of their own, so they can only\n // satisfy a contract index that doesn't request a specific type/options.\n const matchingUniqueConstraint =\n !matchingIndex &&\n contractIndex.type === undefined &&\n contractIndex.options === undefined &&\n schemaUniques.find((u) => arraysEqual(u.columns, contractIndex.columns));\n\n if (!matchingIndex && !matchingUniqueConstraint) {\n issues.push({\n kind: 'index_mismatch',\n table: tableName,\n namespaceId,\n expected: contractIndex.columns.join(', '),\n message: `Table \"${tableName}\" is missing index: ${contractIndex.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: `index(${contractIndex.columns.join(', ')})`,\n contractPath: indexPath,\n code: 'index_mismatch',\n message: 'Index missing',\n expected: contractIndex,\n actual: undefined,\n children: [],\n });\n } else {\n // Name differences are ignored for semantic satisfaction.\n // Names are persisted for deterministic DDL and diagnostics but are not identity.\n nodes.push({\n status: 'pass',\n kind: 'index',\n name: `index(${contractIndex.columns.join(', ')})`,\n contractPath: indexPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n\n // Check for extra indexes in strict mode\n if (strict) {\n for (const schemaIndex of schemaIndexes) {\n // Skip unique indexes (they're handled as unique constraints)\n if (schemaIndex.unique) {\n continue;\n }\n\n const matchingIndex = contractIndexes.find(\n (idx) =>\n arraysEqual(idx.columns, schemaIndex.columns) && indexExtrasMatch(idx, schemaIndex),\n );\n\n if (!matchingIndex) {\n issues.push({\n kind: 'extra_index',\n table: tableName,\n namespaceId,\n indexOrConstraint: schemaIndex.name ?? `idx(${schemaIndex.columns.join(',')})`,\n message: `Extra index found in database (not in contract): ${schemaIndex.columns.join(', ')}`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: `index(${schemaIndex.columns.join(', ')})`,\n contractPath: `${tablePath}.indexes[${schemaIndex.columns.join(',')}]`,\n code: 'extra_index',\n message: 'Extra index found',\n expected: undefined,\n actual: schemaIndex,\n children: [],\n });\n }\n }\n }\n\n return nodes;\n}\n\n/**\n * Computes counts of pass/warn/fail nodes by traversing the tree.\n */\nexport function computeCounts(node: SchemaVerificationNode): {\n pass: number;\n warn: number;\n fail: number;\n totalNodes: number;\n} {\n let pass = 0;\n let warn = 0;\n let fail = 0;\n\n function traverse(n: SchemaVerificationNode): void {\n if (n.status === 'pass') {\n pass++;\n } else if (n.status === 'warn') {\n warn++;\n } else if (n.status === 'fail') {\n fail++;\n }\n\n if (n.children) {\n for (const child of n.children) {\n traverse(child);\n }\n }\n }\n\n traverse(node);\n\n return {\n pass,\n warn,\n fail,\n totalNodes: pass + warn + fail,\n };\n}\n\n/**\n * Compares referential actions between a contract FK and a schema FK.\n * Only compares when the contract FK explicitly specifies onDelete or onUpdate.\n * Returns all mismatches (both onDelete and onUpdate) so both are reported at once.\n *\n * Note: 'noAction' in the contract is semantically equivalent to undefined in the\n * schema IR, because the introspection adapter omits 'NO ACTION' (the database default)\n * to keep the IR sparse. We normalize both sides before comparing.\n */\nfunction getReferentialActionMismatches(\n contractFK: ForeignKey,\n schemaFK: SqlForeignKeyIR,\n): ReadonlyArray<{ expected: string; actual: string; message: string }> {\n const mismatches: Array<{ expected: string; actual: string; message: string }> = [];\n\n const contractOnDelete = normalizeReferentialAction(contractFK.onDelete);\n const schemaOnDelete = normalizeReferentialAction(schemaFK.onDelete);\n if (contractOnDelete !== undefined && contractOnDelete !== schemaOnDelete) {\n mismatches.push({\n expected: `onDelete: ${contractFK.onDelete}`,\n actual: `onDelete: ${schemaFK.onDelete ?? 'noAction (default)'}`,\n message: `onDelete mismatch: expected ${contractFK.onDelete}, got ${schemaFK.onDelete ?? 'noAction (default)'}`,\n });\n }\n\n const contractOnUpdate = normalizeReferentialAction(contractFK.onUpdate);\n const schemaOnUpdate = normalizeReferentialAction(schemaFK.onUpdate);\n if (contractOnUpdate !== undefined && contractOnUpdate !== schemaOnUpdate) {\n mismatches.push({\n expected: `onUpdate: ${contractFK.onUpdate}`,\n actual: `onUpdate: ${schemaFK.onUpdate ?? 'noAction (default)'}`,\n message: `onUpdate mismatch: expected ${contractFK.onUpdate}, got ${schemaFK.onUpdate ?? 'noAction (default)'}`,\n });\n }\n\n return mismatches;\n}\n\n/**\n * Normalizes a referential action value for comparison.\n * 'noAction' is the database default and equivalent to undefined (omitted) in the sparse IR.\n */\nfunction normalizeReferentialAction(action: string | undefined): string | undefined {\n return action === 'noAction' ? undefined : action;\n}\n","/**\n * Pure SQL schema verification function.\n *\n * This module provides a pure function that verifies a SqlSchemaIR against\n * a Contract without requiring a database connection. It can be reused\n * by migration planners and other tools that need to compare schema states.\n */\n\nimport type { ColumnDefault, Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n OperationContext,\n SchemaIssue,\n SchemaVerificationNode,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n isPostgresEnumStorageEntry,\n isStorageTypeInstance,\n type PostgresEnumStorageEntry,\n type SqlStorage,\n type StorageColumn,\n StorageTable,\n type StorageTypeInstance,\n} from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { canonicalStringify } from '@prisma-next/utils/canonical-stringify';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { extractCodecControlHooks } from '../assembly';\nimport type { CodecControlHooks } from '../migrations/types';\nimport {\n arraysEqual,\n computeCounts,\n verifyForeignKeys,\n verifyIndexes,\n verifyPrimaryKey,\n verifyUniqueConstraints,\n} from './verify-helpers';\n\n/**\n * Function type for normalizing raw database default expressions into ColumnDefault.\n * Target-specific implementations handle database dialect differences.\n */\nexport type DefaultNormalizer = (\n rawDefault: string,\n nativeType: string,\n) => ColumnDefault | undefined;\n\n/**\n * Function type for normalizing schema native types to canonical form for comparison.\n * Target-specific implementations handle dialect-specific type name variations\n * (e.g., Postgres 'varchar' → 'character varying', 'timestamptz' normalization).\n */\nexport type NativeTypeNormalizer = (nativeType: string) => string;\n\n/**\n * Options for the pure schema verification function.\n */\nexport interface VerifySqlSchemaOptions {\n /** The validated SQL contract to verify against */\n readonly contract: Contract<SqlStorage>;\n /** The schema IR from introspection (or another source) */\n readonly schema: SqlSchemaIR;\n /** Whether to run in strict mode (detects extra tables/columns) */\n readonly strict: boolean;\n /** Optional operation context for metadata */\n readonly context?: OperationContext;\n /** Type metadata registry for codec consistency warnings */\n readonly typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n /**\n * Active framework components participating in this composition.\n * All components must have matching familyId ('sql') and targetId.\n */\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Optional target-specific normalizer for raw database default expressions.\n * When provided, schema defaults (raw strings) are normalized before comparison\n * with contract defaults (ColumnDefault objects).\n */\n readonly normalizeDefault?: DefaultNormalizer;\n /**\n * Optional target-specific normalizer for schema native type names.\n * When provided, schema native types are normalized before comparison\n * with contract native types (e.g., Postgres 'varchar' → 'character varying').\n */\n readonly normalizeNativeType?: NativeTypeNormalizer;\n /**\n * Bridging adapter that resolves the existing values for a `PostgresEnumStorageEntry`\n * (looked up by its native type) from the introspected schema IR. Targets\n * supply this so the family-level verifier can walk `PostgresEnumStorageEntry` instances\n * natively without reaching into target-specific `schema.annotations`\n * shapes itself.\n *\n * Returning `null` indicates the type is missing from the database; the\n * verifier emits a `type_missing` issue. A non-null array triggers a\n * value-set comparison against the contract's `PostgresEnumStorageEntry.values`.\n */\n readonly resolveExistingEnumValues?: (\n schema: SqlSchemaIR,\n enumType: PostgresEnumStorageEntry,\n ) => readonly string[] | null;\n}\n\n/**\n * Verifies that a SqlSchemaIR matches a Contract.\n *\n * This is a pure function that does NOT perform any database I/O.\n * It takes an already-introspected schema IR and compares it against\n * the contract requirements.\n *\n * @param options - Verification options\n * @returns VerifyDatabaseSchemaResult with verification tree and issues\n */\nexport function verifySqlSchema(options: VerifySqlSchemaOptions): VerifyDatabaseSchemaResult {\n const {\n contract,\n schema,\n strict,\n context,\n typeMetadataRegistry,\n normalizeDefault,\n normalizeNativeType,\n resolveExistingEnumValues,\n } = options;\n const startTime = Date.now();\n\n // Extract codec control hooks once at entry point for reuse\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n\n const { contractStorageHash, contractProfileHash, contractTarget } =\n extractContractMetadata(contract);\n const allStorageTypesMap: Record<string, PostgresEnumStorageEntry | StorageTypeInstance> = {\n ...((contract.storage.types ?? {}) as Record<\n string,\n PostgresEnumStorageEntry | StorageTypeInstance\n >),\n };\n for (const ns of Object.values(contract.storage.namespaces)) {\n const nsTypes = (ns as { types?: Record<string, PostgresEnumStorageEntry> }).types;\n if (nsTypes) {\n for (const [k, v] of Object.entries(nsTypes)) {\n allStorageTypesMap[k] = v;\n }\n }\n }\n const storageTypes = allStorageTypesMap as Readonly<\n Record<string, PostgresEnumStorageEntry | StorageTypeInstance>\n >;\n const { issues, rootChildren } = verifySchemaTables({\n contract,\n schema,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n ...ifDefined('normalizeDefault', normalizeDefault),\n ...ifDefined('normalizeNativeType', normalizeNativeType),\n });\n\n validateFrameworkComponentsForExtensions(contract, options.frameworkComponents);\n\n // Verify storage type instances. PostgresEnumStorageEntry entries are walked\n // natively (using the bridging adapter `resolveExistingEnumValues`);\n // remaining codec-typed entries continue to dispatch through the\n // generic codec-hook `verifyType` path.\n const storageTypeEntries = Object.entries(storageTypes);\n if (storageTypeEntries.length > 0) {\n const typeNodes: SchemaVerificationNode[] = [];\n for (const [typeName, typeInstance] of storageTypeEntries) {\n let typeIssues: readonly SchemaIssue[];\n if (isPostgresEnumStorageEntry(typeInstance)) {\n typeIssues = verifyEnumType({\n typeName,\n typeInstance,\n schema,\n resolveExistingEnumValues,\n });\n } else if (isStorageTypeInstance(typeInstance)) {\n const hook = codecHooks.get(typeInstance.codecId);\n typeIssues = hook?.verifyType ? hook.verifyType({ typeName, typeInstance, schema }) : [];\n } else {\n typeIssues = [];\n }\n if (typeIssues.length > 0) {\n issues.push(...typeIssues);\n }\n const typeStatus = typeIssues.length > 0 ? 'fail' : 'pass';\n const typeCode = typeIssues.length > 0 ? (typeIssues[0]?.kind ?? '') : '';\n typeNodes.push({\n status: typeStatus,\n kind: 'storageType',\n name: `type ${typeName}`,\n contractPath: `storage.types.${typeName}`,\n code: typeCode,\n message:\n typeIssues.length > 0\n ? `${typeIssues.length} issue${typeIssues.length === 1 ? '' : 's'}`\n : '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n const typesStatus = typeNodes.some((n) => n.status === 'fail') ? 'fail' : 'pass';\n rootChildren.push({\n status: typesStatus,\n kind: 'storageTypes',\n name: 'types',\n contractPath: 'storage.types',\n code: typesStatus === 'fail' ? 'type_mismatch' : '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: typeNodes,\n });\n }\n\n const root = buildRootNode(rootChildren);\n\n // Compute counts\n const counts = computeCounts(root);\n\n // Set ok flag\n const ok = counts.fail === 0;\n\n // Set code\n const code = ok ? undefined : 'PN-SCHEMA-0001';\n\n // Set summary\n const summary = ok\n ? 'Database schema satisfies contract'\n : `Database schema does not satisfy contract (${counts.fail} failure${counts.fail === 1 ? '' : 's'})`;\n\n const totalTime = Date.now() - startTime;\n\n return {\n ok,\n ...ifDefined('code', code),\n summary,\n contract: {\n storageHash: contractStorageHash,\n ...ifDefined('profileHash', contractProfileHash),\n },\n target: {\n expected: contractTarget,\n actual: contractTarget,\n },\n schema: {\n issues,\n root,\n counts,\n },\n meta: {\n strict,\n ...ifDefined('contractPath', context?.contractPath),\n ...ifDefined('configPath', context?.configPath),\n },\n timings: {\n total: totalTime,\n },\n };\n}\n\ntype VerificationStatus = 'pass' | 'warn' | 'fail';\n\n/**\n * Native verification walk for `PostgresEnumStorageEntry` instances (no codec hook).\n *\n * Bridges the native `PostgresEnumStorageEntry.values` against the introspected schema\n * IR via the target-supplied `resolveExistingEnumValues` adapter. Without an\n * adapter, the verifier conservatively reports the enum as missing — there\n * is no other way for the family layer to learn about live enum types.\n */\nfunction verifyEnumType(options: {\n readonly typeName: string;\n readonly typeInstance: PostgresEnumStorageEntry;\n readonly schema: SqlSchemaIR;\n readonly resolveExistingEnumValues?:\n | ((schema: SqlSchemaIR, enumType: PostgresEnumStorageEntry) => readonly string[] | null)\n | undefined;\n}): readonly SchemaIssue[] {\n const { typeName, typeInstance, schema, resolveExistingEnumValues } = options;\n const desired = typeInstance.values;\n const existing = resolveExistingEnumValues?.(schema, typeInstance) ?? null;\n if (!existing) {\n return [\n {\n kind: 'type_missing',\n typeName,\n message: `Type \"${typeName}\" is missing from database`,\n },\n ];\n }\n if (arraysEqual(existing, desired)) {\n return [];\n }\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n const addedValues = desired.filter((v) => !existingSet.has(v));\n const removedValues = existing.filter((v) => !desiredSet.has(v));\n const message =\n removedValues.length === 0\n ? `Enum type \"${typeName}\" needs new values: ${addedValues.join(', ')}`\n : `Enum type \"${typeName}\" values changed (requires rebuild): +[${addedValues.join(', ')}] -[${removedValues.join(', ')}]`;\n return [\n {\n kind: 'enum_values_changed' as const,\n typeName,\n addedValues,\n removedValues,\n message,\n },\n ];\n}\n\nfunction extractContractMetadata(contract: Contract<SqlStorage>): {\n contractStorageHash: SqlStorage['storageHash'];\n contractProfileHash?: Contract<SqlStorage>['profileHash'] | undefined;\n contractTarget: Contract<SqlStorage>['target'];\n} {\n return {\n contractStorageHash: contract.storage.storageHash,\n contractProfileHash:\n 'profileHash' in contract && typeof contract.profileHash === 'string'\n ? contract.profileHash\n : undefined,\n contractTarget: contract.target,\n };\n}\n\nfunction verifySchemaTables(options: {\n contract: Contract<SqlStorage>;\n schema: SqlSchemaIR;\n strict: boolean;\n typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n codecHooks: Map<string, CodecControlHooks>;\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>;\n normalizeDefault?: DefaultNormalizer;\n normalizeNativeType?: NativeTypeNormalizer;\n}): { issues: SchemaIssue[]; rootChildren: SchemaVerificationNode[] } {\n const {\n contract,\n schema,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n normalizeDefault,\n normalizeNativeType,\n } = options;\n const issues: SchemaIssue[] = [];\n const rootChildren: SchemaVerificationNode[] = [];\n const schemaTables = schema.tables;\n const namespaceIds = Object.keys(contract.storage.namespaces).sort((a, b) =>\n a < b ? -1 : a > b ? 1 : 0,\n );\n\n for (const namespaceId of namespaceIds) {\n const ns = contract.storage.namespaces[namespaceId];\n if (!ns) continue;\n for (const [tableName, contractTableRaw] of Object.entries(ns.tables)) {\n if (!(contractTableRaw instanceof StorageTable)) {\n throw new Error(\n `verifySqlSchema: expected StorageTable at storage.namespaces.${namespaceId}.tables.${tableName}`,\n );\n }\n const contractTable = contractTableRaw;\n const schemaTable = schemaTables[tableName];\n const tablePath = `storage.namespaces.${namespaceId}.tables.${tableName}`;\n\n if (!schemaTable) {\n issues.push({\n kind: 'missing_table',\n table: tableName,\n namespaceId,\n message: `Table \"${tableName}\" is missing from database`,\n });\n rootChildren.push({\n status: 'fail',\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: tablePath,\n code: 'missing_table',\n message: `Table \"${tableName}\" is missing`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n continue;\n }\n\n const tableChildren = verifyTableChildren({\n contractTable,\n schemaTable,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n ...ifDefined('normalizeDefault', normalizeDefault),\n ...ifDefined('normalizeNativeType', normalizeNativeType),\n });\n rootChildren.push(buildTableNode(tableName, tablePath, tableChildren));\n }\n }\n\n if (strict) {\n for (const tableName of Object.keys(schemaTables)) {\n const claimed = namespaceIds.some(\n (namespaceId) => contract.storage.namespaces[namespaceId]?.tables[tableName] !== undefined,\n );\n if (!claimed) {\n // `namespaceId` is intentionally absent: an extra table exists in the\n // live database but is not claimed by any contract namespace, so there\n // is no contract coordinate to stamp here. Planners that consume this\n // issue must handle the unstamped case (drop / quarantine by name).\n issues.push({\n kind: 'extra_table',\n table: tableName,\n message: `Extra table \"${tableName}\" found in database (not in contract)`,\n });\n rootChildren.push({\n status: 'fail',\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: `storage.namespaces.*.tables.${tableName}`,\n code: 'extra_table',\n message: `Extra table \"${tableName}\" found`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n }\n }\n\n return { issues, rootChildren };\n}\n\nfunction verifyTableChildren(options: {\n contractTable: StorageTable;\n schemaTable: SqlSchemaIR['tables'][string];\n tableName: string;\n namespaceId: string;\n tablePath: string;\n issues: SchemaIssue[];\n strict: boolean;\n typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n codecHooks: Map<string, CodecControlHooks>;\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>;\n normalizeDefault?: DefaultNormalizer;\n normalizeNativeType?: NativeTypeNormalizer;\n}): SchemaVerificationNode[] {\n const {\n contractTable,\n schemaTable,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n normalizeDefault,\n normalizeNativeType,\n } = options;\n const tableChildren: SchemaVerificationNode[] = [];\n const columnNodes = collectContractColumnNodes({\n contractTable,\n schemaTable,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n ...ifDefined('normalizeDefault', normalizeDefault),\n ...ifDefined('normalizeNativeType', normalizeNativeType),\n });\n if (columnNodes.length > 0) {\n tableChildren.push(buildColumnsNode(tablePath, columnNodes));\n }\n if (strict) {\n appendExtraColumnNodes({\n contractTable,\n schemaTable,\n tableName,\n namespaceId,\n tablePath,\n issues,\n columnNodes,\n });\n }\n\n if (contractTable.primaryKey) {\n const pkStatus = verifyPrimaryKey(\n contractTable.primaryKey,\n schemaTable.primaryKey,\n tableName,\n namespaceId,\n issues,\n );\n if (pkStatus === 'fail') {\n tableChildren.push({\n status: 'fail',\n kind: 'primaryKey',\n name: `primary key: ${contractTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: 'primary_key_mismatch',\n message: 'Primary key mismatch',\n expected: contractTable.primaryKey,\n actual: schemaTable.primaryKey,\n children: [],\n });\n } else {\n tableChildren.push({\n status: 'pass',\n kind: 'primaryKey',\n name: `primary key: ${contractTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\n });\n }\n } else if (schemaTable.primaryKey && strict) {\n issues.push({\n kind: 'extra_primary_key',\n table: tableName,\n namespaceId,\n message: 'Extra primary key found in database (not in contract)',\n });\n tableChildren.push({\n status: 'fail',\n kind: 'primaryKey',\n name: `primary key: ${schemaTable.primaryKey.columns.join(', ')}`,\n contractPath: `${tablePath}.primaryKey`,\n code: 'extra_primary_key',\n message: 'Extra primary key found',\n expected: undefined,\n actual: schemaTable.primaryKey,\n children: [],\n });\n }\n\n // Verify FK constraints only for FKs with constraint: true.\n // Always call when strict mode is on so extra-FK detection runs even if\n // the contract has no FKs for this table.\n const constraintFks = contractTable.foreignKeys.filter((fk) => fk.constraint === true);\n if (constraintFks.length > 0 || strict) {\n const fkStatuses = verifyForeignKeys(\n constraintFks,\n schemaTable.foreignKeys,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...fkStatuses);\n }\n\n const uniqueStatuses = verifyUniqueConstraints(\n contractTable.uniques,\n schemaTable.uniques,\n schemaTable.indexes,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...uniqueStatuses);\n\n // Combine user-declared indexes with FK-backing indexes (from FKs with index: true)\n // so the verifier treats FK-backing indexes as expected, not \"extra\".\n // Deduplicate: skip FK-backing indexes already covered by a user-declared index.\n const fkBackingIndexes = contractTable.foreignKeys\n .filter(\n (fk) =>\n fk.index === true &&\n !contractTable.indexes.some((idx) => arraysEqual(idx.columns, fk.source.columns)),\n )\n .map((fk) => ({ columns: fk.source.columns }));\n const allExpectedIndexes = [...contractTable.indexes, ...fkBackingIndexes];\n\n const indexStatuses = verifyIndexes(\n allExpectedIndexes,\n schemaTable.indexes,\n schemaTable.uniques,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...indexStatuses);\n\n return tableChildren;\n}\n\nfunction collectContractColumnNodes(options: {\n contractTable: StorageTable;\n schemaTable: SqlSchemaIR['tables'][string];\n tableName: string;\n namespaceId: string;\n tablePath: string;\n issues: SchemaIssue[];\n strict: boolean;\n typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n codecHooks: Map<string, CodecControlHooks>;\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>;\n normalizeDefault?: DefaultNormalizer;\n normalizeNativeType?: NativeTypeNormalizer;\n}): SchemaVerificationNode[] {\n const {\n contractTable,\n schemaTable,\n tableName,\n namespaceId,\n tablePath,\n issues,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n normalizeDefault,\n normalizeNativeType,\n } = options;\n const columnNodes: SchemaVerificationNode[] = [];\n\n for (const [columnName, contractColumn] of Object.entries(contractTable.columns)) {\n const schemaColumn = schemaTable.columns[columnName];\n const columnPath = `${tablePath}.columns.${columnName}`;\n\n if (!schemaColumn) {\n issues.push({\n kind: 'missing_column',\n table: tableName,\n namespaceId,\n column: columnName,\n message: `Column \"${tableName}\".\"${columnName}\" is missing from database`,\n });\n columnNodes.push({\n status: 'fail',\n kind: 'column',\n name: `${columnName}: missing`,\n contractPath: columnPath,\n code: 'missing_column',\n message: `Column \"${columnName}\" is missing`,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n continue;\n }\n\n columnNodes.push(\n verifyColumn({\n tableName,\n namespaceId,\n columnName,\n contractColumn,\n schemaColumn,\n columnPath,\n issues,\n strict,\n typeMetadataRegistry,\n codecHooks,\n storageTypes,\n ...ifDefined('normalizeDefault', normalizeDefault),\n ...ifDefined('normalizeNativeType', normalizeNativeType),\n }),\n );\n }\n\n return columnNodes;\n}\n\nfunction appendExtraColumnNodes(options: {\n contractTable: StorageTable;\n schemaTable: SqlSchemaIR['tables'][string];\n tableName: string;\n namespaceId: string;\n tablePath: string;\n issues: SchemaIssue[];\n columnNodes: SchemaVerificationNode[];\n}): void {\n const { contractTable, schemaTable, tableName, namespaceId, tablePath, issues, columnNodes } =\n options;\n for (const [columnName, { nativeType }] of Object.entries(schemaTable.columns)) {\n if (!contractTable.columns[columnName]) {\n issues.push({\n kind: 'extra_column',\n table: tableName,\n namespaceId,\n column: columnName,\n message: `Extra column \"${tableName}\".\"${columnName}\" found in database (not in contract)`,\n });\n columnNodes.push({\n status: 'fail',\n kind: 'column',\n name: `${columnName}: extra`,\n contractPath: `${tablePath}.columns.${columnName}`,\n code: 'extra_column',\n message: `Extra column \"${columnName}\" found`,\n expected: undefined,\n actual: nativeType,\n children: [],\n });\n }\n }\n}\n\nfunction verifyColumn(options: {\n tableName: string;\n namespaceId: string;\n columnName: string;\n contractColumn: StorageTable['columns'][string];\n schemaColumn: SqlSchemaIR['tables'][string]['columns'][string];\n columnPath: string;\n issues: SchemaIssue[];\n strict: boolean;\n typeMetadataRegistry: ReadonlyMap<string, { nativeType?: string }>;\n codecHooks: Map<string, CodecControlHooks>;\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>;\n normalizeDefault?: DefaultNormalizer;\n normalizeNativeType?: NativeTypeNormalizer;\n}): SchemaVerificationNode {\n const {\n tableName,\n namespaceId,\n columnName,\n contractColumn,\n schemaColumn,\n columnPath,\n issues,\n strict,\n codecHooks,\n storageTypes,\n normalizeDefault,\n normalizeNativeType,\n } = options;\n const columnChildren: SchemaVerificationNode[] = [];\n let columnStatus: VerificationStatus = 'pass';\n\n const resolvedContractColumn = resolveContractColumnTypeMetadata(contractColumn, storageTypes, {\n tableName,\n columnName,\n });\n const contractNativeType = renderExpectedNativeType(contractColumn, storageTypes, codecHooks, {\n tableName,\n columnName,\n });\n const schemaNativeType =\n normalizeNativeType?.(schemaColumn.nativeType) ?? schemaColumn.nativeType;\n\n if (contractNativeType !== schemaNativeType) {\n issues.push({\n kind: 'type_mismatch',\n table: tableName,\n namespaceId,\n column: columnName,\n expected: contractNativeType,\n actual: schemaNativeType,\n message: `Column \"${tableName}\".\"${columnName}\" has type mismatch: expected \"${contractNativeType}\", got \"${schemaNativeType}\"`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'type',\n name: 'type',\n contractPath: `${columnPath}.nativeType`,\n code: 'type_mismatch',\n message: `Type mismatch: expected ${contractNativeType}, got ${schemaNativeType}`,\n expected: contractNativeType,\n actual: schemaNativeType,\n children: [],\n });\n columnStatus = 'fail';\n }\n\n if (resolvedContractColumn.codecId) {\n const typeMetadata = options.typeMetadataRegistry.get(resolvedContractColumn.codecId);\n if (!typeMetadata) {\n columnChildren.push({\n status: 'warn',\n kind: 'type',\n name: 'type_metadata_missing',\n contractPath: `${columnPath}.codecId`,\n code: 'type_metadata_missing',\n message: `codecId \"${resolvedContractColumn.codecId}\" not found in type metadata registry`,\n expected: resolvedContractColumn.codecId,\n actual: undefined,\n children: [],\n });\n } else if (\n typeMetadata.nativeType &&\n typeMetadata.nativeType !== resolvedContractColumn.nativeType\n ) {\n columnChildren.push({\n status: 'warn',\n kind: 'type',\n name: 'type_consistency',\n contractPath: `${columnPath}.codecId`,\n code: 'type_consistency_warning',\n message: `codecId \"${resolvedContractColumn.codecId}\" maps to nativeType \"${typeMetadata.nativeType}\" in registry, but contract has \"${resolvedContractColumn.nativeType}\"`,\n expected: typeMetadata.nativeType,\n actual: resolvedContractColumn.nativeType,\n children: [],\n });\n }\n }\n\n if (contractColumn.nullable !== schemaColumn.nullable) {\n issues.push({\n kind: 'nullability_mismatch',\n table: tableName,\n namespaceId,\n column: columnName,\n expected: String(contractColumn.nullable),\n actual: String(schemaColumn.nullable),\n message: `Column \"${tableName}\".\"${columnName}\" has nullability mismatch: expected ${contractColumn.nullable ? 'nullable' : 'not null'}, got ${schemaColumn.nullable ? 'nullable' : 'not null'}`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'nullability',\n name: 'nullability',\n contractPath: `${columnPath}.nullable`,\n code: 'nullability_mismatch',\n message: `Nullability mismatch: expected ${contractColumn.nullable ? 'nullable' : 'not null'}, got ${schemaColumn.nullable ? 'nullable' : 'not null'}`,\n expected: contractColumn.nullable,\n actual: schemaColumn.nullable,\n children: [],\n });\n columnStatus = 'fail';\n }\n\n if (contractColumn.default) {\n if (!schemaColumn.default) {\n const defaultDescription = describeColumnDefault(contractColumn.default);\n issues.push({\n kind: 'default_missing',\n table: tableName,\n namespaceId,\n column: columnName,\n expected: defaultDescription,\n message: `Column \"${tableName}\".\"${columnName}\" should have default ${defaultDescription} but database has no default`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'default',\n name: 'default',\n contractPath: `${columnPath}.default`,\n code: 'default_missing',\n message: `Default missing: expected ${defaultDescription}`,\n expected: defaultDescription,\n actual: undefined,\n children: [],\n });\n columnStatus = 'fail';\n } else if (\n !columnDefaultsEqual(\n contractColumn.default,\n schemaColumn.default,\n normalizeDefault,\n schemaNativeType,\n )\n ) {\n const expectedDescription = describeColumnDefault(contractColumn.default);\n // schemaColumn.default is now a raw string, describe it as-is\n const actualDescription = schemaColumn.default;\n issues.push({\n kind: 'default_mismatch',\n table: tableName,\n namespaceId,\n column: columnName,\n expected: expectedDescription,\n actual: actualDescription,\n message: `Column \"${tableName}\".\"${columnName}\" has default mismatch: expected ${expectedDescription}, got ${actualDescription}`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'default',\n name: 'default',\n contractPath: `${columnPath}.default`,\n code: 'default_mismatch',\n message: `Default mismatch: expected ${expectedDescription}, got ${actualDescription}`,\n expected: expectedDescription,\n actual: actualDescription,\n children: [],\n });\n columnStatus = 'fail';\n }\n } else if (strict && schemaColumn.default) {\n issues.push({\n kind: 'extra_default',\n table: tableName,\n namespaceId,\n column: columnName,\n actual: schemaColumn.default,\n message: `Column \"${tableName}\".\"${columnName}\" has default ${schemaColumn.default} in database but contract specifies no default`,\n });\n columnChildren.push({\n status: 'fail',\n kind: 'default',\n name: 'default',\n contractPath: `${columnPath}.default`,\n code: 'extra_default',\n message: `Extra default: ${schemaColumn.default}`,\n expected: undefined,\n actual: schemaColumn.default,\n children: [],\n });\n columnStatus = 'fail';\n }\n\n // Single-pass aggregation for better performance\n const aggregated = aggregateChildState(columnChildren, columnStatus);\n const nullableText = contractColumn.nullable ? 'nullable' : 'not nullable';\n const columnTypeDisplay = resolvedContractColumn.codecId\n ? `${contractNativeType} (${resolvedContractColumn.codecId})`\n : contractNativeType;\n const columnMessage = aggregated.failureMessages.join('; ');\n\n return {\n status: aggregated.status,\n kind: 'column',\n name: `${columnName}: ${columnTypeDisplay} (${nullableText})`,\n contractPath: columnPath,\n code: aggregated.firstCode,\n message: columnMessage,\n expected: undefined,\n actual: undefined,\n children: columnChildren,\n };\n}\n\nfunction buildColumnsNode(\n tablePath: string,\n columnNodes: SchemaVerificationNode[],\n): SchemaVerificationNode {\n return {\n status: aggregateChildState(columnNodes, 'pass').status,\n kind: 'columns',\n name: 'columns',\n contractPath: `${tablePath}.columns`,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: columnNodes,\n };\n}\n\nfunction buildTableNode(\n tableName: string,\n tablePath: string,\n tableChildren: SchemaVerificationNode[],\n): SchemaVerificationNode {\n const tableStatus = aggregateChildState(tableChildren, 'pass').status;\n const tableFailureMessages = tableChildren\n .filter((child) => child.status === 'fail' && child.message)\n .map((child) => child.message)\n .filter((msg): msg is string => typeof msg === 'string' && msg.length > 0);\n const tableMessage =\n tableStatus === 'fail' && tableFailureMessages.length > 0\n ? `${tableFailureMessages.length} issue${tableFailureMessages.length === 1 ? '' : 's'}`\n : '';\n const tableCode =\n tableStatus === 'fail' && tableChildren.length > 0 && tableChildren[0]\n ? tableChildren[0].code\n : '';\n\n return {\n status: tableStatus,\n kind: 'table',\n name: `table ${tableName}`,\n contractPath: tablePath,\n code: tableCode,\n message: tableMessage,\n expected: undefined,\n actual: undefined,\n children: tableChildren,\n };\n}\n\nfunction buildRootNode(rootChildren: SchemaVerificationNode[]): SchemaVerificationNode {\n return {\n status: aggregateChildState(rootChildren, 'pass').status,\n kind: 'contract',\n name: 'contract',\n contractPath: '',\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: rootChildren,\n };\n}\n\n/**\n * Aggregated state from child nodes, computed in a single pass.\n */\ninterface AggregatedChildState {\n readonly status: VerificationStatus;\n readonly failureMessages: readonly string[];\n readonly firstCode: string;\n}\n\n/**\n * Aggregates status, failure messages, and code from children in a single pass.\n * This is more efficient than calling separate functions that each iterate the array.\n */\nfunction aggregateChildState(\n children: SchemaVerificationNode[],\n fallback: VerificationStatus,\n): AggregatedChildState {\n let status: VerificationStatus = fallback;\n const failureMessages: string[] = [];\n let firstCode = '';\n\n for (const child of children) {\n if (child.status === 'fail') {\n status = 'fail';\n if (!firstCode) {\n firstCode = child.code;\n }\n if (child.message && typeof child.message === 'string' && child.message.length > 0) {\n failureMessages.push(child.message);\n }\n } else if (child.status === 'warn' && status !== 'fail') {\n status = 'warn';\n if (!firstCode) {\n firstCode = child.code;\n }\n }\n }\n\n return { status, failureMessages, firstCode };\n}\n\nfunction validateFrameworkComponentsForExtensions(\n contract: Contract<SqlStorage>,\n frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>,\n): void {\n const contractExtensionPacks = contract.extensionPacks ?? {};\n for (const extensionNamespace of Object.keys(contractExtensionPacks)) {\n const hasComponent = frameworkComponents.some(\n (component) =>\n component.id === extensionNamespace &&\n (component.kind === 'extension' ||\n component.kind === 'adapter' ||\n component.kind === 'target'),\n );\n if (!hasComponent) {\n throw new Error(\n `Extension pack '${extensionNamespace}' is declared in the contract but not found in framework components. ` +\n 'This indicates a configuration mismatch - the contract was emitted with this extension pack, ' +\n 'but it is not provided in the current configuration.',\n );\n }\n }\n}\n\n/**\n * Renders the expected native type for a contract column, expanding parameterized types\n * using codec control hooks when available.\n *\n * This function delegates to the `expandNativeType` hook if the codec provides one,\n * ensuring that the SQL family layer remains dialect-agnostic while allowing\n * target-specific adapters (like Postgres) to provide their own expansion logic.\n */\nfunction renderExpectedNativeType(\n contractColumn: StorageColumn,\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,\n codecHooks: Map<string, CodecControlHooks>,\n context?: {\n readonly tableName: string;\n readonly columnName: string;\n },\n): string {\n const { codecId, nativeType, typeParams } = resolveContractColumnTypeMetadata(\n contractColumn,\n storageTypes,\n context,\n );\n\n // If no typeParams or codecId, return the base native type\n if (!typeParams || !codecId) {\n return nativeType;\n }\n\n // Try to use the codec's expandNativeType hook if available\n const hooks = codecHooks.get(codecId);\n if (hooks?.expandNativeType) {\n return hooks.expandNativeType({ nativeType, codecId, typeParams });\n }\n\n // Fallback: return base native type if no hook is available\n return nativeType;\n}\n\nfunction resolveContractColumnTypeMetadata(\n contractColumn: StorageColumn,\n storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,\n context?: {\n readonly tableName: string;\n readonly columnName: string;\n },\n): Pick<StorageColumn, 'codecId' | 'nativeType' | 'typeParams'> {\n if (!contractColumn.typeRef) {\n return contractColumn;\n }\n\n const referencedType = storageTypes[contractColumn.typeRef];\n if (!referencedType) {\n const columnLabel = context\n ? `Column \"${context.tableName}\".\"${context.columnName}\"`\n : 'Column';\n throw new Error(\n `${columnLabel} references storage type \"${contractColumn.typeRef}\" but it is not defined in storage.types.`,\n );\n }\n\n if (isPostgresEnumStorageEntry(referencedType)) {\n return {\n codecId: referencedType.codecId,\n nativeType: referencedType.nativeType,\n typeParams: { values: referencedType.values } as Record<string, unknown>,\n };\n }\n if (isStorageTypeInstance(referencedType)) {\n return {\n codecId: referencedType.codecId,\n nativeType: referencedType.nativeType,\n typeParams: referencedType.typeParams,\n };\n }\n throw new Error(\n `Storage type \"${contractColumn.typeRef}\" has an unknown polymorphic kind; expected codec-instance or postgres-enum.`,\n );\n}\n\n/**\n * Describes a column default for display purposes.\n */\nfunction describeColumnDefault(columnDefault: ColumnDefault): string {\n switch (columnDefault.kind) {\n case 'literal':\n return `literal(${formatLiteralValue(columnDefault.value)})`;\n case 'function':\n return columnDefault.expression;\n }\n}\n\n/**\n * Compares a contract ColumnDefault against a schema raw default string for semantic equality.\n *\n * When a normalizer is provided, the raw schema default is first normalized to a ColumnDefault\n * before comparison. Without a normalizer, falls back to direct string comparison against\n * the contract expression.\n *\n * @param contractDefault - The expected default from the contract (normalized ColumnDefault)\n * @param schemaDefault - The raw default expression from the database (string)\n * @param normalizer - Optional target-specific normalizer to convert raw defaults\n * @param nativeType - The column's native type, passed to normalizer for context\n */\nfunction columnDefaultsEqual(\n contractDefault: ColumnDefault,\n schemaDefault: string,\n normalizer?: DefaultNormalizer,\n nativeType?: string,\n): boolean {\n // If no normalizer provided, fall back to direct string comparison\n if (!normalizer) {\n if (contractDefault.kind === 'function') {\n return contractDefault.expression === schemaDefault;\n }\n const normalizedValue = normalizeLiteralValue(contractDefault.value, nativeType);\n if (typeof normalizedValue === 'string') {\n return normalizedValue === schemaDefault || `'${normalizedValue}'` === schemaDefault;\n }\n return String(normalizedValue) === schemaDefault;\n }\n\n // Normalize the raw schema default using target-specific logic\n const normalizedSchema = normalizer(schemaDefault, nativeType ?? '');\n if (!normalizedSchema) {\n // Normalizer couldn't parse the expression - treat as mismatch\n return false;\n }\n\n // Compare normalized defaults\n if (contractDefault.kind !== normalizedSchema.kind) {\n return false;\n }\n if (contractDefault.kind === 'literal' && normalizedSchema.kind === 'literal') {\n const contractValue = normalizeLiteralValue(contractDefault.value, nativeType);\n const schemaValue = normalizeLiteralValue(normalizedSchema.value, nativeType);\n return literalValuesEqual(contractValue, schemaValue);\n }\n if (contractDefault.kind === 'function' && normalizedSchema.kind === 'function') {\n // Normalize function expressions for comparison (case-insensitive, whitespace-tolerant)\n const normalizeExpr = (expr: string) => expr.toLowerCase().replace(/\\s+/g, '');\n return normalizeExpr(contractDefault.expression) === normalizeExpr(normalizedSchema.expression);\n }\n return false;\n}\n\nfunction isTemporalNativeType(nativeType?: string): boolean {\n if (!nativeType) return false;\n const normalized = nativeType.toLowerCase();\n return normalized.includes('timestamp') || normalized === 'date';\n}\n\nfunction normalizeLiteralValue(value: unknown, nativeType?: string): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === 'string' && isTemporalNativeType(nativeType)) {\n const parsed = new Date(value);\n if (!Number.isNaN(parsed.getTime())) {\n return parsed.toISOString();\n }\n }\n return value;\n}\n\nfunction literalValuesEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {\n return canonicalStringify(a) === canonicalStringify(b);\n }\n if (typeof a === 'object' && a !== null && typeof b === 'string') {\n try {\n return canonicalStringify(a) === canonicalStringify(JSON.parse(b));\n } catch {\n return false;\n }\n }\n if (typeof a === 'string' && typeof b === 'object' && b !== null) {\n try {\n return canonicalStringify(JSON.parse(a)) === canonicalStringify(b);\n } catch {\n return false;\n }\n }\n return false;\n}\n\nfunction formatLiteralValue(value: unknown): string {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === 'string') {\n return value;\n }\n return JSON.stringify(value);\n}\n"],"mappings":"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"}