@prisma-next/sql-contract 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/factories.d.mts +3 -2
- package/dist/factories.d.mts.map +1 -1
- package/dist/factories.mjs +13 -6
- package/dist/factories.mjs.map +1 -1
- package/dist/index-type-validation.d.mts +1 -1
- package/dist/index-type-validation.mjs +11 -8
- package/dist/index-type-validation.mjs.map +1 -1
- package/dist/{types-B0lbr9cb.d.mts → types-FVBrwvCz.d.mts} +64 -51
- package/dist/types-FVBrwvCz.d.mts.map +1 -0
- package/dist/{types-iqFGDcJp.mjs → types-L8p7B1dP.mjs} +76 -65
- package/dist/types-L8p7B1dP.mjs.map +1 -0
- package/dist/types.d.mts +2 -2
- package/dist/types.mjs +2 -2
- package/dist/validators.d.mts +3 -3
- package/dist/validators.d.mts.map +1 -1
- package/dist/validators.mjs +82 -73
- package/dist/validators.mjs.map +1 -1
- package/package.json +6 -6
- package/src/exports/types.ts +4 -3
- package/src/factories.ts +9 -6
- package/src/index-type-validation.ts +27 -24
- package/src/ir/foreign-key-reference.ts +29 -0
- package/src/ir/foreign-key.ts +21 -14
- package/src/ir/sql-storage.ts +107 -41
- package/src/ir/{sql-unspecified-namespace.ts → sql-unbound-namespace.ts} +11 -7
- package/src/ir/storage-table.ts +3 -5
- package/src/types.ts +5 -4
- package/src/validators.ts +104 -84
- package/dist/types-B0lbr9cb.d.mts.map +0 -1
- package/dist/types-iqFGDcJp.mjs.map +0 -1
- package/src/ir/foreign-key-references.ts +0 -26
package/dist/validators.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.mjs","names":["f"],"sources":["../src/validators.ts"],"sourcesContent":["import { ContractValidationError } from '@prisma-next/contract/contract-validation-error';\nimport type { Contract, ContractField, ContractModel } from '@prisma-next/contract/types';\nimport { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport { type } from 'arktype';\nimport {\n type ForeignKeyInput,\n type ForeignKeyReferencesInput,\n type PrimaryKeyInput,\n type ReferentialAction,\n type SqlModelStorage,\n SqlStorage,\n type SqlStorageInput,\n type StorageTypeInstanceInput,\n type UniqueConstraintInput,\n} from './types';\n\ntype ColumnDefaultLiteral = {\n readonly kind: 'literal';\n readonly value: string | number | boolean | Record<string, unknown> | unknown[] | null;\n};\ntype ColumnDefaultFunction = { readonly kind: 'function'; readonly expression: string };\nconst literalKindSchema = type(\"'literal'\");\nconst functionKindSchema = type(\"'function'\");\nconst generatorKindSchema = type(\"'generator'\");\nconst generatorIdSchema = type('string').narrow((value, ctx) => {\n return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(value) ? true : ctx.mustBe('a flat generator id');\n});\n\nexport const ColumnDefaultLiteralSchema = type.declare<ColumnDefaultLiteral>().type({\n kind: literalKindSchema,\n value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',\n});\n\nexport const ColumnDefaultFunctionSchema = type.declare<ColumnDefaultFunction>().type({\n kind: functionKindSchema,\n expression: 'string',\n});\n\nexport const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);\n\nconst ExecutionMutationDefaultValueSchema = type({\n '+': 'reject',\n kind: generatorKindSchema,\n id: generatorIdSchema,\n 'params?': 'Record<string, unknown>',\n});\n\nconst ExecutionMutationDefaultSchema = type({\n '+': 'reject',\n ref: {\n '+': 'reject',\n table: 'string',\n column: 'string',\n },\n 'onCreate?': ExecutionMutationDefaultValueSchema,\n 'onUpdate?': ExecutionMutationDefaultValueSchema,\n});\n\nconst ExecutionSchema = type({\n '+': 'reject',\n executionHash: 'string',\n mutations: {\n '+': 'reject',\n defaults: ExecutionMutationDefaultSchema.array().readonly(),\n },\n});\n\nconst StorageColumnSchema = type({\n '+': 'reject',\n nativeType: 'string',\n codecId: 'string',\n nullable: 'boolean',\n 'typeParams?': 'Record<string, unknown>',\n 'typeRef?': 'string',\n 'default?': ColumnDefaultSchema,\n}).narrow((col, ctx) => {\n if (col.typeParams !== undefined && col.typeRef !== undefined) {\n return ctx.mustBe('a column with either typeParams or typeRef, not both');\n }\n return true;\n});\n\n/**\n * Codec-triple entry persisted under `storage.types[name]`. Carries an\n * enumerable literal `kind: 'codec-instance'` discriminator so the\n * polymorphic slot dispatch can distinguish codec triples from\n * class-instance kinds (e.g. `'postgres-enum'`) sharing the slot.\n */\nconst StorageTypeInstanceSchema = type\n .declare<StorageTypeInstanceInput & { kind: 'codec-instance' }>()\n .type({\n kind: \"'codec-instance'\",\n codecId: 'string',\n nativeType: 'string',\n typeParams: 'Record<string, unknown>',\n });\n\n/**\n * Polymorphic enum-type entry under `storage.types[name]`. Carries an\n * enumerable literal `kind: 'postgres-enum'` discriminator so the\n * per-target hydration walker can dispatch cleanly back to a typed\n * IR-class instance during `deserializeContract`. The discriminator\n * reflects target-level behaviour (Postgres-native enums versus\n * family-layer codec triples) — not the family abstract altitude alone.\n *\n * The schema literal lives at the family layer today because\n * registry-driven validation for arbitrary slot shapes is not wired\n * yet; once a second polymorphic kind ships through the slot, this\n * structural enumeration can move to the registry-dispatch site and\n * per-target schemas can live in their target packages.\n */\nconst PostgresEnumTypeSchema = type({\n kind: \"'postgres-enum'\",\n name: 'string',\n nativeType: 'string',\n values: type.string.array().readonly(),\n});\n\n/**\n * Family-layer arktype validation enumerates the polymorphic shapes the\n * SQL family ships today (codec-instance + Postgres-enum). Pack-contributed\n * entity types ship a parallel arktype schema entry here when they\n * introduce a new persisted shape; the registry-driven hydration seam at\n * `SqlContractSerializerBase.hydrateStorageTypeEntry` is open, but the\n * family-layer structural validator is closed by design — extension\n * packs cannot inject arbitrary persisted shapes through the slot\n * without their structural shape being known at the family layer.\n *\n * A future refinement is to lift `StorageTypeEntrySchema` toward an\n * `unknown` fallback and move structural diagnostics to the\n * registry-dispatch site at hydration time, earned once a non-enum\n * storage shape needs to flow through the slot without growing another\n * closed union arm here first.\n */\nconst StorageTypeEntrySchema = PostgresEnumTypeSchema.or(StorageTypeInstanceSchema);\n\nconst PrimaryKeySchema = type.declare<PrimaryKeyInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst UniqueConstraintSchema = type.declare<UniqueConstraintInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nexport const IndexSchema = type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n 'type?': 'string',\n 'options?': 'Record<string, unknown>',\n});\n\nexport const ForeignKeyReferencesSchema = type.declare<ForeignKeyReferencesInput>().type({\n table: 'string',\n columns: type.string.array().readonly(),\n});\n\nexport const ReferentialActionSchema = type\n .declare<ReferentialAction>()\n .type(\"'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'\");\n\nexport const ForeignKeySchema = type.declare<ForeignKeyInput>().type({\n columns: type.string.array().readonly(),\n references: ForeignKeyReferencesSchema,\n 'name?': 'string',\n 'onDelete?': ReferentialActionSchema,\n 'onUpdate?': ReferentialActionSchema,\n constraint: 'boolean',\n index: 'boolean',\n});\n\nconst StorageTableSchema = type({\n '+': 'reject',\n columns: type({ '[string]': StorageColumnSchema }),\n 'primaryKey?': PrimaryKeySchema,\n uniques: UniqueConstraintSchema.array().readonly(),\n indexes: IndexSchema.array().readonly(),\n foreignKeys: ForeignKeySchema.array().readonly(),\n});\n\n/**\n * Namespace entry under `storage.namespaces[id]`. SQL contracts honour\n * the framework `Storage.namespaces` invariant from PR1; today every\n * contract binds to the singleton placeholder\n * (`SqlUnspecifiedNamespace.instance`) and the persisted shape carries\n * just the namespace id. Per-target namespace concretions\n * (`PostgresSchema`, `SqliteUnspecifiedDatabase`) can additively grow\n * the persisted shape when they earn their slots.\n */\nconst NamespaceEntrySchema = type({\n id: 'string',\n});\n\nconst StorageSchema = type({\n '+': 'reject',\n storageHash: 'string',\n tables: type({ '[string]': StorageTableSchema }),\n 'types?': type({ '[string]': StorageTypeEntrySchema }),\n 'namespaces?': type({ '[string]': NamespaceEntrySchema }),\n});\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction findDuplicateValue(values: readonly string[]): string | undefined {\n const seen = new Set<string>();\n for (const value of values) {\n if (seen.has(value)) {\n return value;\n }\n seen.add(value);\n }\n return undefined;\n}\n\nfunction isContractFieldType(value: unknown): boolean {\n if (!isPlainRecord(value)) return false;\n const kind = value['kind'];\n if (kind === 'scalar') {\n if (typeof value['codecId'] !== 'string') return false;\n const typeParams = value['typeParams'];\n if (typeParams !== undefined && !isPlainRecord(typeParams)) return false;\n return true;\n }\n if (kind === 'valueObject') {\n return typeof value['name'] === 'string';\n }\n if (kind === 'union') {\n const members = value['members'];\n if (!Array.isArray(members)) return false;\n return members.every((m) => isContractFieldType(m));\n }\n return false;\n}\n\nconst ContractFieldTypeSchema = type('unknown').narrow((value, ctx) =>\n isContractFieldType(value) ? true : ctx.mustBe('scalar, valueObject, or union field type'),\n);\n\nconst ModelFieldSchema = type({\n '+': 'reject',\n nullable: 'boolean',\n type: ContractFieldTypeSchema,\n 'many?': 'true',\n 'dict?': 'true',\n});\n\nconst ModelStorageFieldSchema = type({\n column: 'string',\n 'codecId?': 'string',\n 'nullable?': 'boolean',\n});\n\nconst ModelStorageSchema = type({\n table: 'string',\n fields: type({ '[string]': ModelStorageFieldSchema }),\n});\n\nconst ModelSchema = type({\n storage: ModelStorageSchema,\n 'fields?': type({ '[string]': ModelFieldSchema }),\n 'relations?': type({ '[string]': 'unknown' }),\n 'discriminator?': 'unknown',\n 'variants?': 'unknown',\n 'base?': 'string',\n 'owner?': 'string',\n});\n\nconst ContractMetaSchema = type({\n '[string]': 'unknown',\n});\n\nconst SqlContractSchema = type({\n '+': 'reject',\n target: 'string',\n targetFamily: \"'sql'\",\n 'coreHash?': 'string',\n profileHash: 'string',\n 'capabilities?': 'Record<string, Record<string, boolean>>',\n 'extensionPacks?': 'Record<string, unknown>',\n 'meta?': ContractMetaSchema,\n 'roots?': 'Record<string, string>',\n models: type({ '[string]': ModelSchema }),\n 'valueObjects?': 'Record<string, unknown>',\n storage: StorageSchema,\n 'execution?': ExecutionSchema,\n});\n\n// NOTE: StorageColumnSchema, StorageTableSchema, and StorageSchema use bare type()\n// instead of type.declare<T>().type() because the ColumnDefault union's value field\n// includes bigint | Date (runtime-only types after decoding) which cannot be expressed\n// in Arktype's JSON validation DSL. The `as SqlStorage` cast in validateStorage() bridges\n// the gap between the JSON-safe Arktype output and the runtime TypeScript type.\n\n/**\n * Validates the structural shape of SqlStorage using Arktype.\n *\n * @param value - The storage value to validate\n * @returns The validated storage if structure is valid\n * @throws Error if the storage structure is invalid\n */\nexport function validateStorage(value: unknown): SqlStorage {\n const result = StorageSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Storage validation failed: ${messages}`);\n }\n // The arktype-validated shape matches `SqlStorageInput`\n // structurally. Funnel through the constructor so nested IR fields\n // (`tables`, `types`) are normalised into class instances and the\n // branded `storageHash` is preserved on the returned `SqlStorage`.\n return new SqlStorage(result as SqlStorageInput);\n}\n\nexport function validateModel(value: unknown): unknown {\n const result = ModelSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Model validation failed: ${messages}`);\n }\n return result;\n}\n\n/**\n * Structural arktype validation of an SQL contract envelope. Internal\n * helper for {@link validateSqlContractFully} — exposed only inside\n * this module, since the family seam-of-record is the\n * `SqlContractSerializerBase.deserializeContract` SPI.\n */\nfunction validateSqlContractStructure<T extends Contract<SqlStorage>>(value: unknown): T {\n if (typeof value !== 'object' || value === null) {\n throw new ContractValidationError(\n 'Contract structural validation failed: value must be an object',\n 'structural',\n );\n }\n\n const rawValue = value as { targetFamily?: string };\n if (rawValue.targetFamily !== undefined && rawValue.targetFamily !== 'sql') {\n throw new ContractValidationError(\n `Unsupported target family: ${rawValue.targetFamily}`,\n 'structural',\n );\n }\n\n const contractResult = SqlContractSchema(value);\n\n if (contractResult instanceof type.errors) {\n const messages = contractResult.map((p: { message: string }) => p.message).join('; ');\n throw new ContractValidationError(\n `Contract structural validation failed: ${messages}`,\n 'structural',\n );\n }\n\n // Arktype's inferred output type differs from T due to exactOptionalPropertyTypes\n // and branded hash types — the runtime value is structurally compatible after validation\n return contractResult as unknown as T;\n}\n\n/**\n * Validates semantic constraints on SqlStorage that cannot be expressed in Arktype schemas.\n *\n * Returns an array of human-readable error strings. Empty array = valid.\n *\n * Currently checks:\n * - duplicate named primary key / unique / index / foreign key objects within a table\n * - duplicate unique, index, or foreign key declarations within a table\n * - duplicate columns within primary key / unique / index definitions\n * - nullable columns in primary key definitions\n * - `setNull` referential action on a non-nullable FK column (would fail at runtime)\n * - `setDefault` referential action on a non-nullable FK column without a DEFAULT (would fail at runtime)\n */\nexport function validateStorageSemantics(storage: SqlStorage): string[] {\n const errors: string[] = [];\n\n for (const [tableName, table] of Object.entries(storage.tables)) {\n const namedObjects = new Map<string, string[]>();\n const registerNamedObject = (kind: string, name: string | undefined) => {\n if (!name) return;\n namedObjects.set(name, [...(namedObjects.get(name) ?? []), kind]);\n };\n\n registerNamedObject('primary key', table.primaryKey?.name);\n for (const unique of table.uniques) {\n registerNamedObject('unique constraint', unique.name);\n }\n for (const index of table.indexes) {\n registerNamedObject('index', index.name);\n }\n for (const fk of table.foreignKeys) {\n registerNamedObject('foreign key', fk.name);\n }\n\n for (const [name, kinds] of namedObjects) {\n if (kinds.length > 1) {\n errors.push(\n `Table \"${tableName}\": named object \"${name}\" is declared multiple times (${kinds.join(', ')})`,\n );\n }\n }\n\n if (table.primaryKey) {\n const duplicateColumn = findDuplicateValue(table.primaryKey.columns);\n if (duplicateColumn !== undefined) {\n errors.push(\n `Table \"${tableName}\": primary key contains duplicate column \"${duplicateColumn}\"`,\n );\n }\n\n for (const columnName of table.primaryKey.columns) {\n const column = table.columns[columnName];\n if (column?.nullable === true) {\n errors.push(\n `Table \"${tableName}\": primary key column \"${columnName}\" is nullable; primary key columns must be NOT NULL`,\n );\n }\n }\n }\n\n const seenUniqueDefinitions = new Set<string>();\n for (const unique of table.uniques) {\n const duplicateColumn = findDuplicateValue(unique.columns);\n if (duplicateColumn !== undefined) {\n errors.push(\n `Table \"${tableName}\": unique constraint contains duplicate column \"${duplicateColumn}\"`,\n );\n }\n\n const signature = JSON.stringify({ columns: unique.columns });\n if (seenUniqueDefinitions.has(signature)) {\n errors.push(\n `Table \"${tableName}\": duplicate unique constraint definition on columns [${unique.columns.join(', ')}]`,\n );\n continue;\n }\n seenUniqueDefinitions.add(signature);\n }\n\n const sortOptions = (o: Record<string, unknown> | undefined): Record<string, unknown> | null =>\n o ? Object.fromEntries(Object.entries(o).sort(([a], [b]) => a.localeCompare(b))) : null;\n\n const seenIndexDefinitions = new Set<string>();\n for (const index of table.indexes) {\n const duplicateColumn = findDuplicateValue(index.columns);\n if (duplicateColumn !== undefined) {\n errors.push(`Table \"${tableName}\": index contains duplicate column \"${duplicateColumn}\"`);\n }\n\n const signature = JSON.stringify({\n columns: index.columns,\n type: index.type ?? null,\n options: sortOptions(index.options),\n });\n if (seenIndexDefinitions.has(signature)) {\n errors.push(\n `Table \"${tableName}\": duplicate index definition on columns [${index.columns.join(', ')}]`,\n );\n continue;\n }\n seenIndexDefinitions.add(signature);\n }\n\n const seenForeignKeyDefinitions = new Set<string>();\n for (const fk of table.foreignKeys) {\n const signature = JSON.stringify({\n columns: fk.columns,\n references: fk.references,\n onDelete: fk.onDelete ?? null,\n onUpdate: fk.onUpdate ?? null,\n constraint: fk.constraint,\n index: fk.index,\n });\n if (seenForeignKeyDefinitions.has(signature)) {\n errors.push(\n `Table \"${tableName}\": duplicate foreign key definition on columns [${fk.columns.join(', ')}]`,\n );\n continue;\n }\n seenForeignKeyDefinitions.add(signature);\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.columns) {\n const column = table.columns[colName];\n if (!column) continue;\n\n if (fk.onDelete === 'setNull' && !column.nullable) {\n errors.push(\n `Table \"${tableName}\": onDelete setNull on foreign key column \"${colName}\" which is NOT NULL`,\n );\n }\n if (fk.onUpdate === 'setNull' && !column.nullable) {\n errors.push(\n `Table \"${tableName}\": onUpdate setNull on foreign key column \"${colName}\" which is NOT NULL`,\n );\n }\n if (fk.onDelete === 'setDefault' && !column.nullable && column.default === undefined) {\n errors.push(\n `Table \"${tableName}\": onDelete setDefault on foreign key column \"${colName}\" which is NOT NULL and has no DEFAULT`,\n );\n }\n if (fk.onUpdate === 'setDefault' && !column.nullable && column.default === undefined) {\n errors.push(\n `Table \"${tableName}\": onUpdate setDefault on foreign key column \"${colName}\" which is NOT NULL and has no DEFAULT`,\n );\n }\n }\n }\n }\n\n return errors;\n}\n\n/**\n * SQL storage logical-consistency checks: every model.storage.table\n * resolves to a real table, every model.storage.fields[*].column\n * resolves to a real column, and value-object fields land on JSON-native\n * columns. Throws `ContractValidationError` on the first mismatch.\n */\nexport function validateModelStorageReferences(contract: Contract<SqlStorage>): void {\n const models = contract.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const storageTable = model.storage.table;\n\n const table = contract.storage.tables[storageTable] as\n | (typeof contract.storage.tables)[string]\n | undefined;\n if (!table) {\n throw new ContractValidationError(\n `Model \"${modelName}\" references non-existent table \"${storageTable}\"`,\n 'storage',\n );\n }\n\n const columnNames = new Set(Object.keys(table.columns));\n for (const [fieldName, field] of Object.entries(model.storage.fields)) {\n if (!columnNames.has(field.column)) {\n throw new ContractValidationError(\n `Model \"${modelName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${storageTable}\"`,\n 'storage',\n );\n }\n }\n\n const JSON_NATIVE_TYPES = new Set(['json', 'jsonb']);\n for (const [fieldName, domainField] of Object.entries(model.fields ?? {})) {\n const f = domainField as ContractField;\n if (f.type?.kind !== 'valueObject') continue;\n const storageField = model.storage.fields[fieldName];\n if (!storageField) continue;\n const column = table.columns[storageField.column];\n if (!column) continue;\n if (!JSON_NATIVE_TYPES.has(column.nativeType)) {\n throw new ContractValidationError(\n `Model \"${modelName}\" field \"${fieldName}\" is a value object but storage column \"${storageField.column}\" has nativeType \"${column.nativeType}\" (expected json or jsonb)`,\n 'storage',\n );\n }\n }\n }\n}\n\n/**\n * Cross-table consistency checks for SQL storage: primary key, unique,\n * index, and foreign key column references resolve to real columns;\n * NOT NULL columns don't carry a literal `null` default; FK column\n * counts match their referenced columns. Throws on the first mismatch.\n */\nexport function validateSqlStorageConsistency(contract: Contract<SqlStorage>): void {\n const tableNames = new Set(Object.keys(contract.storage.tables));\n\n for (const [tableName, table] of Object.entries(contract.storage.tables)) {\n const columnNames = new Set(Object.keys(table.columns));\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const colName of unique.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const index of table.indexes) {\n for (const colName of index.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const [colName, column] of Object.entries(table.columns)) {\n if (!column.nullable && column.default?.kind === 'literal' && column.default.value === null) {\n throw new ContractValidationError(\n `Table \"${tableName}\" column \"${colName}\" is NOT NULL but has a literal null default`,\n 'storage',\n );\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n\n if (!tableNames.has(fk.references.table)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.references.table}\"`,\n 'storage',\n );\n }\n\n const referencedTable = contract.storage.tables[fk.references.table];\n if (!referencedTable) continue;\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.references.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw new ContractValidationError(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.references.table}\"`,\n 'storage',\n );\n }\n }\n\n if (fk.columns.length !== fk.references.columns.length) {\n throw new ContractValidationError(\n `Table \"${tableName}\" foreignKey column count (${fk.columns.length}) does not match referenced column count (${fk.references.columns.length})`,\n 'storage',\n );\n }\n }\n }\n}\n\n/**\n * Full SQL contract validation: structural (arktype) +\n * framework-shared domain + SQL storage logical-consistency + SQL\n * storage semantic + model ↔ storage reference checks. Throws\n * `ContractValidationError` on the first failure. Returns the\n * validated flat-data shape; IR class hydration happens in the SPI\n * base on top of this helper.\n */\nexport function validateSqlContractFully<T extends Contract<SqlStorage>>(value: unknown): T {\n const stripped =\n typeof value === 'object' && value !== null\n ? (() => {\n const { schemaVersion: _, _generated: _g, ...rest } = value as Record<string, unknown>;\n return rest;\n })()\n : value;\n const validated = validateSqlContractStructure<T>(stripped);\n validateContractDomain({\n roots: validated.roots,\n models: validated.models,\n ...(validated.valueObjects ? { valueObjects: validated.valueObjects } : {}),\n });\n validateSqlStorageConsistency(validated);\n const semanticErrors = validateStorageSemantics(validated.storage);\n if (semanticErrors.length > 0) {\n throw new ContractValidationError(\n `Contract semantic validation failed: ${semanticErrors.join('; ')}`,\n 'storage',\n );\n }\n validateModelStorageReferences(validated);\n return validated;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validators.mjs","names":["f","referencedTable"],"sources":["../src/validators.ts"],"sourcesContent":["import { ContractValidationError } from '@prisma-next/contract/contract-validation-error';\nimport type { Contract, ContractField, ContractModel } from '@prisma-next/contract/types';\nimport { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport type { Namespace } from '@prisma-next/framework-components/ir';\nimport { type } from 'arktype';\nimport {\n type ForeignKeyInput,\n type ForeignKeyReferenceInput,\n type PrimaryKeyInput,\n type ReferentialAction,\n type SqlModelStorage,\n SqlStorage,\n type SqlStorageInput,\n type StorageTable,\n type StorageTypeInstanceInput,\n type UniqueConstraintInput,\n} from './types';\n\ntype ColumnDefaultLiteral = {\n readonly kind: 'literal';\n readonly value: string | number | boolean | Record<string, unknown> | unknown[] | null;\n};\ntype ColumnDefaultFunction = { readonly kind: 'function'; readonly expression: string };\nconst literalKindSchema = type(\"'literal'\");\nconst functionKindSchema = type(\"'function'\");\nconst generatorKindSchema = type(\"'generator'\");\nconst generatorIdSchema = type('string').narrow((value, ctx) => {\n return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(value) ? true : ctx.mustBe('a flat generator id');\n});\n\nexport const ColumnDefaultLiteralSchema = type.declare<ColumnDefaultLiteral>().type({\n kind: literalKindSchema,\n value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',\n});\n\nexport const ColumnDefaultFunctionSchema = type.declare<ColumnDefaultFunction>().type({\n kind: functionKindSchema,\n expression: 'string',\n});\n\nexport const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);\n\nconst ExecutionMutationDefaultValueSchema = type({\n '+': 'reject',\n kind: generatorKindSchema,\n id: generatorIdSchema,\n 'params?': 'Record<string, unknown>',\n});\n\nconst ExecutionMutationDefaultSchema = type({\n '+': 'reject',\n ref: {\n '+': 'reject',\n table: 'string',\n column: 'string',\n },\n 'onCreate?': ExecutionMutationDefaultValueSchema,\n 'onUpdate?': ExecutionMutationDefaultValueSchema,\n});\n\nconst ExecutionSchema = type({\n '+': 'reject',\n executionHash: 'string',\n mutations: {\n '+': 'reject',\n defaults: ExecutionMutationDefaultSchema.array().readonly(),\n },\n});\n\nconst StorageColumnSchema = type({\n '+': 'reject',\n nativeType: 'string',\n codecId: 'string',\n nullable: 'boolean',\n 'typeParams?': 'Record<string, unknown>',\n 'typeRef?': 'string',\n 'default?': ColumnDefaultSchema,\n}).narrow((col, ctx) => {\n if (col.typeParams !== undefined && col.typeRef !== undefined) {\n return ctx.mustBe('a column with either typeParams or typeRef, not both');\n }\n return true;\n});\n\n/**\n * Codec-triple entry persisted under `storage.types[name]`. Carries an\n * enumerable literal `kind: 'codec-instance'` discriminator so the\n * polymorphic slot dispatch can distinguish codec triples from\n * class-instance kinds (e.g. `'postgres-enum'`) sharing the slot.\n */\nconst StorageTypeInstanceSchema = type\n .declare<StorageTypeInstanceInput & { kind: 'codec-instance' }>()\n .type({\n kind: \"'codec-instance'\",\n codecId: 'string',\n nativeType: 'string',\n typeParams: 'Record<string, unknown>',\n });\n\n/**\n * Postgres native enum entry under `storage.namespaces[namespaceId].types[name]`.\n * Document-scoped `storage.types` carries codec aliases only\n * (`DocumentScopedStorageTypeSchema`).\n */\nconst PostgresEnumTypeSchema = type({\n kind: \"'postgres-enum'\",\n 'name?': 'string',\n 'nativeType?': 'string',\n values: type.string.array().readonly(),\n});\n\n/** Document-scoped `storage.types`: codec triples only. */\nconst DocumentScopedStorageTypeSchema = StorageTypeInstanceSchema;\n\nconst PrimaryKeySchema = type.declare<PrimaryKeyInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nconst UniqueConstraintSchema = type.declare<UniqueConstraintInput>().type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n});\n\nexport const IndexSchema = type({\n columns: type.string.array().readonly(),\n 'name?': 'string',\n 'type?': 'string',\n 'options?': 'Record<string, unknown>',\n});\n\nexport const ForeignKeyReferenceSchema = type.declare<ForeignKeyReferenceInput>().type({\n namespaceId: 'string',\n tableName: 'string',\n columns: type.string.array().readonly(),\n});\n\nexport const ReferentialActionSchema = type\n .declare<ReferentialAction>()\n .type(\"'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'\");\n\nexport const ForeignKeySchema = type.declare<ForeignKeyInput>().type({\n source: ForeignKeyReferenceSchema,\n target: ForeignKeyReferenceSchema,\n 'name?': 'string',\n 'onDelete?': ReferentialActionSchema,\n 'onUpdate?': ReferentialActionSchema,\n constraint: 'boolean',\n index: 'boolean',\n});\n\nconst StorageTableSchema = type({\n '+': 'reject',\n columns: type({ '[string]': StorageColumnSchema }),\n 'primaryKey?': PrimaryKeySchema,\n uniques: UniqueConstraintSchema.array().readonly(),\n indexes: IndexSchema.array().readonly(),\n foreignKeys: ForeignKeySchema.array().readonly(),\n});\n\n/**\n * Namespace entry under `storage.namespaces[id]`. Tables live on each\n * namespace; the unbound sentinel may appear as a plain `{ id }`\n * envelope (normalised to `SqlUnboundNamespace.instance` by\n * {@link SqlStorage}'s constructor) or carry a `tables` map when the\n * late-bound slot holds authored tables.\n */\nconst NamespaceEntrySchema = type({\n '+': 'reject',\n id: 'string',\n 'kind?': 'string',\n 'tables?': type({ '[string]': StorageTableSchema }),\n 'types?': type({ '[string]': PostgresEnumTypeSchema }),\n});\n\nconst StorageSchema = type({\n '+': 'reject',\n storageHash: 'string',\n 'types?': type({ '[string]': DocumentScopedStorageTypeSchema }),\n 'namespaces?': type({ '[string]': NamespaceEntrySchema }),\n});\n\n// SQL-specific namespace walk shape (`tables` is the SQL family's idiom —\n// the framework `Namespace` interface no longer carries it). The wider\n// `object` table value keeps this helper structurally compatible with\n// `SqlNamespace` (whose tables narrow to `StorageTable`) and the JSON\n// envelope variants that lose class identity.\ntype NamespacedStorageWalk = {\n readonly namespaces: Readonly<\n Record<string, Namespace & { readonly tables?: Readonly<Record<string, object>> }>\n >;\n};\n\nfunction eachStorageTable(storage: NamespacedStorageWalk) {\n return Object.entries(storage.namespaces).flatMap(([namespaceId, ns]) =>\n Object.entries(ns.tables ?? {}).map(([tableName, table]) => ({\n namespaceId,\n tableName,\n table,\n })),\n );\n}\n\nfunction findStorageTableByTableName(storage: NamespacedStorageWalk, tableName: string): unknown {\n for (const ns of Object.values(storage.namespaces)) {\n const t = ns.tables?.[tableName];\n if (t !== undefined) {\n return t;\n }\n }\n return undefined;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction findDuplicateValue(values: readonly string[]): string | undefined {\n const seen = new Set<string>();\n for (const value of values) {\n if (seen.has(value)) {\n return value;\n }\n seen.add(value);\n }\n return undefined;\n}\n\nfunction isContractFieldType(value: unknown): boolean {\n if (!isPlainRecord(value)) return false;\n const kind = value['kind'];\n if (kind === 'scalar') {\n if (typeof value['codecId'] !== 'string') return false;\n const typeParams = value['typeParams'];\n if (typeParams !== undefined && !isPlainRecord(typeParams)) return false;\n return true;\n }\n if (kind === 'valueObject') {\n return typeof value['name'] === 'string';\n }\n if (kind === 'union') {\n const members = value['members'];\n if (!Array.isArray(members)) return false;\n return members.every((m) => isContractFieldType(m));\n }\n return false;\n}\n\nconst ContractFieldTypeSchema = type('unknown').narrow((value, ctx) =>\n isContractFieldType(value) ? true : ctx.mustBe('scalar, valueObject, or union field type'),\n);\n\nconst ModelFieldSchema = type({\n '+': 'reject',\n nullable: 'boolean',\n type: ContractFieldTypeSchema,\n 'many?': 'true',\n 'dict?': 'true',\n});\n\nconst ModelStorageFieldSchema = type({\n column: 'string',\n 'codecId?': 'string',\n 'nullable?': 'boolean',\n});\n\nconst ModelStorageSchema = type({\n table: 'string',\n fields: type({ '[string]': ModelStorageFieldSchema }),\n});\n\nconst ModelSchema = type({\n storage: ModelStorageSchema,\n 'fields?': type({ '[string]': ModelFieldSchema }),\n 'relations?': type({ '[string]': 'unknown' }),\n 'discriminator?': 'unknown',\n 'variants?': 'unknown',\n 'base?': 'string',\n 'owner?': 'string',\n});\n\nconst ContractMetaSchema = type({\n '[string]': 'unknown',\n});\n\nconst SqlContractSchema = type({\n '+': 'reject',\n target: 'string',\n targetFamily: \"'sql'\",\n 'coreHash?': 'string',\n profileHash: 'string',\n 'capabilities?': 'Record<string, Record<string, boolean>>',\n 'extensionPacks?': 'Record<string, unknown>',\n 'meta?': ContractMetaSchema,\n 'roots?': 'Record<string, string>',\n models: type({ '[string]': ModelSchema }),\n 'valueObjects?': 'Record<string, unknown>',\n storage: StorageSchema,\n 'execution?': ExecutionSchema,\n});\n\n// NOTE: StorageColumnSchema, StorageTableSchema, and StorageSchema use bare type()\n// instead of type.declare<T>().type() because the ColumnDefault union's value field\n// includes bigint | Date (runtime-only types after decoding) which cannot be expressed\n// in Arktype's JSON validation DSL. The `as SqlStorage` cast in validateStorage() bridges\n// the gap between the JSON-safe Arktype output and the runtime TypeScript type.\n\n/**\n * Validates the structural shape of SqlStorage using Arktype.\n *\n * @param value - The storage value to validate\n * @returns The validated storage if structure is valid\n * @throws Error if the storage structure is invalid\n */\nexport function validateStorage(value: unknown): SqlStorage {\n const result = StorageSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Storage validation failed: ${messages}`);\n }\n // The arktype-validated shape matches `SqlStorageInput`\n // structurally. Funnel through the constructor so nested IR fields\n // (`types`) are normalised into class instances and the\n // branded `storageHash` is preserved on the returned `SqlStorage`.\n return new SqlStorage(result as SqlStorageInput);\n}\n\nexport function validateModel(value: unknown): unknown {\n const result = ModelSchema(value);\n if (result instanceof type.errors) {\n const messages = result.map((p: { message: string }) => p.message).join('; ');\n throw new Error(`Model validation failed: ${messages}`);\n }\n return result;\n}\n\n/**\n * Structural arktype validation of an SQL contract envelope. Internal\n * helper for {@link validateSqlContractFully} — exposed only inside\n * this module, since the family seam-of-record is the\n * `SqlContractSerializerBase.deserializeContract` SPI.\n */\nfunction validateSqlContractStructure<T extends Contract<SqlStorage>>(value: unknown): T {\n if (typeof value !== 'object' || value === null) {\n throw new ContractValidationError(\n 'Contract structural validation failed: value must be an object',\n 'structural',\n );\n }\n\n const rawValue = value as { targetFamily?: string };\n if (rawValue.targetFamily !== undefined && rawValue.targetFamily !== 'sql') {\n throw new ContractValidationError(\n `Unsupported target family: ${rawValue.targetFamily}`,\n 'structural',\n );\n }\n\n const contractResult = SqlContractSchema(value);\n\n if (contractResult instanceof type.errors) {\n const messages = contractResult.map((p: { message: string }) => p.message).join('; ');\n throw new ContractValidationError(\n `Contract structural validation failed: ${messages}`,\n 'structural',\n );\n }\n\n // Arktype's inferred output type differs from T due to exactOptionalPropertyTypes\n // and branded hash types — the runtime value is structurally compatible after validation\n return contractResult as unknown as T;\n}\n\n/**\n * Validates semantic constraints on SqlStorage that cannot be expressed in Arktype schemas.\n *\n * Returns an array of human-readable error strings. Empty array = valid.\n *\n * Currently checks:\n * - duplicate named primary key / unique / index / foreign key objects within a table\n * - duplicate unique, index, or foreign key declarations within a table\n * - duplicate columns within primary key / unique / index definitions\n * - nullable columns in primary key definitions\n * - `setNull` referential action on a non-nullable FK column (would fail at runtime)\n * - `setDefault` referential action on a non-nullable FK column without a DEFAULT (would fail at runtime)\n */\nexport function validateStorageSemantics(storage: SqlStorage): string[] {\n const errors: string[] = [];\n\n for (const { namespaceId, tableName, table: rawTable } of eachStorageTable(storage)) {\n const table = rawTable as StorageTable;\n const namedObjects = new Map<string, string[]>();\n const registerNamedObject = (kind: string, name: string | undefined) => {\n if (!name) return;\n namedObjects.set(name, [...(namedObjects.get(name) ?? []), kind]);\n };\n\n registerNamedObject('primary key', table.primaryKey?.name);\n for (const unique of table.uniques) {\n registerNamedObject('unique constraint', unique.name);\n }\n for (const index of table.indexes) {\n registerNamedObject('index', index.name);\n }\n for (const fk of table.foreignKeys) {\n registerNamedObject('foreign key', fk.name);\n }\n\n for (const [name, kinds] of namedObjects) {\n if (kinds.length > 1) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": named object \"${name}\" is declared multiple times (${kinds.join(', ')})`,\n );\n }\n }\n\n if (table.primaryKey) {\n const duplicateColumn = findDuplicateValue(table.primaryKey.columns);\n if (duplicateColumn !== undefined) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": primary key contains duplicate column \"${duplicateColumn}\"`,\n );\n }\n\n for (const columnName of table.primaryKey.columns) {\n const column = table.columns[columnName];\n if (column?.nullable === true) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": primary key column \"${columnName}\" is nullable; primary key columns must be NOT NULL`,\n );\n }\n }\n }\n\n const seenUniqueDefinitions = new Set<string>();\n for (const unique of table.uniques) {\n const duplicateColumn = findDuplicateValue(unique.columns);\n if (duplicateColumn !== undefined) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": unique constraint contains duplicate column \"${duplicateColumn}\"`,\n );\n }\n\n const signature = JSON.stringify({ columns: unique.columns });\n if (seenUniqueDefinitions.has(signature)) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": duplicate unique constraint definition on columns [${unique.columns.join(', ')}]`,\n );\n continue;\n }\n seenUniqueDefinitions.add(signature);\n }\n\n const sortOptions = (o: Record<string, unknown> | undefined): Record<string, unknown> | null =>\n o ? Object.fromEntries(Object.entries(o).sort(([a], [b]) => a.localeCompare(b))) : null;\n\n const seenIndexDefinitions = new Set<string>();\n for (const index of table.indexes) {\n const duplicateColumn = findDuplicateValue(index.columns);\n if (duplicateColumn !== undefined) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": index contains duplicate column \"${duplicateColumn}\"`,\n );\n }\n\n const signature = JSON.stringify({\n columns: index.columns,\n type: index.type ?? null,\n options: sortOptions(index.options),\n });\n if (seenIndexDefinitions.has(signature)) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": duplicate index definition on columns [${index.columns.join(', ')}]`,\n );\n continue;\n }\n seenIndexDefinitions.add(signature);\n }\n\n const seenForeignKeyDefinitions = new Set<string>();\n for (const fk of table.foreignKeys) {\n const signature = JSON.stringify({\n source: fk.source,\n target: fk.target,\n onDelete: fk.onDelete ?? null,\n onUpdate: fk.onUpdate ?? null,\n constraint: fk.constraint,\n index: fk.index,\n });\n if (seenForeignKeyDefinitions.has(signature)) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": duplicate foreign key definition on columns [${fk.source.columns.join(', ')}]`,\n );\n continue;\n }\n seenForeignKeyDefinitions.add(signature);\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.source.columns) {\n const column = table.columns[colName];\n if (!column) continue;\n\n if (fk.onDelete === 'setNull' && !column.nullable) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": onDelete setNull on foreign key column \"${colName}\" which is NOT NULL`,\n );\n }\n if (fk.onUpdate === 'setNull' && !column.nullable) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": onUpdate setNull on foreign key column \"${colName}\" which is NOT NULL`,\n );\n }\n if (fk.onDelete === 'setDefault' && !column.nullable && column.default === undefined) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": onDelete setDefault on foreign key column \"${colName}\" which is NOT NULL and has no DEFAULT`,\n );\n }\n if (fk.onUpdate === 'setDefault' && !column.nullable && column.default === undefined) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": onUpdate setDefault on foreign key column \"${colName}\" which is NOT NULL and has no DEFAULT`,\n );\n }\n }\n }\n }\n\n return errors;\n}\n\n/**\n * SQL storage logical-consistency checks: every model.storage.table\n * resolves to a real table, every model.storage.fields[*].column\n * resolves to a real column, and value-object fields land on JSON-native\n * columns. Throws `ContractValidationError` on the first mismatch.\n */\nexport function validateModelStorageReferences(contract: Contract<SqlStorage>): void {\n const models = contract.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const storageTable = model.storage.table;\n\n const rawTable = findStorageTableByTableName(contract.storage, storageTable);\n if (rawTable === undefined) {\n throw new ContractValidationError(\n `Model \"${modelName}\" references non-existent table \"${storageTable}\"`,\n 'storage',\n );\n }\n\n const table = rawTable as StorageTable;\n\n const columnNames = new Set(Object.keys(table.columns));\n for (const [fieldName, field] of Object.entries(model.storage.fields)) {\n if (!columnNames.has(field.column)) {\n throw new ContractValidationError(\n `Model \"${modelName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${storageTable}\"`,\n 'storage',\n );\n }\n }\n\n const JSON_NATIVE_TYPES = new Set(['json', 'jsonb']);\n for (const [fieldName, domainField] of Object.entries(model.fields ?? {})) {\n const f = domainField as ContractField;\n if (f.type?.kind !== 'valueObject') continue;\n const storageField = model.storage.fields[fieldName];\n if (!storageField) continue;\n const column = table.columns[storageField.column];\n if (!column) continue;\n if (!JSON_NATIVE_TYPES.has(column.nativeType)) {\n throw new ContractValidationError(\n `Model \"${modelName}\" field \"${fieldName}\" is a value object but storage column \"${storageField.column}\" has nativeType \"${column.nativeType}\" (expected json or jsonb)`,\n 'storage',\n );\n }\n }\n }\n}\n\n/**\n * Cross-table consistency checks for SQL storage: primary key, unique,\n * index, and foreign key column references resolve to real columns;\n * NOT NULL columns don't carry a literal `null` default; FK column\n * counts match their referenced columns. Throws on the first mismatch.\n */\nexport function validateSqlStorageConsistency(contract: Contract<SqlStorage>): void {\n for (const { namespaceId, tableName, table: rawTable } of eachStorageTable(contract.storage)) {\n const table = rawTable as StorageTable;\n const columnNames = new Set(Object.keys(table.columns));\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const colName of unique.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const index of table.indexes) {\n for (const colName of index.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" index references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n }\n\n for (const [colName, column] of Object.entries(table.columns)) {\n if (!column.nullable && column.default?.kind === 'literal' && column.default.value === null) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" column \"${colName}\" is NOT NULL but has a literal null default`,\n 'storage',\n );\n }\n }\n\n for (const fk of table.foreignKeys) {\n if (fk.source.namespaceId !== namespaceId || fk.source.tableName !== tableName) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" contains foreignKey with mismatched source coordinates (${fk.source.namespaceId}.${fk.source.tableName})`,\n 'storage',\n );\n }\n\n for (const colName of fk.source.columns) {\n if (!columnNames.has(colName)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n 'storage',\n );\n }\n }\n\n const targetNamespace = contract.storage.namespaces[fk.target.namespaceId];\n const referencedRaw = targetNamespace?.tables?.[fk.target.tableName];\n if (referencedRaw === undefined) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" foreignKey references non-existent table \"${fk.target.namespaceId}.${fk.target.tableName}\"`,\n 'storage',\n );\n }\n const referencedTable = referencedRaw as StorageTable;\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.target.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.target.tableName}\"`,\n 'storage',\n );\n }\n }\n\n if (fk.source.columns.length !== fk.target.columns.length) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`,\n 'storage',\n );\n }\n }\n }\n}\n\n/**\n * Full SQL contract validation: structural (arktype) +\n * framework-shared domain + SQL storage logical-consistency + SQL\n * storage semantic + model ↔ storage reference checks. Throws\n * `ContractValidationError` on the first failure. Returns the\n * validated flat-data shape; IR class hydration happens in the SPI\n * base on top of this helper.\n */\nexport function validateSqlContractFully<T extends Contract<SqlStorage>>(value: unknown): T {\n const stripped =\n typeof value === 'object' && value !== null\n ? (() => {\n const { schemaVersion: _, _generated: _g, ...rest } = value as Record<string, unknown>;\n return rest;\n })()\n : value;\n const validated = validateSqlContractStructure<T>(stripped);\n validateContractDomain({\n roots: validated.roots,\n models: validated.models,\n ...(validated.valueObjects ? { valueObjects: validated.valueObjects } : {}),\n });\n validateSqlStorageConsistency(validated);\n const semanticErrors = validateStorageSemantics(validated.storage);\n if (semanticErrors.length > 0) {\n throw new ContractValidationError(\n `Contract semantic validation failed: ${semanticErrors.join('; ')}`,\n 'storage',\n );\n }\n validateModelStorageReferences(validated);\n return validated;\n}\n"],"mappings":";;;;;AAuBA,MAAM,oBAAoB,KAAK,YAAY;AAC3C,MAAM,qBAAqB,KAAK,aAAa;AAC7C,MAAM,sBAAsB,KAAK,cAAc;AAC/C,MAAM,oBAAoB,KAAK,SAAS,CAAC,QAAQ,OAAO,QAAQ;CAC9D,OAAO,8BAA8B,KAAK,MAAM,GAAG,OAAO,IAAI,OAAO,sBAAsB;EAC3F;AAEF,MAAa,6BAA6B,KAAK,SAA+B,CAAC,KAAK;CAClF,MAAM;CACN,OAAO;CACR,CAAC;AAEF,MAAa,8BAA8B,KAAK,SAAgC,CAAC,KAAK;CACpF,MAAM;CACN,YAAY;CACb,CAAC;AAEF,MAAa,sBAAsB,2BAA2B,GAAG,4BAA4B;AAE7F,MAAM,sCAAsC,KAAK;CAC/C,KAAK;CACL,MAAM;CACN,IAAI;CACJ,WAAW;CACZ,CAAC;AAaF,MAAM,kBAAkB,KAAK;CAC3B,KAAK;CACL,eAAe;CACf,WAAW;EACT,KAAK;EACL,UAhBmC,KAAK;GAC1C,KAAK;GACL,KAAK;IACH,KAAK;IACL,OAAO;IACP,QAAQ;IACT;GACD,aAAa;GACb,aAAa;GACd,CAO2C,CAAC,OAAO,CAAC,UAAU;EAC5D;CACF,CAAC;AAEF,MAAM,sBAAsB,KAAK;CAC/B,KAAK;CACL,YAAY;CACZ,SAAS;CACT,UAAU;CACV,eAAe;CACf,YAAY;CACZ,YAAY;CACb,CAAC,CAAC,QAAQ,KAAK,QAAQ;CACtB,IAAI,IAAI,eAAe,KAAA,KAAa,IAAI,YAAY,KAAA,GAClD,OAAO,IAAI,OAAO,uDAAuD;CAE3E,OAAO;EACP;;;;;;;AAQF,MAAM,4BAA4B,KAC/B,SAAgE,CAChE,KAAK;CACJ,MAAM;CACN,SAAS;CACT,YAAY;CACZ,YAAY;CACb,CAAC;;;;;;AAOJ,MAAM,yBAAyB,KAAK;CAClC,MAAM;CACN,SAAS;CACT,eAAe;CACf,QAAQ,KAAK,OAAO,OAAO,CAAC,UAAU;CACvC,CAAC;;AAGF,MAAM,kCAAkC;AAExC,MAAM,mBAAmB,KAAK,SAA0B,CAAC,KAAK;CAC5D,SAAS,KAAK,OAAO,OAAO,CAAC,UAAU;CACvC,SAAS;CACV,CAAC;AAEF,MAAM,yBAAyB,KAAK,SAAgC,CAAC,KAAK;CACxE,SAAS,KAAK,OAAO,OAAO,CAAC,UAAU;CACvC,SAAS;CACV,CAAC;AAEF,MAAa,cAAc,KAAK;CAC9B,SAAS,KAAK,OAAO,OAAO,CAAC,UAAU;CACvC,SAAS;CACT,SAAS;CACT,YAAY;CACb,CAAC;AAEF,MAAa,4BAA4B,KAAK,SAAmC,CAAC,KAAK;CACrF,aAAa;CACb,WAAW;CACX,SAAS,KAAK,OAAO,OAAO,CAAC,UAAU;CACxC,CAAC;AAEF,MAAa,0BAA0B,KACpC,SAA4B,CAC5B,KAAK,iEAAiE;AAEzE,MAAa,mBAAmB,KAAK,SAA0B,CAAC,KAAK;CACnE,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,aAAa;CACb,aAAa;CACb,YAAY;CACZ,OAAO;CACR,CAAC;;;;;;;;AAkBF,MAAM,uBAAuB,KAAK;CAChC,KAAK;CACL,IAAI;CACJ,SAAS;CACT,WAAW,KAAK,EAAE,YApBO,KAAK;EAC9B,KAAK;EACL,SAAS,KAAK,EAAE,YAAY,qBAAqB,CAAC;EAClD,eAAe;EACf,SAAS,uBAAuB,OAAO,CAAC,UAAU;EAClD,SAAS,YAAY,OAAO,CAAC,UAAU;EACvC,aAAa,iBAAiB,OAAO,CAAC,UAAU;EACjD,CAaiD,EAAE,CAAC;CACnD,UAAU,KAAK,EAAE,YAAY,wBAAwB,CAAC;CACvD,CAAC;AAEF,MAAM,gBAAgB,KAAK;CACzB,KAAK;CACL,aAAa;CACb,UAAU,KAAK,EAAE,YAAY,iCAAiC,CAAC;CAC/D,eAAe,KAAK,EAAE,YAAY,sBAAsB,CAAC;CAC1D,CAAC;AAaF,SAAS,iBAAiB,SAAgC;CACxD,OAAO,OAAO,QAAQ,QAAQ,WAAW,CAAC,SAAS,CAAC,aAAa,QAC/D,OAAO,QAAQ,GAAG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,YAAY;EAC3D;EACA;EACA;EACD,EAAE,CACJ;;AAGH,SAAS,4BAA4B,SAAgC,WAA4B;CAC/F,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,WAAW,EAAE;EAClD,MAAM,IAAI,GAAG,SAAS;EACtB,IAAI,MAAM,KAAA,GACR,OAAO;;;AAMb,SAAS,cAAc,OAAkD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,mBAAmB,QAA+C;CACzE,MAAM,uBAAO,IAAI,KAAa;CAC9B,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,KAAK,IAAI,MAAM,EACjB,OAAO;EAET,KAAK,IAAI,MAAM;;;AAKnB,SAAS,oBAAoB,OAAyB;CACpD,IAAI,CAAC,cAAc,MAAM,EAAE,OAAO;CAClC,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,UAAU;EACrB,IAAI,OAAO,MAAM,eAAe,UAAU,OAAO;EACjD,MAAM,aAAa,MAAM;EACzB,IAAI,eAAe,KAAA,KAAa,CAAC,cAAc,WAAW,EAAE,OAAO;EACnE,OAAO;;CAET,IAAI,SAAS,eACX,OAAO,OAAO,MAAM,YAAY;CAElC,IAAI,SAAS,SAAS;EACpB,MAAM,UAAU,MAAM;EACtB,IAAI,CAAC,MAAM,QAAQ,QAAQ,EAAE,OAAO;EACpC,OAAO,QAAQ,OAAO,MAAM,oBAAoB,EAAE,CAAC;;CAErD,OAAO;;AAOT,MAAM,mBAAmB,KAAK;CAC5B,KAAK;CACL,UAAU;CACV,MAP8B,KAAK,UAAU,CAAC,QAAQ,OAAO,QAC7D,oBAAoB,MAAM,GAAG,OAAO,IAAI,OAAO,2CAA2C,CAM7D;CAC7B,SAAS;CACT,SAAS;CACV,CAAC;AAaF,MAAM,cAAc,KAAK;CACvB,SANyB,KAAK;EAC9B,OAAO;EACP,QAAQ,KAAK,EAAE,YARe,KAAK;GACnC,QAAQ;GACR,YAAY;GACZ,aAAa;GACd,CAImD,EAAE,CAAC;EACtD,CAG4B;CAC3B,WAAW,KAAK,EAAE,YAAY,kBAAkB,CAAC;CACjD,cAAc,KAAK,EAAE,YAAY,WAAW,CAAC;CAC7C,kBAAkB;CAClB,aAAa;CACb,SAAS;CACT,UAAU;CACX,CAAC;AAMF,MAAM,oBAAoB,KAAK;CAC7B,KAAK;CACL,QAAQ;CACR,cAAc;CACd,aAAa;CACb,aAAa;CACb,iBAAiB;CACjB,mBAAmB;CACnB,SAZyB,KAAK,EAC9B,YAAY,WACb,CAU4B;CAC3B,UAAU;CACV,QAAQ,KAAK,EAAE,YAAY,aAAa,CAAC;CACzC,iBAAiB;CACjB,SAAS;CACT,cAAc;CACf,CAAC;;;;;;;;AAeF,SAAgB,gBAAgB,OAA4B;CAC1D,MAAM,SAAS,cAAc,MAAM;CACnC,IAAI,kBAAkB,KAAK,QAAQ;EACjC,MAAM,WAAW,OAAO,KAAK,MAA2B,EAAE,QAAQ,CAAC,KAAK,KAAK;EAC7E,MAAM,IAAI,MAAM,8BAA8B,WAAW;;CAM3D,OAAO,IAAI,WAAW,OAA0B;;AAGlD,SAAgB,cAAc,OAAyB;CACrD,MAAM,SAAS,YAAY,MAAM;CACjC,IAAI,kBAAkB,KAAK,QAAQ;EACjC,MAAM,WAAW,OAAO,KAAK,MAA2B,EAAE,QAAQ,CAAC,KAAK,KAAK;EAC7E,MAAM,IAAI,MAAM,4BAA4B,WAAW;;CAEzD,OAAO;;;;;;;;AAST,SAAS,6BAA6D,OAAmB;CACvF,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,MAAM,IAAI,wBACR,kEACA,aACD;CAGH,MAAM,WAAW;CACjB,IAAI,SAAS,iBAAiB,KAAA,KAAa,SAAS,iBAAiB,OACnE,MAAM,IAAI,wBACR,8BAA8B,SAAS,gBACvC,aACD;CAGH,MAAM,iBAAiB,kBAAkB,MAAM;CAE/C,IAAI,0BAA0B,KAAK,QAEjC,MAAM,IAAI,wBACR,0CAFe,eAAe,KAAK,MAA2B,EAAE,QAAQ,CAAC,KAAK,KAE5B,IAClD,aACD;CAKH,OAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,yBAAyB,SAA+B;CACtE,MAAM,SAAmB,EAAE;CAE3B,KAAK,MAAM,EAAE,aAAa,WAAW,OAAO,cAAc,iBAAiB,QAAQ,EAAE;EACnF,MAAM,QAAQ;EACd,MAAM,+BAAe,IAAI,KAAuB;EAChD,MAAM,uBAAuB,MAAc,SAA6B;GACtE,IAAI,CAAC,MAAM;GACX,aAAa,IAAI,MAAM,CAAC,GAAI,aAAa,IAAI,KAAK,IAAI,EAAE,EAAG,KAAK,CAAC;;EAGnE,oBAAoB,eAAe,MAAM,YAAY,KAAK;EAC1D,KAAK,MAAM,UAAU,MAAM,SACzB,oBAAoB,qBAAqB,OAAO,KAAK;EAEvD,KAAK,MAAM,SAAS,MAAM,SACxB,oBAAoB,SAAS,MAAM,KAAK;EAE1C,KAAK,MAAM,MAAM,MAAM,aACrB,oBAAoB,eAAe,GAAG,KAAK;EAG7C,KAAK,MAAM,CAAC,MAAM,UAAU,cAC1B,IAAI,MAAM,SAAS,GACjB,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,mBAAmB,KAAK,gCAAgC,MAAM,KAAK,KAAK,CAAC,GACzH;EAIL,IAAI,MAAM,YAAY;GACpB,MAAM,kBAAkB,mBAAmB,MAAM,WAAW,QAAQ;GACpE,IAAI,oBAAoB,KAAA,GACtB,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,4CAA4C,gBAAgB,GAC5G;GAGH,KAAK,MAAM,cAAc,MAAM,WAAW,SAExC,IADe,MAAM,QAAQ,aACjB,aAAa,MACvB,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,yBAAyB,WAAW,qDACpF;;EAKP,MAAM,wCAAwB,IAAI,KAAa;EAC/C,KAAK,MAAM,UAAU,MAAM,SAAS;GAClC,MAAM,kBAAkB,mBAAmB,OAAO,QAAQ;GAC1D,IAAI,oBAAoB,KAAA,GACtB,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,kDAAkD,gBAAgB,GAClH;GAGH,MAAM,YAAY,KAAK,UAAU,EAAE,SAAS,OAAO,SAAS,CAAC;GAC7D,IAAI,sBAAsB,IAAI,UAAU,EAAE;IACxC,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,wDAAwD,OAAO,QAAQ,KAAK,KAAK,CAAC,GAClI;IACD;;GAEF,sBAAsB,IAAI,UAAU;;EAGtC,MAAM,eAAe,MACnB,IAAI,OAAO,YAAY,OAAO,QAAQ,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,GAAG;EAErF,MAAM,uCAAuB,IAAI,KAAa;EAC9C,KAAK,MAAM,SAAS,MAAM,SAAS;GACjC,MAAM,kBAAkB,mBAAmB,MAAM,QAAQ;GACzD,IAAI,oBAAoB,KAAA,GACtB,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,sCAAsC,gBAAgB,GACtG;GAGH,MAAM,YAAY,KAAK,UAAU;IAC/B,SAAS,MAAM;IACf,MAAM,MAAM,QAAQ;IACpB,SAAS,YAAY,MAAM,QAAQ;IACpC,CAAC;GACF,IAAI,qBAAqB,IAAI,UAAU,EAAE;IACvC,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,4CAA4C,MAAM,QAAQ,KAAK,KAAK,CAAC,GACrH;IACD;;GAEF,qBAAqB,IAAI,UAAU;;EAGrC,MAAM,4CAA4B,IAAI,KAAa;EACnD,KAAK,MAAM,MAAM,MAAM,aAAa;GAClC,MAAM,YAAY,KAAK,UAAU;IAC/B,QAAQ,GAAG;IACX,QAAQ,GAAG;IACX,UAAU,GAAG,YAAY;IACzB,UAAU,GAAG,YAAY;IACzB,YAAY,GAAG;IACf,OAAO,GAAG;IACX,CAAC;GACF,IAAI,0BAA0B,IAAI,UAAU,EAAE;IAC5C,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,kDAAkD,GAAG,OAAO,QAAQ,KAAK,KAAK,CAAC,GAC/H;IACD;;GAEF,0BAA0B,IAAI,UAAU;;EAG1C,KAAK,MAAM,MAAM,MAAM,aACrB,KAAK,MAAM,WAAW,GAAG,OAAO,SAAS;GACvC,MAAM,SAAS,MAAM,QAAQ;GAC7B,IAAI,CAAC,QAAQ;GAEb,IAAI,GAAG,aAAa,aAAa,CAAC,OAAO,UACvC,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,6CAA6C,QAAQ,qBACrG;GAEH,IAAI,GAAG,aAAa,aAAa,CAAC,OAAO,UACvC,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,6CAA6C,QAAQ,qBACrG;GAEH,IAAI,GAAG,aAAa,gBAAgB,CAAC,OAAO,YAAY,OAAO,YAAY,KAAA,GACzE,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,gDAAgD,QAAQ,wCACxG;GAEH,IAAI,GAAG,aAAa,gBAAgB,CAAC,OAAO,YAAY,OAAO,YAAY,KAAA,GACzE,OAAO,KACL,cAAc,YAAY,WAAW,UAAU,gDAAgD,QAAQ,wCACxG;;;CAMT,OAAO;;;;;;;;AAST,SAAgB,+BAA+B,UAAsC;CACnF,MAAM,SAAS,SAAS;CACxB,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,OAAO,EAAE;EACvD,MAAM,eAAe,MAAM,QAAQ;EAEnC,MAAM,WAAW,4BAA4B,SAAS,SAAS,aAAa;EAC5E,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,wBACR,UAAU,UAAU,mCAAmC,aAAa,IACpE,UACD;EAGH,MAAM,QAAQ;EAEd,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,QAAQ,CAAC;EACvD,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,QAAQ,OAAO,EACnE,IAAI,CAAC,YAAY,IAAI,MAAM,OAAO,EAChC,MAAM,IAAI,wBACR,UAAU,UAAU,WAAW,UAAU,oCAAoC,MAAM,OAAO,cAAc,aAAa,IACrH,UACD;EAIL,MAAM,oBAAoB,IAAI,IAAI,CAAC,QAAQ,QAAQ,CAAC;EACpD,KAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,MAAM,UAAU,EAAE,CAAC,EAAE;GAEzE,IAAIA,YAAE,MAAM,SAAS,eAAe;GACpC,MAAM,eAAe,MAAM,QAAQ,OAAO;GAC1C,IAAI,CAAC,cAAc;GACnB,MAAM,SAAS,MAAM,QAAQ,aAAa;GAC1C,IAAI,CAAC,QAAQ;GACb,IAAI,CAAC,kBAAkB,IAAI,OAAO,WAAW,EAC3C,MAAM,IAAI,wBACR,UAAU,UAAU,WAAW,UAAU,0CAA0C,aAAa,OAAO,oBAAoB,OAAO,WAAW,6BAC7I,UACD;;;;;;;;;;AAYT,SAAgB,8BAA8B,UAAsC;CAClF,KAAK,MAAM,EAAE,aAAa,WAAW,OAAO,cAAc,iBAAiB,SAAS,QAAQ,EAAE;EAC5F,MAAM,QAAQ;EACd,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,QAAQ,CAAC;EAEvD,IAAI,MAAM;QACH,MAAM,WAAW,MAAM,WAAW,SACrC,IAAI,CAAC,YAAY,IAAI,QAAQ,EAC3B,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,+CAA+C,QAAQ,IACtG,UACD;;EAKP,KAAK,MAAM,UAAU,MAAM,SACzB,KAAK,MAAM,WAAW,OAAO,SAC3B,IAAI,CAAC,YAAY,IAAI,QAAQ,EAC3B,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,sDAAsD,QAAQ,IAC7G,UACD;EAKP,KAAK,MAAM,SAAS,MAAM,SACxB,KAAK,MAAM,WAAW,MAAM,SAC1B,IAAI,CAAC,YAAY,IAAI,QAAQ,EAC3B,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,0CAA0C,QAAQ,IACjG,UACD;EAKP,KAAK,MAAM,CAAC,SAAS,WAAW,OAAO,QAAQ,MAAM,QAAQ,EAC3D,IAAI,CAAC,OAAO,YAAY,OAAO,SAAS,SAAS,aAAa,OAAO,QAAQ,UAAU,MACrF,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,YAAY,QAAQ,+CACnE,UACD;EAIL,KAAK,MAAM,MAAM,MAAM,aAAa;GAClC,IAAI,GAAG,OAAO,gBAAgB,eAAe,GAAG,OAAO,cAAc,WACnE,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,4DAA4D,GAAG,OAAO,YAAY,GAAG,GAAG,OAAO,UAAU,IACxJ,UACD;GAGH,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,YAAY,IAAI,QAAQ,EAC3B,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,+CAA+C,QAAQ,IACtG,UACD;GAKL,MAAM,gBADkB,SAAS,QAAQ,WAAW,GAAG,OAAO,cACvB,SAAS,GAAG,OAAO;GAC1D,IAAI,kBAAkB,KAAA,GACpB,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,8CAA8C,GAAG,OAAO,YAAY,GAAG,GAAG,OAAO,UAAU,IAC1I,UACD;GAGH,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAKC,cAAgB,QAAQ,CAAC;GAC3E,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,sBAAsB,IAAI,QAAQ,EACrC,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,+CAA+C,QAAQ,cAAc,GAAG,OAAO,UAAU,IACxI,UACD;GAIL,IAAI,GAAG,OAAO,QAAQ,WAAW,GAAG,OAAO,QAAQ,QACjD,MAAM,IAAI,wBACR,cAAc,YAAY,WAAW,UAAU,6BAA6B,GAAG,OAAO,QAAQ,OAAO,4CAA4C,GAAG,OAAO,QAAQ,OAAO,IAC1K,UACD;;;;;;;;;;;;AAcT,SAAgB,yBAAyD,OAAmB;CAQ1F,MAAM,YAAY,6BANhB,OAAO,UAAU,YAAY,UAAU,cAC5B;EACL,MAAM,EAAE,eAAe,GAAG,YAAY,IAAI,GAAG,SAAS;EACtD,OAAO;KACL,GACJ,MACqD;CAC3D,uBAAuB;EACrB,OAAO,UAAU;EACjB,QAAQ,UAAU;EAClB,GAAI,UAAU,eAAe,EAAE,cAAc,UAAU,cAAc,GAAG,EAAE;EAC3E,CAAC;CACF,8BAA8B,UAAU;CACxC,MAAM,iBAAiB,yBAAyB,UAAU,QAAQ;CAClE,IAAI,eAAe,SAAS,GAC1B,MAAM,IAAI,wBACR,wCAAwC,eAAe,KAAK,KAAK,IACjE,UACD;CAEH,+BAA+B,UAAU;CACzC,OAAO"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "SQL contract types, validators, and IR factories for Prisma Next",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/contract": "0.
|
|
10
|
-
"@prisma-next/framework-components": "0.
|
|
9
|
+
"@prisma-next/contract": "0.10.0",
|
|
10
|
+
"@prisma-next/framework-components": "0.10.0",
|
|
11
11
|
"arktype": "^2.2.0"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@prisma-next/test-utils": "0.
|
|
15
|
-
"@prisma-next/tsconfig": "0.
|
|
16
|
-
"@prisma-next/tsdown": "0.
|
|
14
|
+
"@prisma-next/test-utils": "0.10.0",
|
|
15
|
+
"@prisma-next/tsconfig": "0.10.0",
|
|
16
|
+
"@prisma-next/tsdown": "0.10.0",
|
|
17
17
|
"tsdown": "0.22.0",
|
|
18
18
|
"typescript": "5.9.3",
|
|
19
19
|
"vitest": "4.1.6"
|
package/src/exports/types.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type {
|
|
|
10
10
|
FieldOutputTypesOf,
|
|
11
11
|
ForeignKeyInput,
|
|
12
12
|
ForeignKeyOptions,
|
|
13
|
-
|
|
13
|
+
ForeignKeyReferenceInput,
|
|
14
14
|
IndexInput,
|
|
15
15
|
PostgresEnumStorageEntry,
|
|
16
16
|
PrimaryKeyInput,
|
|
@@ -23,6 +23,7 @@ export type {
|
|
|
23
23
|
ResolveCodecTypes,
|
|
24
24
|
SqlModelFieldStorage,
|
|
25
25
|
SqlModelStorage,
|
|
26
|
+
SqlNamespaceTablesInput,
|
|
26
27
|
SqlQueryOperationTypes,
|
|
27
28
|
SqlStorageInput,
|
|
28
29
|
SqlStorageTypeEntry,
|
|
@@ -40,7 +41,7 @@ export {
|
|
|
40
41
|
DEFAULT_FK_CONSTRAINT,
|
|
41
42
|
DEFAULT_FK_INDEX,
|
|
42
43
|
ForeignKey,
|
|
43
|
-
|
|
44
|
+
ForeignKeyReference,
|
|
44
45
|
Index,
|
|
45
46
|
isPostgresEnumStorageEntry,
|
|
46
47
|
isStorageTypeInstance,
|
|
@@ -48,7 +49,7 @@ export {
|
|
|
48
49
|
PrimaryKey,
|
|
49
50
|
SqlNode,
|
|
50
51
|
SqlStorage,
|
|
51
|
-
|
|
52
|
+
SqlUnboundNamespace,
|
|
52
53
|
StorageColumn,
|
|
53
54
|
StorageTable,
|
|
54
55
|
toStorageTypeInstance,
|
package/src/factories.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ScalarFieldType } from '@prisma-next/contract/types';
|
|
2
|
+
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
2
3
|
import {
|
|
3
4
|
applyFkDefaults,
|
|
4
5
|
ForeignKey,
|
|
@@ -30,15 +31,17 @@ export function index(...columns: readonly string[]): Index {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
export function fk(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
srcTableName: string,
|
|
35
|
+
srcColumns: readonly string[],
|
|
36
|
+
targetTableName: string,
|
|
37
|
+
targetColumns: readonly string[],
|
|
38
|
+
opts?: ForeignKeyOptions & { constraint?: boolean; index?: boolean; namespaceId?: string },
|
|
37
39
|
): ForeignKey {
|
|
38
40
|
const defaults = applyFkDefaults({ constraint: opts?.constraint, index: opts?.index });
|
|
41
|
+
const namespaceId = opts?.namespaceId ?? UNBOUND_NAMESPACE_ID;
|
|
39
42
|
return new ForeignKey({
|
|
40
|
-
columns,
|
|
41
|
-
|
|
43
|
+
source: { namespaceId, tableName: srcTableName, columns: srcColumns },
|
|
44
|
+
target: { namespaceId, tableName: targetTableName, columns: targetColumns },
|
|
42
45
|
...(opts?.name !== undefined && { name: opts.name }),
|
|
43
46
|
...(opts?.onDelete !== undefined && { onDelete: opts.onDelete }),
|
|
44
47
|
...(opts?.onUpdate !== undefined && { onUpdate: opts.onUpdate }),
|
|
@@ -2,35 +2,38 @@ import { ContractValidationError } from '@prisma-next/contract/contract-validati
|
|
|
2
2
|
import type { Contract } from '@prisma-next/contract/types';
|
|
3
3
|
import { type } from 'arktype';
|
|
4
4
|
import type { IndexTypeRegistry } from './index-types';
|
|
5
|
-
import type { SqlStorage } from './types';
|
|
5
|
+
import type { SqlStorage, StorageTable } from './types';
|
|
6
6
|
|
|
7
7
|
export function validateIndexTypes(
|
|
8
8
|
contract: Contract<SqlStorage>,
|
|
9
9
|
indexTypeRegistry: IndexTypeRegistry,
|
|
10
10
|
): void {
|
|
11
|
-
for (const [
|
|
12
|
-
for (const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
11
|
+
for (const [namespaceId, ns] of Object.entries(contract.storage.namespaces)) {
|
|
12
|
+
for (const [tableName, rawTable] of Object.entries(ns.tables)) {
|
|
13
|
+
const table = rawTable as StorageTable;
|
|
14
|
+
for (const index of table.indexes) {
|
|
15
|
+
if (index.type === undefined && index.options !== undefined) {
|
|
16
|
+
throw new ContractValidationError(
|
|
17
|
+
`Namespace "${namespaceId}" table "${tableName}" index on columns [${index.columns.join(', ')}] has options without a type`,
|
|
18
|
+
'storage',
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
if (index.type === undefined) continue;
|
|
22
|
+
const entry = indexTypeRegistry.get(index.type);
|
|
23
|
+
if (entry === undefined) {
|
|
24
|
+
throw new ContractValidationError(
|
|
25
|
+
`Namespace "${namespaceId}" table "${tableName}" index on columns [${index.columns.join(', ')}] uses unregistered index type "${index.type}"`,
|
|
26
|
+
'storage',
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const optionsValue = index.options ?? {};
|
|
30
|
+
const result = entry.options(optionsValue);
|
|
31
|
+
if (result instanceof type.errors) {
|
|
32
|
+
throw new ContractValidationError(
|
|
33
|
+
`Namespace "${namespaceId}" table "${tableName}" index on columns [${index.columns.join(', ')}] has invalid options for type "${index.type}": ${result.summary}`,
|
|
34
|
+
'storage',
|
|
35
|
+
);
|
|
36
|
+
}
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
2
|
+
import { SqlNode } from './sql-node';
|
|
3
|
+
|
|
4
|
+
export interface ForeignKeyReferenceInput {
|
|
5
|
+
readonly namespaceId: string;
|
|
6
|
+
readonly tableName: string;
|
|
7
|
+
readonly columns: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SQL Contract IR node for one side (source or target) of a foreign-key
|
|
12
|
+
* declaration. Carries the full coordinate: namespace, table, and columns.
|
|
13
|
+
*
|
|
14
|
+
* Use `UNBOUND_NAMESPACE_ID` from `@prisma-next/framework-components/ir`
|
|
15
|
+
* as the sentinel `namespaceId` for single-namespace (unbound) references.
|
|
16
|
+
*/
|
|
17
|
+
export class ForeignKeyReference extends SqlNode {
|
|
18
|
+
readonly namespaceId: string;
|
|
19
|
+
readonly tableName: string;
|
|
20
|
+
readonly columns: readonly string[];
|
|
21
|
+
|
|
22
|
+
constructor(input: ForeignKeyReferenceInput) {
|
|
23
|
+
super();
|
|
24
|
+
this.namespaceId = input.namespaceId;
|
|
25
|
+
this.tableName = input.tableName;
|
|
26
|
+
this.columns = input.columns;
|
|
27
|
+
freezeNode(this);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/ir/foreign-key.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { freezeNode } from '@prisma-next/framework-components/ir';
|
|
2
|
-
import {
|
|
2
|
+
import { ForeignKeyReference, type ForeignKeyReferenceInput } from './foreign-key-reference';
|
|
3
3
|
import { SqlNode } from './sql-node';
|
|
4
4
|
|
|
5
5
|
export type ReferentialAction = 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';
|
|
6
6
|
|
|
7
7
|
export interface ForeignKeyInput {
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
8
|
+
readonly source: ForeignKeyReference | ForeignKeyReferenceInput;
|
|
9
|
+
readonly target: ForeignKeyReference | ForeignKeyReferenceInput;
|
|
10
10
|
readonly name?: string;
|
|
11
11
|
readonly onDelete?: ReferentialAction;
|
|
12
12
|
readonly onUpdate?: ReferentialAction;
|
|
@@ -19,14 +19,18 @@ export interface ForeignKeyInput {
|
|
|
19
19
|
/**
|
|
20
20
|
* SQL Contract IR node for a table-level foreign-key declaration.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* Each FK carries explicit `source` and `target` {@link ForeignKeyReference}
|
|
23
|
+
* coordinates (namespace, table, columns). For single-namespace contracts the
|
|
24
|
+
* sentinel `UNBOUND_NAMESPACE_ID` appears on both sides.
|
|
25
|
+
*
|
|
26
|
+
* The nested references are normalised to {@link ForeignKeyReference}
|
|
27
|
+
* instances inside the constructor so downstream walks see a uniform AST
|
|
28
|
+
* regardless of whether the input was a JSON literal or an already-constructed
|
|
29
|
+
* class instance.
|
|
26
30
|
*/
|
|
27
31
|
export class ForeignKey extends SqlNode {
|
|
28
|
-
readonly
|
|
29
|
-
readonly
|
|
32
|
+
readonly source: ForeignKeyReference;
|
|
33
|
+
readonly target: ForeignKeyReference;
|
|
30
34
|
readonly constraint: boolean;
|
|
31
35
|
readonly index: boolean;
|
|
32
36
|
declare readonly name?: string;
|
|
@@ -35,11 +39,14 @@ export class ForeignKey extends SqlNode {
|
|
|
35
39
|
|
|
36
40
|
constructor(input: ForeignKeyInput) {
|
|
37
41
|
super();
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
this.source =
|
|
43
|
+
input.source instanceof ForeignKeyReference
|
|
44
|
+
? input.source
|
|
45
|
+
: new ForeignKeyReference(input.source);
|
|
46
|
+
this.target =
|
|
47
|
+
input.target instanceof ForeignKeyReference
|
|
48
|
+
? input.target
|
|
49
|
+
: new ForeignKeyReference(input.target);
|
|
43
50
|
this.constraint = input.constraint;
|
|
44
51
|
this.index = input.index;
|
|
45
52
|
if (input.name !== undefined) this.name = input.name;
|