@prisma-next/family-sql 0.3.0-pr.87.2 → 0.3.0-pr.87.3

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.
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-SU7LN2UH.js";
5
5
  import {
6
6
  verifySqlSchema
7
- } from "./chunk-D6DIM7UR.js";
7
+ } from "./chunk-XH2Y5NTD.js";
8
8
 
9
9
  // src/core/assembly.ts
10
10
  import { createOperationRegistry } from "@prisma-next/operations";
@@ -586,4 +586,4 @@ export {
586
586
  convertOperationManifest,
587
587
  createSqlFamilyInstance
588
588
  };
589
- //# sourceMappingURL=chunk-DI4IPJTV.js.map
589
+ //# sourceMappingURL=chunk-F27CR6XZ.js.map
@@ -10,6 +10,20 @@ function arraysEqual(a, b) {
10
10
  }
11
11
  return true;
12
12
  }
13
+ function isUniqueConstraintSatisfied(uniques, indexes, columns) {
14
+ const hasConstraint = uniques.some((unique) => arraysEqual(unique.columns, columns));
15
+ if (hasConstraint) {
16
+ return true;
17
+ }
18
+ return indexes.some((index) => index.unique && arraysEqual(index.columns, columns));
19
+ }
20
+ function isIndexSatisfied(indexes, uniques, columns) {
21
+ const hasMatchingIndex = indexes.some((index) => arraysEqual(index.columns, columns));
22
+ if (hasMatchingIndex) {
23
+ return true;
24
+ }
25
+ return uniques.some((unique) => arraysEqual(unique.columns, columns));
26
+ }
13
27
  function verifyPrimaryKey(contractPK, schemaPK, tableName, issues) {
14
28
  if (!schemaPK) {
15
29
  issues.push({
@@ -693,7 +707,9 @@ function collectDependenciesFromFrameworkComponents(components) {
693
707
 
694
708
  export {
695
709
  arraysEqual,
710
+ isUniqueConstraintSatisfied,
711
+ isIndexSatisfied,
696
712
  verifyDatabaseDependencies,
697
713
  verifySqlSchema
698
714
  };
699
- //# sourceMappingURL=chunk-D6DIM7UR.js.map
715
+ //# sourceMappingURL=chunk-XH2Y5NTD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/schema-verify/verify-helpers.ts","../src/core/schema-verify/verify-sql-schema.ts"],"sourcesContent":["/**\n * Pure verification helper functions for SQL schema verification.\n * These functions verify schema IR against contract requirements.\n */\n\nimport type { SchemaIssue, SchemaVerificationNode } from '@prisma-next/core-control-plane/types';\nimport type {\n ForeignKey,\n Index,\n PrimaryKey,\n UniqueConstraint,\n} from '@prisma-next/sql-contract/types';\nimport type {\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlSchemaIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport type { ComponentDatabaseDependency } from '../migrations/types';\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 issues: SchemaIssue[],\n): 'pass' | 'fail' {\n if (!schemaPK) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\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 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 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.columns.join(',')}]`;\n const matchingFK = schemaFKs.find((fk) => {\n return (\n arraysEqual(fk.columns, contractFK.columns) &&\n fk.referencedTable === contractFK.references.table &&\n arraysEqual(fk.referencedColumns, contractFK.references.columns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n expected: `${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n message: `Table \"${tableName}\" is missing foreign key: ${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.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 // 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: 'foreignKey',\n name: `foreignKey(${contractFK.columns.join(', ')})`,\n contractPath: fkPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\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 return (\n arraysEqual(fk.columns, schemaFK.columns) &&\n fk.references.table === schemaFK.referencedTable &&\n arraysEqual(fk.references.columns, schemaFK.referencedColumns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'extra_foreign_key',\n table: tableName,\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 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 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 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 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((idx) =>\n arraysEqual(idx.columns, contractIndex.columns),\n );\n\n // Also check if a unique constraint satisfies the index requirement\n const matchingUniqueConstraint =\n !matchingIndex && schemaUniques.find((u) => arraysEqual(u.columns, contractIndex.columns));\n\n if (!matchingIndex && !matchingUniqueConstraint) {\n issues.push({\n kind: 'index_mismatch',\n table: tableName,\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((idx) =>\n arraysEqual(idx.columns, schemaIndex.columns),\n );\n\n if (!matchingIndex) {\n issues.push({\n kind: 'extra_index',\n table: tableName,\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 * Verifies database dependencies are installed using component-owned verification hooks.\n * Each dependency provides a pure verifyDatabaseDependencyInstalled function that checks\n * whether the dependency is satisfied based on the in-memory schema IR (no DB I/O).\n *\n * Returns verification nodes for the tree.\n */\nexport function verifyDatabaseDependencies(\n dependencies: ReadonlyArray<ComponentDatabaseDependency<unknown>>,\n schema: SqlSchemaIR,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n for (const dependency of dependencies) {\n const depIssues = dependency.verifyDatabaseDependencyInstalled(schema);\n const depPath = `dependencies.${dependency.id}`;\n\n if (depIssues.length > 0) {\n // Dependency is not satisfied\n issues.push(...depIssues);\n const issuesMessage = depIssues.map((i) => i.message).join('; ');\n const nodeMessage = issuesMessage ? `${dependency.id}: ${issuesMessage}` : dependency.id;\n nodes.push({\n status: 'fail',\n kind: 'databaseDependency',\n name: dependency.label,\n contractPath: depPath,\n code: 'dependency_missing',\n message: nodeMessage,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n } else {\n // Dependency is satisfied\n nodes.push({\n status: 'pass',\n kind: 'databaseDependency',\n name: dependency.label,\n contractPath: depPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\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 * Pure SQL schema verification function.\n *\n * This module provides a pure function that verifies a SqlSchemaIR against\n * a SqlContract 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 { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type {\n OperationContext,\n SchemaIssue,\n SchemaVerificationNode,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { ComponentDatabaseDependency } from '../migrations/types';\nimport {\n computeCounts,\n verifyDatabaseDependencies,\n verifyForeignKeys,\n verifyIndexes,\n verifyPrimaryKey,\n verifyUniqueConstraints,\n} from './verify-helpers';\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: SqlContract<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\n/**\n * Verifies that a SqlSchemaIR matches a SqlContract.\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 { contract, schema, strict, context, typeMetadataRegistry } = options;\n const startTime = Date.now();\n\n // Extract contract hashes and target\n const contractCoreHash = contract.coreHash;\n const contractProfileHash =\n 'profileHash' in contract && typeof contract.profileHash === 'string'\n ? contract.profileHash\n : undefined;\n const contractTarget = contract.target;\n\n // Compare contract vs schema IR\n const issues: SchemaIssue[] = [];\n const rootChildren: SchemaVerificationNode[] = [];\n\n // Compare tables\n const contractTables = contract.storage.tables;\n const schemaTables = schema.tables;\n\n for (const [tableName, contractTable] of Object.entries(contractTables)) {\n const schemaTable = schemaTables[tableName];\n const tablePath = `storage.tables.${tableName}`;\n\n if (!schemaTable) {\n // Missing table\n issues.push({\n kind: 'missing_table',\n table: tableName,\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 // Table exists - compare columns, constraints, etc.\n const tableChildren: SchemaVerificationNode[] = [];\n const columnNodes: SchemaVerificationNode[] = [];\n\n // Compare columns\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 // Missing column\n issues.push({\n kind: 'missing_column',\n table: tableName,\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 // Column exists - compare type and nullability\n const columnChildren: SchemaVerificationNode[] = [];\n let columnStatus: 'pass' | 'warn' | 'fail' = 'pass';\n\n // Compare type using nativeType directly\n // Both contractColumn.nativeType and schemaColumn.nativeType are required by their types\n const contractNativeType = contractColumn.nativeType;\n const schemaNativeType = schemaColumn.nativeType;\n\n if (contractNativeType !== schemaNativeType) {\n // Compare native types directly\n issues.push({\n kind: 'type_mismatch',\n table: tableName,\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 // Optionally validate that codecId (if present) and nativeType agree with registry\n if (contractColumn.codecId) {\n const typeMetadata = typeMetadataRegistry.get(contractColumn.codecId);\n if (!typeMetadata) {\n // Warning: codecId not found in registry\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 \"${contractColumn.codecId}\" not found in type metadata registry`,\n expected: contractColumn.codecId,\n actual: undefined,\n children: [],\n });\n } else if (typeMetadata.nativeType && typeMetadata.nativeType !== contractNativeType) {\n // Warning: codecId and nativeType don't agree with registry\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 \"${contractColumn.codecId}\" maps to nativeType \"${typeMetadata.nativeType}\" in registry, but contract has \"${contractNativeType}\"`,\n expected: typeMetadata.nativeType,\n actual: contractNativeType,\n children: [],\n });\n }\n }\n\n // Compare nullability\n if (contractColumn.nullable !== schemaColumn.nullable) {\n issues.push({\n kind: 'nullability_mismatch',\n table: tableName,\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 // Compute column status from children (fail > warn > pass)\n const computedColumnStatus = columnChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : columnChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Use computed status if we have children, otherwise use the manually set status\n const finalColumnStatus = columnChildren.length > 0 ? computedColumnStatus : columnStatus;\n\n // Build column node\n const nullableText = contractColumn.nullable ? 'nullable' : 'not nullable';\n const columnTypeDisplay = contractColumn.codecId\n ? `${contractNativeType} (${contractColumn.codecId})`\n : contractNativeType;\n // Collect failure messages from children to create a summary message\n const failureMessages = columnChildren\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 columnMessage =\n finalColumnStatus === 'fail' && failureMessages.length > 0\n ? failureMessages.join('; ')\n : '';\n // Extract code from first child if status indicates an issue\n const columnCode =\n (finalColumnStatus === 'fail' || finalColumnStatus === 'warn') && columnChildren[0]\n ? columnChildren[0].code\n : '';\n columnNodes.push({\n status: finalColumnStatus,\n kind: 'column',\n name: `${columnName}: ${columnTypeDisplay} (${nullableText})`,\n contractPath: columnPath,\n code: columnCode,\n message: columnMessage,\n expected: undefined,\n actual: undefined,\n children: columnChildren,\n });\n }\n\n // Group columns under a \"columns\" header if we have any columns\n if (columnNodes.length > 0) {\n const columnsStatus = columnNodes.some((c) => c.status === 'fail')\n ? 'fail'\n : columnNodes.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n tableChildren.push({\n status: columnsStatus,\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\n // Check for extra columns in strict mode\n if (strict) {\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 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\n // Compare primary key\n if (contractTable.primaryKey) {\n const pkStatus = verifyPrimaryKey(\n contractTable.primaryKey,\n schemaTable.primaryKey,\n tableName,\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 // Extra primary key in strict mode\n issues.push({\n kind: 'extra_primary_key',\n table: tableName,\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 // Compare foreign keys\n const fkStatuses = verifyForeignKeys(\n contractTable.foreignKeys,\n schemaTable.foreignKeys,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...fkStatuses);\n\n // Compare unique constraints\n // Pass schemaIndexes so unique indexes can satisfy unique constraint requirements\n const uniqueStatuses = verifyUniqueConstraints(\n contractTable.uniques,\n schemaTable.uniques,\n schemaTable.indexes,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...uniqueStatuses);\n\n // Compare indexes\n // Pass schemaUniques so unique constraints can satisfy index requirements\n const indexStatuses = verifyIndexes(\n contractTable.indexes,\n schemaTable.indexes,\n schemaTable.uniques,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...indexStatuses);\n\n // Build table node\n const tableStatus = tableChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : tableChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Collect failure messages from children to create a summary message\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 rootChildren.push({\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\n // Check for extra tables in strict mode\n if (strict) {\n for (const tableName of Object.keys(schemaTables)) {\n if (!contractTables[tableName]) {\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.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 // Validate that all extension packs declared in the contract are present in frameworkComponents\n // This is a configuration integrity check - if the contract was emitted with an extension,\n // that extension must be provided in the current configuration.\n // Note: contract.extensionPacks includes adapter.id and target.id (from extractExtensionIds),\n // so we check for matches as extension, adapter, or target components.\n const contractExtensionPacks = contract.extensionPacks ?? {};\n for (const extensionNamespace of Object.keys(contractExtensionPacks)) {\n const hasComponent = options.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 // Compare component-owned database dependencies (pure, deterministic)\n // Per ADR 154: We do NOT infer dependencies from contract extension packs.\n // Dependencies are only collected from frameworkComponents provided by the CLI.\n const databaseDependencies = collectDependenciesFromFrameworkComponents(\n options.frameworkComponents,\n );\n const dependencyStatuses = verifyDatabaseDependencies(databaseDependencies, schema, issues);\n rootChildren.push(...dependencyStatuses);\n\n // Build root node\n const rootStatus = rootChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : rootChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n const root: SchemaVerificationNode = {\n status: rootStatus,\n kind: 'contract',\n name: 'contract',\n contractPath: '',\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: rootChildren,\n };\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 coreHash: contractCoreHash,\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\n/**\n * Type predicate to check if a component has database dependencies with an init array.\n * The familyId check is redundant since TargetBoundComponentDescriptor<'sql', T> already\n * guarantees familyId is 'sql' at the type level, so we don't need runtime checks for it.\n */\nfunction hasDatabaseDependenciesInit<T extends string>(\n component: TargetBoundComponentDescriptor<'sql', T>,\n): component is TargetBoundComponentDescriptor<'sql', T> & {\n readonly databaseDependencies: {\n readonly init: readonly ComponentDatabaseDependency<T>[];\n };\n} {\n if (!('databaseDependencies' in component)) {\n return false;\n }\n const dbDeps = (component as Record<string, unknown>)['databaseDependencies'];\n if (dbDeps === undefined || dbDeps === null || typeof dbDeps !== 'object') {\n return false;\n }\n const depsRecord = dbDeps as Record<string, unknown>;\n const init = depsRecord['init'];\n if (init === undefined || !Array.isArray(init)) {\n return false;\n }\n return true;\n}\n\nfunction collectDependenciesFromFrameworkComponents<T extends string>(\n components: ReadonlyArray<TargetBoundComponentDescriptor<'sql', T>>,\n): ReadonlyArray<ComponentDatabaseDependency<T>> {\n const dependencies: ComponentDatabaseDependency<T>[] = [];\n for (const component of components) {\n if (hasDatabaseDependenciesInit(component)) {\n dependencies.push(...component.databaseDependencies.init);\n }\n }\n return dependencies;\n}\n"],"mappings":"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","names":[]}
@@ -10,6 +10,32 @@ import type { ComponentDatabaseDependency } from '../migrations/types';
10
10
  * Compares two arrays of strings for equality (order-sensitive).
11
11
  */
12
12
  export declare function arraysEqual(a: readonly string[], b: readonly string[]): boolean;
13
+ /**
14
+ * Checks if a unique constraint requirement is satisfied by the given columns.
15
+ *
16
+ * Semantic satisfaction: a unique constraint requirement can be satisfied by:
17
+ * - A unique constraint with the same columns, OR
18
+ * - A unique index with the same columns
19
+ *
20
+ * @param uniques - The unique constraints in the schema table
21
+ * @param indexes - The indexes in the schema table
22
+ * @param columns - The columns required by the unique constraint
23
+ * @returns true if the requirement is satisfied
24
+ */
25
+ export declare function isUniqueConstraintSatisfied(uniques: readonly SqlUniqueIR[], indexes: readonly SqlIndexIR[], columns: readonly string[]): boolean;
26
+ /**
27
+ * Checks if an index requirement is satisfied by the given columns.
28
+ *
29
+ * Semantic satisfaction: a non-unique index requirement can be satisfied by:
30
+ * - Any index (unique or non-unique) with the same columns, OR
31
+ * - A unique constraint with the same columns (stronger satisfies weaker)
32
+ *
33
+ * @param indexes - The indexes in the schema table
34
+ * @param uniques - The unique constraints in the schema table
35
+ * @param columns - The columns required by the index
36
+ * @returns true if the requirement is satisfied
37
+ */
38
+ export declare function isIndexSatisfied(indexes: readonly SqlIndexIR[], uniques: readonly SqlUniqueIR[], columns: readonly string[]): boolean;
13
39
  /**
14
40
  * Verifies primary key matches between contract and schema.
15
41
  * Returns 'pass' or 'fail'.
@@ -1 +1 @@
1
- {"version":3,"file":"verify-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/schema-verify/verify-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AACjG,OAAO,KAAK,EACV,UAAU,EACV,KAAK,EACL,UAAU,EACV,gBAAgB,EACjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACZ,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAEvE;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAU/E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,GACpB,MAAM,GAAG,MAAM,CA0BjB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAkF1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,SAAS,gBAAgB,EAAE,EAC5C,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,aAAa,EAAE,SAAS,UAAU,EAAE,EACpC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAiF1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,eAAe,EAAE,SAAS,KAAK,EAAE,EACjC,aAAa,EAAE,SAAS,UAAU,EAAE,EACpC,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAsF1B;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,aAAa,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,EACjE,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,sBAAsB,EAAE,CAwC1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,sBAAsB,GAAG;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CA6BA"}
1
+ {"version":3,"file":"verify-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/schema-verify/verify-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AACjG,OAAO,KAAK,EACV,UAAU,EACV,KAAK,EACL,UAAU,EACV,gBAAgB,EACjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACZ,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAEvE;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAU/E;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAQT;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAQT;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,GACpB,MAAM,GAAG,MAAM,CA0BjB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAkF1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,SAAS,gBAAgB,EAAE,EAC5C,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,aAAa,EAAE,SAAS,UAAU,EAAE,EACpC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAiF1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,eAAe,EAAE,SAAS,KAAK,EAAE,EACjC,aAAa,EAAE,SAAS,UAAU,EAAE,EACpC,aAAa,EAAE,SAAS,WAAW,EAAE,EACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,sBAAsB,EAAE,CAsF1B;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,aAAa,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,EACjE,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,sBAAsB,EAAE,CAwC1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,sBAAsB,GAAG;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CA6BA"}
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createSqlFamilyInstance
3
- } from "../chunk-DI4IPJTV.js";
3
+ } from "../chunk-F27CR6XZ.js";
4
4
  import "../chunk-SU7LN2UH.js";
5
- import "../chunk-D6DIM7UR.js";
5
+ import "../chunk-XH2Y5NTD.js";
6
6
 
7
7
  // src/core/descriptor.ts
8
8
  import { sqlTargetFamilyHook } from "@prisma-next/sql-contract-emitter";
@@ -5,7 +5,7 @@
5
5
  * without a database connection. It's suitable for migration planning and
6
6
  * other tools that need to compare schema states.
7
7
  */
8
- export { arraysEqual, verifyDatabaseDependencies } from '../core/schema-verify/verify-helpers';
8
+ export { arraysEqual, isIndexSatisfied, isUniqueConstraintSatisfied, verifyDatabaseDependencies, } from '../core/schema-verify/verify-helpers';
9
9
  export type { VerifySqlSchemaOptions } from '../core/schema-verify/verify-sql-schema';
10
10
  export { verifySqlSchema } from '../core/schema-verify/verify-sql-schema';
11
11
  //# sourceMappingURL=schema-verify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-verify.d.ts","sourceRoot":"","sources":["../../src/exports/schema-verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAC/F,YAAY,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC"}
1
+ {"version":3,"file":"schema-verify.d.ts","sourceRoot":"","sources":["../../src/exports/schema-verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC"}
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  arraysEqual,
3
+ isIndexSatisfied,
4
+ isUniqueConstraintSatisfied,
3
5
  verifyDatabaseDependencies,
4
6
  verifySqlSchema
5
- } from "../chunk-D6DIM7UR.js";
7
+ } from "../chunk-XH2Y5NTD.js";
6
8
  export {
7
9
  arraysEqual,
10
+ isIndexSatisfied,
11
+ isUniqueConstraintSatisfied,
8
12
  verifyDatabaseDependencies,
9
13
  verifySqlSchema
10
14
  };
@@ -4,9 +4,9 @@ import {
4
4
  extractCodecTypeImports,
5
5
  extractExtensionIds,
6
6
  extractOperationTypeImports
7
- } from "../chunk-DI4IPJTV.js";
7
+ } from "../chunk-F27CR6XZ.js";
8
8
  import "../chunk-SU7LN2UH.js";
9
- import "../chunk-D6DIM7UR.js";
9
+ import "../chunk-XH2Y5NTD.js";
10
10
  export {
11
11
  assembleOperationRegistry,
12
12
  convertOperationManifest,
package/package.json CHANGED
@@ -1,32 +1,32 @@
1
1
  {
2
2
  "name": "@prisma-next/family-sql",
3
- "version": "0.3.0-pr.87.2",
3
+ "version": "0.3.0-pr.87.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "SQL family descriptor for Prisma Next",
7
7
  "dependencies": {
8
8
  "arktype": "^2.0.0",
9
- "@prisma-next/cli": "0.3.0-pr.87.2",
10
- "@prisma-next/contract": "0.3.0-pr.87.2",
11
- "@prisma-next/core-control-plane": "0.3.0-pr.87.2",
12
- "@prisma-next/core-execution-plane": "0.3.0-pr.87.2",
13
- "@prisma-next/operations": "0.3.0-pr.87.2",
14
- "@prisma-next/runtime-executor": "0.3.0-pr.87.2",
15
- "@prisma-next/sql-contract": "0.3.0-pr.87.2",
16
- "@prisma-next/sql-contract-emitter": "0.3.0-pr.87.2",
17
- "@prisma-next/sql-contract-ts": "0.3.0-pr.87.2",
18
- "@prisma-next/sql-operations": "0.3.0-pr.87.2",
19
- "@prisma-next/sql-relational-core": "0.3.0-pr.87.2",
20
- "@prisma-next/sql-runtime": "0.3.0-pr.87.2",
21
- "@prisma-next/utils": "0.3.0-pr.87.2",
22
- "@prisma-next/sql-schema-ir": "0.3.0-pr.87.2"
9
+ "@prisma-next/cli": "0.3.0-pr.87.3",
10
+ "@prisma-next/contract": "0.3.0-pr.87.3",
11
+ "@prisma-next/core-control-plane": "0.3.0-pr.87.3",
12
+ "@prisma-next/core-execution-plane": "0.3.0-pr.87.3",
13
+ "@prisma-next/operations": "0.3.0-pr.87.3",
14
+ "@prisma-next/sql-contract": "0.3.0-pr.87.3",
15
+ "@prisma-next/sql-contract-emitter": "0.3.0-pr.87.3",
16
+ "@prisma-next/sql-contract-ts": "0.3.0-pr.87.3",
17
+ "@prisma-next/sql-operations": "0.3.0-pr.87.3",
18
+ "@prisma-next/runtime-executor": "0.3.0-pr.87.3",
19
+ "@prisma-next/sql-relational-core": "0.3.0-pr.87.3",
20
+ "@prisma-next/sql-runtime": "0.3.0-pr.87.3",
21
+ "@prisma-next/sql-schema-ir": "0.3.0-pr.87.3",
22
+ "@prisma-next/utils": "0.3.0-pr.87.3"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@vitest/coverage-v8": "4.0.16",
26
26
  "tsup": "8.5.1",
27
27
  "typescript": "5.9.3",
28
28
  "vitest": "4.0.16",
29
- "@prisma-next/driver-postgres": "0.3.0-pr.87.2",
29
+ "@prisma-next/driver-postgres": "0.3.0-pr.87.3",
30
30
  "@prisma-next/test-utils": "0.0.1"
31
31
  },
32
32
  "files": [
@@ -33,6 +33,65 @@ export function arraysEqual(a: readonly string[], b: readonly string[]): boolean
33
33
  return true;
34
34
  }
35
35
 
36
+ // ============================================================================
37
+ // Semantic Satisfaction Predicates
38
+ // ============================================================================
39
+ // These predicates implement the "stronger satisfies weaker" logic for storage
40
+ // objects. They are used by both verification and migration planning to ensure
41
+ // consistent behavior across the control plane.
42
+
43
+ /**
44
+ * Checks if a unique constraint requirement is satisfied by the given columns.
45
+ *
46
+ * Semantic satisfaction: a unique constraint requirement can be satisfied by:
47
+ * - A unique constraint with the same columns, OR
48
+ * - A unique index with the same columns
49
+ *
50
+ * @param uniques - The unique constraints in the schema table
51
+ * @param indexes - The indexes in the schema table
52
+ * @param columns - The columns required by the unique constraint
53
+ * @returns true if the requirement is satisfied
54
+ */
55
+ export function isUniqueConstraintSatisfied(
56
+ uniques: readonly SqlUniqueIR[],
57
+ indexes: readonly SqlIndexIR[],
58
+ columns: readonly string[],
59
+ ): boolean {
60
+ // Check for matching unique constraint
61
+ const hasConstraint = uniques.some((unique) => arraysEqual(unique.columns, columns));
62
+ if (hasConstraint) {
63
+ return true;
64
+ }
65
+ // Check for matching unique index (semantic satisfaction)
66
+ return indexes.some((index) => index.unique && arraysEqual(index.columns, columns));
67
+ }
68
+
69
+ /**
70
+ * Checks if an index requirement is satisfied by the given columns.
71
+ *
72
+ * Semantic satisfaction: a non-unique index requirement can be satisfied by:
73
+ * - Any index (unique or non-unique) with the same columns, OR
74
+ * - A unique constraint with the same columns (stronger satisfies weaker)
75
+ *
76
+ * @param indexes - The indexes in the schema table
77
+ * @param uniques - The unique constraints in the schema table
78
+ * @param columns - The columns required by the index
79
+ * @returns true if the requirement is satisfied
80
+ */
81
+ export function isIndexSatisfied(
82
+ indexes: readonly SqlIndexIR[],
83
+ uniques: readonly SqlUniqueIR[],
84
+ columns: readonly string[],
85
+ ): boolean {
86
+ // Check for any matching index (unique or non-unique)
87
+ const hasMatchingIndex = indexes.some((index) => arraysEqual(index.columns, columns));
88
+ if (hasMatchingIndex) {
89
+ return true;
90
+ }
91
+ // Check for matching unique constraint (semantic satisfaction)
92
+ return uniques.some((unique) => arraysEqual(unique.columns, columns));
93
+ }
94
+
36
95
  /**
37
96
  * Verifies primary key matches between contract and schema.
38
97
  * Returns 'pass' or 'fail'.
@@ -6,6 +6,11 @@
6
6
  * other tools that need to compare schema states.
7
7
  */
8
8
 
9
- export { arraysEqual, verifyDatabaseDependencies } from '../core/schema-verify/verify-helpers';
9
+ export {
10
+ arraysEqual,
11
+ isIndexSatisfied,
12
+ isUniqueConstraintSatisfied,
13
+ verifyDatabaseDependencies,
14
+ } from '../core/schema-verify/verify-helpers';
10
15
  export type { VerifySqlSchemaOptions } from '../core/schema-verify/verify-sql-schema';
11
16
  export { verifySqlSchema } from '../core/schema-verify/verify-sql-schema';
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/schema-verify/verify-helpers.ts","../src/core/schema-verify/verify-sql-schema.ts"],"sourcesContent":["/**\n * Pure verification helper functions for SQL schema verification.\n * These functions verify schema IR against contract requirements.\n */\n\nimport type { SchemaIssue, SchemaVerificationNode } from '@prisma-next/core-control-plane/types';\nimport type {\n ForeignKey,\n Index,\n PrimaryKey,\n UniqueConstraint,\n} from '@prisma-next/sql-contract/types';\nimport type {\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlSchemaIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport type { ComponentDatabaseDependency } from '../migrations/types';\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 * 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 issues: SchemaIssue[],\n): 'pass' | 'fail' {\n if (!schemaPK) {\n issues.push({\n kind: 'primary_key_mismatch',\n table: tableName,\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 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 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.columns.join(',')}]`;\n const matchingFK = schemaFKs.find((fk) => {\n return (\n arraysEqual(fk.columns, contractFK.columns) &&\n fk.referencedTable === contractFK.references.table &&\n arraysEqual(fk.referencedColumns, contractFK.references.columns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'foreign_key_mismatch',\n table: tableName,\n expected: `${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n message: `Table \"${tableName}\" is missing foreign key: ${contractFK.columns.join(', ')} -> ${contractFK.references.table}(${contractFK.references.columns.join(', ')})`,\n });\n nodes.push({\n status: 'fail',\n kind: 'foreignKey',\n name: `foreignKey(${contractFK.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 // 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: 'foreignKey',\n name: `foreignKey(${contractFK.columns.join(', ')})`,\n contractPath: fkPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\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 return (\n arraysEqual(fk.columns, schemaFK.columns) &&\n fk.references.table === schemaFK.referencedTable &&\n arraysEqual(fk.references.columns, schemaFK.referencedColumns)\n );\n });\n\n if (!matchingFK) {\n issues.push({\n kind: 'extra_foreign_key',\n table: tableName,\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 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 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 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 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((idx) =>\n arraysEqual(idx.columns, contractIndex.columns),\n );\n\n // Also check if a unique constraint satisfies the index requirement\n const matchingUniqueConstraint =\n !matchingIndex && schemaUniques.find((u) => arraysEqual(u.columns, contractIndex.columns));\n\n if (!matchingIndex && !matchingUniqueConstraint) {\n issues.push({\n kind: 'index_mismatch',\n table: tableName,\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((idx) =>\n arraysEqual(idx.columns, schemaIndex.columns),\n );\n\n if (!matchingIndex) {\n issues.push({\n kind: 'extra_index',\n table: tableName,\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 * Verifies database dependencies are installed using component-owned verification hooks.\n * Each dependency provides a pure verifyDatabaseDependencyInstalled function that checks\n * whether the dependency is satisfied based on the in-memory schema IR (no DB I/O).\n *\n * Returns verification nodes for the tree.\n */\nexport function verifyDatabaseDependencies(\n dependencies: ReadonlyArray<ComponentDatabaseDependency<unknown>>,\n schema: SqlSchemaIR,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n\n for (const dependency of dependencies) {\n const depIssues = dependency.verifyDatabaseDependencyInstalled(schema);\n const depPath = `dependencies.${dependency.id}`;\n\n if (depIssues.length > 0) {\n // Dependency is not satisfied\n issues.push(...depIssues);\n const issuesMessage = depIssues.map((i) => i.message).join('; ');\n const nodeMessage = issuesMessage ? `${dependency.id}: ${issuesMessage}` : dependency.id;\n nodes.push({\n status: 'fail',\n kind: 'databaseDependency',\n name: dependency.label,\n contractPath: depPath,\n code: 'dependency_missing',\n message: nodeMessage,\n expected: undefined,\n actual: undefined,\n children: [],\n });\n } else {\n // Dependency is satisfied\n nodes.push({\n status: 'pass',\n kind: 'databaseDependency',\n name: dependency.label,\n contractPath: depPath,\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: [],\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 * Pure SQL schema verification function.\n *\n * This module provides a pure function that verifies a SqlSchemaIR against\n * a SqlContract 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 { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';\nimport type {\n OperationContext,\n SchemaIssue,\n SchemaVerificationNode,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { ComponentDatabaseDependency } from '../migrations/types';\nimport {\n computeCounts,\n verifyDatabaseDependencies,\n verifyForeignKeys,\n verifyIndexes,\n verifyPrimaryKey,\n verifyUniqueConstraints,\n} from './verify-helpers';\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: SqlContract<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\n/**\n * Verifies that a SqlSchemaIR matches a SqlContract.\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 { contract, schema, strict, context, typeMetadataRegistry } = options;\n const startTime = Date.now();\n\n // Extract contract hashes and target\n const contractCoreHash = contract.coreHash;\n const contractProfileHash =\n 'profileHash' in contract && typeof contract.profileHash === 'string'\n ? contract.profileHash\n : undefined;\n const contractTarget = contract.target;\n\n // Compare contract vs schema IR\n const issues: SchemaIssue[] = [];\n const rootChildren: SchemaVerificationNode[] = [];\n\n // Compare tables\n const contractTables = contract.storage.tables;\n const schemaTables = schema.tables;\n\n for (const [tableName, contractTable] of Object.entries(contractTables)) {\n const schemaTable = schemaTables[tableName];\n const tablePath = `storage.tables.${tableName}`;\n\n if (!schemaTable) {\n // Missing table\n issues.push({\n kind: 'missing_table',\n table: tableName,\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 // Table exists - compare columns, constraints, etc.\n const tableChildren: SchemaVerificationNode[] = [];\n const columnNodes: SchemaVerificationNode[] = [];\n\n // Compare columns\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 // Missing column\n issues.push({\n kind: 'missing_column',\n table: tableName,\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 // Column exists - compare type and nullability\n const columnChildren: SchemaVerificationNode[] = [];\n let columnStatus: 'pass' | 'warn' | 'fail' = 'pass';\n\n // Compare type using nativeType directly\n // Both contractColumn.nativeType and schemaColumn.nativeType are required by their types\n const contractNativeType = contractColumn.nativeType;\n const schemaNativeType = schemaColumn.nativeType;\n\n if (contractNativeType !== schemaNativeType) {\n // Compare native types directly\n issues.push({\n kind: 'type_mismatch',\n table: tableName,\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 // Optionally validate that codecId (if present) and nativeType agree with registry\n if (contractColumn.codecId) {\n const typeMetadata = typeMetadataRegistry.get(contractColumn.codecId);\n if (!typeMetadata) {\n // Warning: codecId not found in registry\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 \"${contractColumn.codecId}\" not found in type metadata registry`,\n expected: contractColumn.codecId,\n actual: undefined,\n children: [],\n });\n } else if (typeMetadata.nativeType && typeMetadata.nativeType !== contractNativeType) {\n // Warning: codecId and nativeType don't agree with registry\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 \"${contractColumn.codecId}\" maps to nativeType \"${typeMetadata.nativeType}\" in registry, but contract has \"${contractNativeType}\"`,\n expected: typeMetadata.nativeType,\n actual: contractNativeType,\n children: [],\n });\n }\n }\n\n // Compare nullability\n if (contractColumn.nullable !== schemaColumn.nullable) {\n issues.push({\n kind: 'nullability_mismatch',\n table: tableName,\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 // Compute column status from children (fail > warn > pass)\n const computedColumnStatus = columnChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : columnChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Use computed status if we have children, otherwise use the manually set status\n const finalColumnStatus = columnChildren.length > 0 ? computedColumnStatus : columnStatus;\n\n // Build column node\n const nullableText = contractColumn.nullable ? 'nullable' : 'not nullable';\n const columnTypeDisplay = contractColumn.codecId\n ? `${contractNativeType} (${contractColumn.codecId})`\n : contractNativeType;\n // Collect failure messages from children to create a summary message\n const failureMessages = columnChildren\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 columnMessage =\n finalColumnStatus === 'fail' && failureMessages.length > 0\n ? failureMessages.join('; ')\n : '';\n // Extract code from first child if status indicates an issue\n const columnCode =\n (finalColumnStatus === 'fail' || finalColumnStatus === 'warn') && columnChildren[0]\n ? columnChildren[0].code\n : '';\n columnNodes.push({\n status: finalColumnStatus,\n kind: 'column',\n name: `${columnName}: ${columnTypeDisplay} (${nullableText})`,\n contractPath: columnPath,\n code: columnCode,\n message: columnMessage,\n expected: undefined,\n actual: undefined,\n children: columnChildren,\n });\n }\n\n // Group columns under a \"columns\" header if we have any columns\n if (columnNodes.length > 0) {\n const columnsStatus = columnNodes.some((c) => c.status === 'fail')\n ? 'fail'\n : columnNodes.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n tableChildren.push({\n status: columnsStatus,\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\n // Check for extra columns in strict mode\n if (strict) {\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 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\n // Compare primary key\n if (contractTable.primaryKey) {\n const pkStatus = verifyPrimaryKey(\n contractTable.primaryKey,\n schemaTable.primaryKey,\n tableName,\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 // Extra primary key in strict mode\n issues.push({\n kind: 'extra_primary_key',\n table: tableName,\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 // Compare foreign keys\n const fkStatuses = verifyForeignKeys(\n contractTable.foreignKeys,\n schemaTable.foreignKeys,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...fkStatuses);\n\n // Compare unique constraints\n // Pass schemaIndexes so unique indexes can satisfy unique constraint requirements\n const uniqueStatuses = verifyUniqueConstraints(\n contractTable.uniques,\n schemaTable.uniques,\n schemaTable.indexes,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...uniqueStatuses);\n\n // Compare indexes\n // Pass schemaUniques so unique constraints can satisfy index requirements\n const indexStatuses = verifyIndexes(\n contractTable.indexes,\n schemaTable.indexes,\n schemaTable.uniques,\n tableName,\n tablePath,\n issues,\n strict,\n );\n tableChildren.push(...indexStatuses);\n\n // Build table node\n const tableStatus = tableChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : tableChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n // Collect failure messages from children to create a summary message\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 rootChildren.push({\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\n // Check for extra tables in strict mode\n if (strict) {\n for (const tableName of Object.keys(schemaTables)) {\n if (!contractTables[tableName]) {\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.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 // Validate that all extension packs declared in the contract are present in frameworkComponents\n // This is a configuration integrity check - if the contract was emitted with an extension,\n // that extension must be provided in the current configuration.\n // Note: contract.extensionPacks includes adapter.id and target.id (from extractExtensionIds),\n // so we check for matches as extension, adapter, or target components.\n const contractExtensionPacks = contract.extensionPacks ?? {};\n for (const extensionNamespace of Object.keys(contractExtensionPacks)) {\n const hasComponent = options.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 // Compare component-owned database dependencies (pure, deterministic)\n // Per ADR 154: We do NOT infer dependencies from contract extension packs.\n // Dependencies are only collected from frameworkComponents provided by the CLI.\n const databaseDependencies = collectDependenciesFromFrameworkComponents(\n options.frameworkComponents,\n );\n const dependencyStatuses = verifyDatabaseDependencies(databaseDependencies, schema, issues);\n rootChildren.push(...dependencyStatuses);\n\n // Build root node\n const rootStatus = rootChildren.some((c) => c.status === 'fail')\n ? 'fail'\n : rootChildren.some((c) => c.status === 'warn')\n ? 'warn'\n : 'pass';\n const root: SchemaVerificationNode = {\n status: rootStatus,\n kind: 'contract',\n name: 'contract',\n contractPath: '',\n code: '',\n message: '',\n expected: undefined,\n actual: undefined,\n children: rootChildren,\n };\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 coreHash: contractCoreHash,\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\n/**\n * Type predicate to check if a component has database dependencies with an init array.\n * The familyId check is redundant since TargetBoundComponentDescriptor<'sql', T> already\n * guarantees familyId is 'sql' at the type level, so we don't need runtime checks for it.\n */\nfunction hasDatabaseDependenciesInit<T extends string>(\n component: TargetBoundComponentDescriptor<'sql', T>,\n): component is TargetBoundComponentDescriptor<'sql', T> & {\n readonly databaseDependencies: {\n readonly init: readonly ComponentDatabaseDependency<T>[];\n };\n} {\n if (!('databaseDependencies' in component)) {\n return false;\n }\n const dbDeps = (component as Record<string, unknown>)['databaseDependencies'];\n if (dbDeps === undefined || dbDeps === null || typeof dbDeps !== 'object') {\n return false;\n }\n const depsRecord = dbDeps as Record<string, unknown>;\n const init = depsRecord['init'];\n if (init === undefined || !Array.isArray(init)) {\n return false;\n }\n return true;\n}\n\nfunction collectDependenciesFromFrameworkComponents<T extends string>(\n components: ReadonlyArray<TargetBoundComponentDescriptor<'sql', T>>,\n): ReadonlyArray<ComponentDatabaseDependency<T>> {\n const dependencies: ComponentDatabaseDependency<T>[] = [];\n for (const component of components) {\n if (hasDatabaseDependenciesInit(component)) {\n dependencies.push(...component.databaseDependencies.init);\n }\n }\n return dependencies;\n}\n"],"mappings":"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","names":[]}