@prisma-next/sql-contract 0.13.0-dev.34 → 0.13.0-dev.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{types-B7kJ6S7m.mjs → entity-kinds-Cl36zL5j.mjs} +119 -195
  2. package/dist/entity-kinds-Cl36zL5j.mjs.map +1 -0
  3. package/dist/entity-kinds.d.mts +18 -0
  4. package/dist/entity-kinds.d.mts.map +1 -0
  5. package/dist/entity-kinds.mjs +2 -0
  6. package/dist/factories.d.mts +2 -2
  7. package/dist/factories.mjs +2 -1
  8. package/dist/factories.mjs.map +1 -1
  9. package/dist/index-type-validation.d.mts +1 -1
  10. package/dist/index-type-validation.mjs +1 -1
  11. package/dist/resolve-storage-table.d.mts +2 -1
  12. package/dist/resolve-storage-table.d.mts.map +1 -1
  13. package/dist/sql-storage-Dga0jwP2.d.mts +128 -0
  14. package/dist/sql-storage-Dga0jwP2.d.mts.map +1 -0
  15. package/dist/{sql-storage-BCLmt-nS.d.mts → storage-value-set-WnYsIFM8.d.mts} +3 -125
  16. package/dist/storage-value-set-WnYsIFM8.d.mts.map +1 -0
  17. package/dist/types-B-eiQXff.mjs +191 -0
  18. package/dist/types-B-eiQXff.mjs.map +1 -0
  19. package/dist/{types-D2oSAmdy.d.mts → types-B1N8w0I2.d.mts} +3 -2
  20. package/dist/types-B1N8w0I2.d.mts.map +1 -0
  21. package/dist/types.d.mts +3 -2
  22. package/dist/types.mjs +2 -1
  23. package/dist/validators.d.mts +65 -31
  24. package/dist/validators.d.mts.map +1 -1
  25. package/dist/validators.mjs +30 -137
  26. package/dist/validators.mjs.map +1 -1
  27. package/package.json +8 -7
  28. package/src/entity-kinds.ts +45 -0
  29. package/src/exports/entity-kinds.ts +5 -0
  30. package/src/ir/build-sql-namespace.ts +11 -34
  31. package/src/ir/storage-entry-schemas.ts +128 -0
  32. package/src/validators.ts +50 -172
  33. package/dist/sql-storage-BCLmt-nS.d.mts.map +0 -1
  34. package/dist/types-B7kJ6S7m.mjs.map +0 -1
  35. package/dist/types-D2oSAmdy.d.mts.map +0 -1
@@ -1,32 +1,21 @@
1
- import { b as SqlUnboundNamespace, i as SqlStorage, l as buildSqlNamespaceMap } from "./types-B7kJ6S7m.mjs";
2
- import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
3
- import { blindCast, castAs } from "@prisma-next/utils/casts";
4
- import { ifDefined } from "@prisma-next/utils/defined";
1
+ import { C as StorageTableSchema, S as ReferentialActionSchema, _ as ColumnDefaultSchema, b as ForeignKeySourceSchema, g as ColumnDefaultLiteralSchema, h as ColumnDefaultFunctionSchema, m as CheckConstraintSchema, t as composeSqlEntityKinds, v as ForeignKeyReferenceSchema, w as StorageValueSetSchema, x as IndexSchema, y as ForeignKeySchema } from "./entity-kinds-Cl36zL5j.mjs";
2
+ import { i as SqlStorage, l as buildSqlNamespaceMap, u as SqlUnboundNamespace } from "./types-B-eiQXff.mjs";
3
+ import { type } from "arktype";
4
+ import { UNBOUND_NAMESPACE_ID, isPlainRecord } from "@prisma-next/framework-components/ir";
5
5
  import { CrossReferenceSchema } from "@prisma-next/contract/types";
6
+ import { blindCast } from "@prisma-next/utils/casts";
6
7
  import { ContractValidationError } from "@prisma-next/contract/contract-validation-error";
7
8
  import { validateContractDomain } from "@prisma-next/contract/validate-domain";
8
- import { type } from "arktype";
9
+ import { ifDefined } from "@prisma-next/utils/defined";
9
10
  //#region src/validators.ts
10
- const literalKindSchema = type("'literal'");
11
- const functionKindSchema = type("'function'");
12
11
  const generatorKindSchema = type("'generator'");
13
12
  const ControlPolicySchema = type("'managed' | 'tolerated' | 'external' | 'observed'");
14
- const generatorIdSchema = type("string").narrow((value, ctx) => {
15
- return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(value) ? true : ctx.mustBe("a flat generator id");
16
- });
17
- const ColumnDefaultLiteralSchema = type.declare().type({
18
- kind: literalKindSchema,
19
- value: "string | number | boolean | null | unknown[] | Record<string, unknown>"
20
- });
21
- const ColumnDefaultFunctionSchema = type.declare().type({
22
- kind: functionKindSchema,
23
- expression: "string"
24
- });
25
- const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);
26
13
  const ExecutionMutationDefaultValueSchema = type({
27
14
  "+": "reject",
28
15
  kind: generatorKindSchema,
29
- id: generatorIdSchema,
16
+ id: type("string").narrow((value, ctx) => {
17
+ return /^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(value) ? true : ctx.mustBe("a flat generator id");
18
+ }),
30
19
  "params?": "Record<string, unknown>"
31
20
  });
32
21
  const ExecutionSchema = type({
@@ -46,13 +35,6 @@ const ExecutionSchema = type({
46
35
  }).array().readonly()
47
36
  }
48
37
  });
49
- const StorageValueSetRefSchema = type({
50
- plane: "'storage'",
51
- namespaceId: "string",
52
- entityKind: "'valueSet'",
53
- entityName: "string",
54
- "spaceId?": "string"
55
- });
56
38
  const DomainEnumRefSchema = type({
57
39
  plane: "'domain'",
58
40
  namespaceId: "string",
@@ -60,20 +42,6 @@ const DomainEnumRefSchema = type({
60
42
  entityName: "string",
61
43
  "spaceId?": "string"
62
44
  });
63
- const StorageColumnSchema = type({
64
- "+": "reject",
65
- nativeType: "string",
66
- codecId: "string",
67
- nullable: "boolean",
68
- "typeParams?": "Record<string, unknown>",
69
- "typeRef?": "string",
70
- "default?": ColumnDefaultSchema,
71
- "control?": ControlPolicySchema,
72
- "valueSet?": StorageValueSetRefSchema
73
- }).narrow((col, ctx) => {
74
- if (col.typeParams !== void 0 && col.typeRef !== void 0) return ctx.mustBe("a column with either typeParams or typeRef, not both");
75
- return true;
76
- });
77
45
  /** Document-scoped `storage.types`: codec triples only. */
78
46
  const DocumentScopedStorageTypeSchema = type.declare().type({
79
47
  kind: "'codec-instance'",
@@ -82,15 +50,6 @@ const DocumentScopedStorageTypeSchema = type.declare().type({
82
50
  "typeParams?": "Record<string, unknown>"
83
51
  });
84
52
  /**
85
- * Storage value-set entry under `storage.namespaces[id].entries.valueSet[name]`.
86
- * Carries a `kind: 'valueSet'` discriminator (enumerable, survives JSON) and an
87
- * ordered `values` array of codec-encoded permitted values.
88
- */
89
- const StorageValueSetSchema = type({
90
- kind: "'valueSet'",
91
- values: type("string | number | boolean | null | unknown[] | Record<string, unknown>").array().readonly()
92
- });
93
- /**
94
53
  * Domain enum entry under `domain.namespaces[id].enum[name]`.
95
54
  * Carries the codec id and an ordered `members` array of `{name, value}` pairs.
96
55
  */
@@ -102,86 +61,25 @@ const ContractEnumSchema = type({
102
61
  value: "string | number | boolean | null | unknown[] | Record<string, unknown>"
103
62
  }).array().readonly()
104
63
  });
105
- const PrimaryKeySchema = type.declare().type({
106
- columns: type.string.array().readonly(),
107
- "name?": "string"
108
- });
109
- const UniqueConstraintSchema = type.declare().type({
110
- columns: type.string.array().readonly(),
111
- "name?": "string"
112
- });
113
- const IndexSchema = type({
114
- columns: type.string.array().readonly(),
115
- "name?": "string",
116
- "type?": "string",
117
- "options?": "Record<string, unknown>"
118
- });
119
- const ForeignKeyReferenceSchema = type({
120
- "+": "reject",
121
- namespaceId: "string",
122
- tableName: "string",
123
- columns: type.string.array().readonly(),
124
- "spaceId?": "string"
125
- });
126
- const ForeignKeySourceSchema = type({
127
- "+": "reject",
128
- namespaceId: "string",
129
- tableName: "string",
130
- columns: type.string.array().readonly()
131
- });
132
- const ReferentialActionSchema = type.declare().type("'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault'");
133
- const ForeignKeySchema = type.declare().type({
134
- source: ForeignKeySourceSchema,
135
- target: ForeignKeyReferenceSchema,
136
- "name?": "string",
137
- "onDelete?": ReferentialActionSchema,
138
- "onUpdate?": ReferentialActionSchema,
139
- constraint: "boolean",
140
- index: "boolean"
141
- });
142
- const CheckConstraintSchema = type({
143
- "+": "reject",
144
- name: "string",
145
- column: "string",
146
- valueSet: StorageValueSetRefSchema
147
- });
148
- const StorageTableSchema = type({
149
- "+": "reject",
150
- columns: type({ "[string]": StorageColumnSchema }),
151
- "primaryKey?": PrimaryKeySchema,
152
- uniques: UniqueConstraintSchema.array().readonly(),
153
- indexes: IndexSchema.array().readonly(),
154
- foreignKeys: ForeignKeySchema.array().readonly(),
155
- "control?": ControlPolicySchema,
156
- "checks?": CheckConstraintSchema.array().readonly()
157
- });
158
64
  /**
159
- * Composes the single entry-validator registry consulted during
160
- * structural validation. SQL core registers its own kinds (`'table'`,
161
- * `'valueSet'`) into the same registry targets extend — there is no
162
- * separate built-in fallback tier. Target packs pass their contributed
163
- * kinds via `packSchemas`.
65
+ * Derives a schema map from a descriptor map: maps each kind's key to its
66
+ * `schema` field. Used by validation functions to validate entries.
164
67
  */
165
- function createSqlEntrySchemaRegistry(packSchemas) {
166
- const registry = new Map([["table", castAs(StorageTableSchema)], ["valueSet", castAs(StorageValueSetSchema)]]);
167
- if (packSchemas !== void 0) for (const [kind, schema] of packSchemas) {
168
- if (registry.has(kind)) throw new Error(`createSqlEntrySchemaRegistry: pack schema "${kind}" collides with a core kind — pack schemas cannot override "table" or "valueSet"`);
169
- registry.set(kind, schema);
170
- }
171
- return registry;
68
+ function schemaViewOf(kinds) {
69
+ return new Map([...kinds].map(([k, d]) => [k, d.schema]));
172
70
  }
71
+ const DEFAULT_SQL_KINDS = composeSqlEntityKinds();
173
72
  /**
174
73
  * Builds the per-namespace entry schema for `storage.namespaces[id]`.
175
74
  *
176
- * Validation is registry-driven: the `registry` parameter maps each
177
- * entries key to an arktype schema that validates a single inner-map
178
- * value for that kind. Compose the registry with
179
- * {@link createSqlEntrySchemaRegistry} SQL core's kinds and pack
180
- * contributions live in the same map. An unregistered key fails
181
- * validation naming the kind and the namespace id, so validation fails
182
- * closed.
75
+ * Validation is descriptor-driven: the `kinds` map carries both the schema
76
+ * (used here for structural validation) and the construct function (used at
77
+ * hydration time). An unregistered key fails validation naming the kind and
78
+ * the namespace id, so validation fails closed.
183
79
  */
184
- function createNamespaceEntrySchema(registry) {
80
+ function createNamespaceEntrySchema(kinds) {
81
+ const schemas = schemaViewOf(kinds);
82
+ const knownKinds = new Set(kinds.keys());
185
83
  return type({
186
84
  "+": "reject",
187
85
  id: "string",
@@ -190,9 +88,9 @@ function createNamespaceEntrySchema(registry) {
190
88
  }).narrow((ns, ctx) => {
191
89
  if (!isPlainRecord(ns.entries)) return ctx.mustBe("an entries object");
192
90
  for (const [key, innerMap] of Object.entries(ns.entries)) {
193
- const entrySchema = registry.get(key);
194
- if (entrySchema === void 0) return ctx.reject({ expected: `entries key "${key}" in namespace "${ns.id}" is not a registered entity kind` });
91
+ if (!knownKinds.has(key)) return ctx.reject({ expected: `entries key "${key}" in namespace "${ns.id}" is not a registered entity kind` });
195
92
  if (!isPlainRecord(innerMap)) return ctx.reject({ expected: `entries["${key}"] in namespace "${ns.id}" must be an object` });
93
+ const entrySchema = blindCast(schemas.get(key));
196
94
  for (const [, value] of Object.entries(innerMap)) {
197
95
  const parsed = entrySchema(value);
198
96
  if (parsed instanceof type.errors) return ctx.reject({ expected: parsed.summary });
@@ -207,8 +105,8 @@ function createNamespaceEntrySchema(registry) {
207
105
  * document-scoped `storage.types` field (codec triples only) and the
208
106
  * storage hash stay family-shared.
209
107
  */
210
- function createSqlStorageSchema(registry) {
211
- const namespaceEntry = createNamespaceEntrySchema(registry);
108
+ function createSqlStorageSchema(kinds) {
109
+ const namespaceEntry = createNamespaceEntrySchema(kinds);
212
110
  return type({
213
111
  "+": "reject",
214
112
  storageHash: "string",
@@ -216,7 +114,7 @@ function createSqlStorageSchema(registry) {
216
114
  "namespaces?": type({ "[string]": namespaceEntry })
217
115
  });
218
116
  }
219
- const StorageSchema = createSqlStorageSchema(createSqlEntrySchemaRegistry());
117
+ const StorageSchema = createSqlStorageSchema(DEFAULT_SQL_KINDS);
220
118
  function eachStorageTable(storage) {
221
119
  return Object.entries(storage.namespaces).flatMap(([namespaceId, ns]) => Object.entries(ns.entries["table"] ?? {}).map(([tableName, table]) => ({
222
120
  namespaceId,
@@ -224,11 +122,6 @@ function eachStorageTable(storage) {
224
122
  table
225
123
  })));
226
124
  }
227
- function isPlainRecord(value) {
228
- if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
229
- const proto = Object.getPrototypeOf(value);
230
- return proto === Object.prototype || proto === null;
231
- }
232
125
  function findDuplicateValue(values) {
233
126
  const seen = /* @__PURE__ */ new Set();
234
127
  for (const value of values) {
@@ -318,8 +211,8 @@ const ContractMetaSchema = type({ "[string]": "unknown" });
318
211
  * pack contributions through {@link createSqlStorageSchema}; the rest
319
212
  * of the contract envelope is family-shared.
320
213
  */
321
- function createSqlContractSchema(registry) {
322
- const storage = createSqlStorageSchema(registry);
214
+ function createSqlContractSchema(kinds) {
215
+ const storage = createSqlStorageSchema(kinds);
323
216
  return type({
324
217
  "+": "reject",
325
218
  target: "string",
@@ -340,7 +233,7 @@ function createSqlContractSchema(registry) {
340
233
  "execution?": ExecutionSchema
341
234
  });
342
235
  }
343
- const SqlContractSchema = createSqlContractSchema(createSqlEntrySchemaRegistry());
236
+ const SqlContractSchema = createSqlContractSchema(DEFAULT_SQL_KINDS);
344
237
  /**
345
238
  * Validates the structural shape of SqlStorage using Arktype.
346
239
  *
@@ -572,6 +465,6 @@ function validateSqlContractFully(value, options) {
572
465
  return validated;
573
466
  }
574
467
  //#endregion
575
- export { CheckConstraintSchema, ColumnDefaultFunctionSchema, ColumnDefaultLiteralSchema, ColumnDefaultSchema, ContractEnumSchema, ForeignKeyReferenceSchema, ForeignKeySchema, ForeignKeySourceSchema, IndexSchema, ReferentialActionSchema, StorageValueSetSchema, createNamespaceEntrySchema, createSqlContractSchema, createSqlEntrySchemaRegistry, createSqlStorageSchema, validateModel, validateModelStorageReferences, validateSqlContractFully, validateSqlStorageConsistency, validateStorage, validateStorageSemantics };
468
+ export { CheckConstraintSchema, ColumnDefaultFunctionSchema, ColumnDefaultLiteralSchema, ColumnDefaultSchema, ContractEnumSchema, ForeignKeyReferenceSchema, ForeignKeySchema, ForeignKeySourceSchema, IndexSchema, ReferentialActionSchema, StorageTableSchema, StorageValueSetSchema, createNamespaceEntrySchema, createSqlContractSchema, createSqlStorageSchema, validateModel, validateModelStorageReferences, validateSqlContractFully, validateSqlStorageConsistency, validateStorage, validateStorageSemantics };
576
469
 
577
470
  //# sourceMappingURL=validators.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators.mjs","names":["f","referencedTable"],"sources":["../src/validators.ts"],"sourcesContent":["import { ContractValidationError } from '@prisma-next/contract/contract-validation-error';\nimport {\n type Contract,\n type ContractField,\n type ContractModel,\n CrossReferenceSchema,\n} from '@prisma-next/contract/types';\nimport { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport { type Namespace, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { blindCast, castAs } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { type Type, type } from 'arktype';\nimport { buildSqlNamespaceMap } from './ir/build-sql-namespace';\nimport { SqlUnboundNamespace } from './ir/sql-unbound-namespace';\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 ControlPolicySchema = type(\"'managed' | 'tolerated' | 'external' | 'observed'\");\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 StorageValueSetRefSchema = type({\n plane: \"'storage'\",\n namespaceId: 'string',\n entityKind: \"'valueSet'\",\n entityName: 'string',\n 'spaceId?': 'string',\n});\n\nconst DomainEnumRefSchema = type({\n plane: \"'domain'\",\n namespaceId: 'string',\n entityKind: \"'enum'\",\n entityName: 'string',\n 'spaceId?': 'string',\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 'control?': ControlPolicySchema,\n 'valueSet?': StorageValueSetRefSchema,\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.\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/** Document-scoped `storage.types`: codec triples only. */\nconst DocumentScopedStorageTypeSchema = StorageTypeInstanceSchema;\n\n/**\n * Storage value-set entry under `storage.namespaces[id].entries.valueSet[name]`.\n * Carries a `kind: 'valueSet'` discriminator (enumerable, survives JSON) and an\n * ordered `values` array of codec-encoded permitted values.\n */\nexport const StorageValueSetSchema = type({\n kind: \"'valueSet'\",\n values: type('string | number | boolean | null | unknown[] | Record<string, unknown>')\n .array()\n .readonly(),\n});\n\n/**\n * Domain enum entry under `domain.namespaces[id].enum[name]`.\n * Carries the codec id and an ordered `members` array of `{name, value}` pairs.\n */\nexport const ContractEnumSchema = type({\n '+': 'reject',\n codecId: 'string',\n members: type({\n name: 'string',\n value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',\n })\n .array()\n .readonly(),\n});\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({\n '+': 'reject',\n namespaceId: 'string',\n tableName: 'string',\n columns: type.string.array().readonly(),\n 'spaceId?': 'string',\n}) satisfies Type<ForeignKeyReferenceInput>;\n\nexport const ForeignKeySourceSchema = type({\n '+': 'reject',\n namespaceId: 'string',\n tableName: 'string',\n columns: type.string.array().readonly(),\n}) satisfies Type<ForeignKeyReferenceInput>;\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: ForeignKeySourceSchema,\n target: ForeignKeyReferenceSchema,\n 'name?': 'string',\n 'onDelete?': ReferentialActionSchema,\n 'onUpdate?': ReferentialActionSchema,\n constraint: 'boolean',\n index: 'boolean',\n});\n\nexport const CheckConstraintSchema = type({\n '+': 'reject',\n name: 'string',\n column: 'string',\n valueSet: StorageValueSetRefSchema,\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 'control?': ControlPolicySchema,\n 'checks?': CheckConstraintSchema.array().readonly(),\n});\n\n/**\n * Composes the single entry-validator registry consulted during\n * structural validation. SQL core registers its own kinds (`'table'`,\n * `'valueSet'`) into the same registry targets extend — there is no\n * separate built-in fallback tier. Target packs pass their contributed\n * kinds via `packSchemas`.\n */\nexport function createSqlEntrySchemaRegistry(\n packSchemas?: ReadonlyMap<string, Type<unknown>>,\n): ReadonlyMap<string, Type<unknown>> {\n const registry = new Map<string, Type<unknown>>([\n ['table', castAs<Type<unknown>>(StorageTableSchema)],\n ['valueSet', castAs<Type<unknown>>(StorageValueSetSchema)],\n ]);\n if (packSchemas !== undefined) {\n for (const [kind, schema] of packSchemas) {\n if (registry.has(kind)) {\n throw new Error(\n `createSqlEntrySchemaRegistry: pack schema \"${kind}\" collides with a core kind — pack schemas cannot override \"table\" or \"valueSet\"`,\n );\n }\n registry.set(kind, schema);\n }\n }\n return registry;\n}\n\n/**\n * Builds the per-namespace entry schema for `storage.namespaces[id]`.\n *\n * Validation is registry-driven: the `registry` parameter maps each\n * entries key to an arktype schema that validates a single inner-map\n * value for that kind. Compose the registry with\n * {@link createSqlEntrySchemaRegistry} — SQL core's kinds and pack\n * contributions live in the same map. An unregistered key fails\n * validation naming the kind and the namespace id, so validation fails\n * closed.\n */\nexport function createNamespaceEntrySchema(\n registry: ReadonlyMap<string, Type<unknown>>,\n): Type<unknown> {\n return type({\n '+': 'reject',\n id: 'string',\n 'kind?': 'string',\n entries: 'object',\n }).narrow((ns, ctx) => {\n if (!isPlainRecord(ns.entries)) {\n return ctx.mustBe('an entries object');\n }\n for (const [key, innerMap] of Object.entries(ns.entries)) {\n const entrySchema = registry.get(key);\n if (entrySchema === undefined) {\n return ctx.reject({\n expected: `entries key \"${key}\" in namespace \"${ns.id}\" is not a registered entity kind`,\n });\n }\n if (!isPlainRecord(innerMap)) {\n return ctx.reject({\n expected: `entries[\"${key}\"] in namespace \"${ns.id}\" must be an object`,\n });\n }\n for (const [, value] of Object.entries(innerMap)) {\n const parsed = entrySchema(value);\n if (parsed instanceof type.errors) {\n return ctx.reject({ expected: parsed.summary });\n }\n }\n }\n return true;\n }) as Type<unknown>;\n}\n\n/**\n * Builds the storage schema. Pack contributions reach the per-namespace\n * entry shape through {@link createNamespaceEntrySchema}; the\n * document-scoped `storage.types` field (codec triples only) and the\n * storage hash stay family-shared.\n */\nexport function createSqlStorageSchema(\n registry: ReadonlyMap<string, Type<unknown>>,\n): Type<unknown> {\n const namespaceEntry = createNamespaceEntrySchema(registry);\n return type({\n '+': 'reject',\n storageHash: 'string',\n 'types?': type({ '[string]': DocumentScopedStorageTypeSchema }),\n // `__unbound__` is NOT required here: cross-namespace contracts can\n // declare only named namespaces (see cross-namespace FK fixtures). The\n // `__unbound__` brand on `SqlStorageInput['namespaces']` is kept sound at\n // construction time by injecting the unbound singleton when absent\n // (see `validateStorage` / `hydrateSqlStorage`), not by structural require.\n 'namespaces?': type({ '[string]': namespaceEntry }),\n }) as Type<unknown>;\n}\n\nconst StorageSchema = createSqlStorageSchema(createSqlEntrySchemaRegistry());\n\ntype NamespacedStorageWalk = {\n readonly namespaces: Readonly<\n Record<\n string,\n Namespace & { readonly entries: Readonly<Record<string, Readonly<Record<string, unknown>>>> }\n >\n >;\n};\n\nfunction eachStorageTable(storage: NamespacedStorageWalk) {\n return Object.entries(storage.namespaces).flatMap(([namespaceId, ns]) =>\n Object.entries(ns.entries['table'] ?? {}).map(([tableName, table]) => ({\n namespaceId,\n tableName,\n table,\n })),\n );\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\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 'valueSet?': DomainEnumRefSchema,\n});\n\nconst ModelStorageFieldSchema = type({\n column: 'string',\n 'codecId?': 'string',\n 'nullable?': 'boolean',\n});\n\nconst ModelStorageSchema = type({\n table: 'string',\n namespaceId: 'string',\n fields: type({ '[string]': ModelStorageFieldSchema }),\n});\n\nconst ContractRelationThroughSchema = type({\n '+': 'reject',\n table: 'string',\n namespaceId: 'string',\n parentColumns: type.string.array().readonly(),\n childColumns: type.string.array().readonly(),\n targetColumns: type.string.array().readonly(),\n});\n\nconst ContractRelationOnSchema = type({\n '+': 'reject',\n localFields: type.string.array().readonly(),\n targetFields: type.string.array().readonly(),\n});\n\nconst ContractManyToManyRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'N:M'\",\n on: ContractRelationOnSchema,\n through: ContractRelationThroughSchema,\n});\n\nconst ContractNonJunctionRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'1:1' | '1:N' | 'N:1'\",\n on: ContractRelationOnSchema,\n});\n\nconst ContractReferenceRelationSchema = ContractManyToManyRelationSchema.or(\n ContractNonJunctionRelationSchema,\n);\n\nconst ContractEmbedRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'1:1' | '1:N'\",\n});\n\nconst ContractRelationSchema = ContractReferenceRelationSchema.or(ContractEmbedRelationSchema);\n\nconst ModelSchema = type({\n storage: ModelStorageSchema,\n 'fields?': type({ '[string]': ModelFieldSchema }),\n 'relations?': type({ '[string]': ContractRelationSchema }),\n 'discriminator?': 'unknown',\n 'variants?': 'unknown',\n 'base?': CrossReferenceSchema,\n 'owner?': 'string',\n});\n\nconst ContractMetaSchema = type({\n '[string]': 'unknown',\n});\n\n/**\n * Builds the full SQL contract schema. The storage subtree threads\n * pack contributions through {@link createSqlStorageSchema}; the rest\n * of the contract envelope is family-shared.\n */\nexport function createSqlContractSchema(\n registry: ReadonlyMap<string, Type<unknown>>,\n): Type<unknown> {\n const storage = createSqlStorageSchema(registry);\n return 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 'defaultControlPolicy?': ControlPolicySchema,\n 'roots?': type({ '[string]': CrossReferenceSchema }),\n domain: type({\n namespaces: type({\n '[string]': type({\n models: type({ '[string]': ModelSchema }),\n 'valueObjects?': 'Record<string, unknown>',\n 'enum?': type({ '[string]': ContractEnumSchema }),\n }),\n }),\n }),\n storage,\n 'execution?': ExecutionSchema,\n }) as Type<unknown>;\n}\n\nconst SqlContractSchema = createSqlContractSchema(createSqlEntrySchemaRegistry());\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 // Arktype validates the JSON-safe envelope, but the `ColumnDefault`\n // union carries runtime-only `bigint | Date` that the validation DSL\n // can't express (see NOTE above), so bridge the validated shape to the\n // input type. Construction below re-materialises nested IR fields.\n const validated = blindCast<\n SqlStorageInput & { readonly namespaces?: SqlStorageInput['namespaces'] },\n 'arktype validated the JSON envelope but its output type is unknown (ColumnDefault carries runtime-only bigint|Date); bridge to the input shape'\n >(result);\n const namespaces = buildSqlNamespaceMap(validated.namespaces ?? {});\n // Compatibility shim: inject the empty unbound singleton when absent so that\n // production code paths which address __unbound__ for table metadata have a\n // slot to read or write into. The `SqlStorageInput['namespaces']` type no\n // longer requires __unbound__, so this is a runtime convenience, not a type\n // invariant.\n const unbound = namespaces[UNBOUND_NAMESPACE_ID] ?? SqlUnboundNamespace.instance;\n return new SqlStorage({\n storageHash: validated.storageHash,\n ...ifDefined('types', validated.types),\n namespaces: { ...namespaces, [UNBOUND_NAMESPACE_ID]: unbound },\n });\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>>(\n value: unknown,\n contractSchema: Type<unknown>,\n): 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 = contractSchema(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 for (const check of table.checks ?? []) {\n registerNamedObject('check constraint', check.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 const seenCheckDefinitions = new Set<string>();\n for (const check of table.checks ?? []) {\n const signature = JSON.stringify({ column: check.column, valueSet: check.valueSet });\n if (seenCheckDefinitions.has(signature)) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": duplicate check constraint definition on column \"${check.column}\"`,\n );\n continue;\n }\n seenCheckDefinitions.add(signature);\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 for (const [namespaceId, namespace] of Object.entries(contract.domain.namespaces)) {\n const models = namespace.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const qualifiedName = `${namespaceId}:${modelName}`;\n const storageNamespaceId = model.storage.namespaceId;\n if (storageNamespaceId !== namespaceId) {\n throw new ContractValidationError(\n `Model \"${qualifiedName}\" storage.namespaceId \"${storageNamespaceId}\" does not match domain namespace \"${namespaceId}\"`,\n 'storage',\n );\n }\n\n const storageTable = model.storage.table;\n const storageNs = contract.storage.namespaces[storageNamespaceId];\n const rawTable = storageNs?.entries.table?.[storageTable];\n if (rawTable === undefined) {\n throw new ContractValidationError(\n `Model \"${qualifiedName}\" references non-existent table \"${storageNamespaceId}.${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 \"${qualifiedName}\" 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 \"${qualifiedName}\" 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/**\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 check of table.checks ?? []) {\n if (!columnNames.has(check.column)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" check constraint \"${check.name}\" references non-existent column \"${check.column}\"`,\n 'storage',\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 if (fk.target.spaceId === undefined) {\n const targetNamespace = contract.storage.namespaces[fk.target.namespaceId];\n const referencedRaw = targetNamespace?.entries.table?.[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\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\nexport interface ValidateSqlContractFullyOptions {\n /**\n * Precomputed structural schema to validate against. Built once at\n * serializer construction time when the family `ContractSerializer`\n * has folded pack-contributed `validatorSchema` fragments into the\n * per-namespace entry shape; absent for the family-default validator\n * path (no pack contributions). Falls back to the cached default\n * `SqlContractSchema` when omitted.\n */\n readonly contractSchema?: Type<unknown>;\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>>(\n value: unknown,\n options?: ValidateSqlContractFullyOptions,\n): 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 schema = options?.contractSchema ?? SqlContractSchema;\n const validated = validateSqlContractStructure<T>(stripped, schema);\n validateContractDomain({\n roots: validated.roots,\n domain: validated.domain,\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 {\n type Contract,\n type ContractField,\n type ContractModel,\n CrossReferenceSchema,\n} from '@prisma-next/contract/types';\nimport { validateContractDomain } from '@prisma-next/contract/validate-domain';\nimport {\n type AnyEntityKindDescriptor,\n isPlainRecord,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { type Type, type } from 'arktype';\nimport { composeSqlEntityKinds } from './entity-kinds';\nimport { buildSqlNamespaceMap } from './ir/build-sql-namespace';\n\nexport {\n CheckConstraintSchema,\n ColumnDefaultFunctionSchema,\n ColumnDefaultLiteralSchema,\n ColumnDefaultSchema,\n ForeignKeyReferenceSchema,\n ForeignKeySchema,\n ForeignKeySourceSchema,\n IndexSchema,\n ReferentialActionSchema,\n StorageTableSchema,\n StorageValueSetSchema,\n} from './ir/storage-entry-schemas';\n\nimport { SqlUnboundNamespace } from './ir/sql-unbound-namespace';\nimport {\n type SqlModelStorage,\n SqlStorage,\n type SqlStorageInput,\n type StorageTable,\n type StorageTypeInstanceInput,\n} from './types';\n\nconst generatorKindSchema = type(\"'generator'\");\nconst ControlPolicySchema = type(\"'managed' | 'tolerated' | 'external' | 'observed'\");\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\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 DomainEnumRefSchema = type({\n plane: \"'domain'\",\n namespaceId: 'string',\n entityKind: \"'enum'\",\n entityName: 'string',\n 'spaceId?': 'string',\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/** Document-scoped `storage.types`: codec triples only. */\nconst DocumentScopedStorageTypeSchema = StorageTypeInstanceSchema;\n\n/**\n * Domain enum entry under `domain.namespaces[id].enum[name]`.\n * Carries the codec id and an ordered `members` array of `{name, value}` pairs.\n */\nexport const ContractEnumSchema = type({\n '+': 'reject',\n codecId: 'string',\n members: type({\n name: 'string',\n value: 'string | number | boolean | null | unknown[] | Record<string, unknown>',\n })\n .array()\n .readonly(),\n});\n\n/**\n * Derives a schema map from a descriptor map: maps each kind's key to its\n * `schema` field. Used by validation functions to validate entries.\n */\nfunction schemaViewOf(\n kinds: ReadonlyMap<string, AnyEntityKindDescriptor>,\n): ReadonlyMap<string, Type<unknown>> {\n return new Map([...kinds].map(([k, d]) => [k, d.schema]));\n}\n\nconst DEFAULT_SQL_KINDS = composeSqlEntityKinds();\n\n/**\n * Builds the per-namespace entry schema for `storage.namespaces[id]`.\n *\n * Validation is descriptor-driven: the `kinds` map carries both the schema\n * (used here for structural validation) and the construct function (used at\n * hydration time). An unregistered key fails validation naming the kind and\n * the namespace id, so validation fails closed.\n */\nexport function createNamespaceEntrySchema(\n kinds: ReadonlyMap<string, AnyEntityKindDescriptor>,\n): Type<unknown> {\n const schemas = schemaViewOf(kinds);\n const knownKinds = new Set(kinds.keys());\n return type({\n '+': 'reject',\n id: 'string',\n 'kind?': 'string',\n entries: 'object',\n }).narrow((ns, ctx) => {\n if (!isPlainRecord(ns.entries)) {\n return ctx.mustBe('an entries object');\n }\n for (const [key, innerMap] of Object.entries(ns.entries)) {\n if (!knownKinds.has(key)) {\n return ctx.reject({\n expected: `entries key \"${key}\" in namespace \"${ns.id}\" is not a registered entity kind`,\n });\n }\n if (!isPlainRecord(innerMap)) {\n return ctx.reject({\n expected: `entries[\"${key}\"] in namespace \"${ns.id}\" must be an object`,\n });\n }\n const entrySchema = blindCast<\n Type<unknown>,\n 'knownKinds.has(key) guarantees schemas.get(key) is defined'\n >(schemas.get(key));\n for (const [, value] of Object.entries(innerMap)) {\n const parsed = entrySchema(value);\n if (parsed instanceof type.errors) {\n return ctx.reject({ expected: parsed.summary });\n }\n }\n }\n return true;\n }) as Type<unknown>;\n}\n\n/**\n * Builds the storage schema. Pack contributions reach the per-namespace\n * entry shape through {@link createNamespaceEntrySchema}; the\n * document-scoped `storage.types` field (codec triples only) and the\n * storage hash stay family-shared.\n */\nexport function createSqlStorageSchema(\n kinds: ReadonlyMap<string, AnyEntityKindDescriptor>,\n): Type<unknown> {\n const namespaceEntry = createNamespaceEntrySchema(kinds);\n return type({\n '+': 'reject',\n storageHash: 'string',\n 'types?': type({ '[string]': DocumentScopedStorageTypeSchema }),\n // `__unbound__` is NOT required here: cross-namespace contracts can\n // declare only named namespaces (see cross-namespace FK fixtures). The\n // `__unbound__` brand on `SqlStorageInput['namespaces']` is kept sound at\n // construction time by injecting the unbound singleton when absent\n // (see `validateStorage` / `hydrateSqlStorage`), not by structural require.\n 'namespaces?': type({ '[string]': namespaceEntry }),\n }) as Type<unknown>;\n}\n\nconst StorageSchema = createSqlStorageSchema(DEFAULT_SQL_KINDS);\n\ntype NamespacedStorageWalk = {\n readonly namespaces: Readonly<\n Record<\n string,\n Namespace & { readonly entries: Readonly<Record<string, Readonly<Record<string, unknown>>>> }\n >\n >;\n};\n\nfunction eachStorageTable(storage: NamespacedStorageWalk) {\n return Object.entries(storage.namespaces).flatMap(([namespaceId, ns]) =>\n Object.entries(ns.entries['table'] ?? {}).map(([tableName, table]) => ({\n namespaceId,\n tableName,\n table,\n })),\n );\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 'valueSet?': DomainEnumRefSchema,\n});\n\nconst ModelStorageFieldSchema = type({\n column: 'string',\n 'codecId?': 'string',\n 'nullable?': 'boolean',\n});\n\nconst ModelStorageSchema = type({\n table: 'string',\n namespaceId: 'string',\n fields: type({ '[string]': ModelStorageFieldSchema }),\n});\n\nconst ContractRelationThroughSchema = type({\n '+': 'reject',\n table: 'string',\n namespaceId: 'string',\n parentColumns: type.string.array().readonly(),\n childColumns: type.string.array().readonly(),\n targetColumns: type.string.array().readonly(),\n});\n\nconst ContractRelationOnSchema = type({\n '+': 'reject',\n localFields: type.string.array().readonly(),\n targetFields: type.string.array().readonly(),\n});\n\nconst ContractManyToManyRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'N:M'\",\n on: ContractRelationOnSchema,\n through: ContractRelationThroughSchema,\n});\n\nconst ContractNonJunctionRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'1:1' | '1:N' | 'N:1'\",\n on: ContractRelationOnSchema,\n});\n\nconst ContractReferenceRelationSchema = ContractManyToManyRelationSchema.or(\n ContractNonJunctionRelationSchema,\n);\n\nconst ContractEmbedRelationSchema = type({\n '+': 'reject',\n to: CrossReferenceSchema,\n cardinality: \"'1:1' | '1:N'\",\n});\n\nconst ContractRelationSchema = ContractReferenceRelationSchema.or(ContractEmbedRelationSchema);\n\nconst ModelSchema = type({\n storage: ModelStorageSchema,\n 'fields?': type({ '[string]': ModelFieldSchema }),\n 'relations?': type({ '[string]': ContractRelationSchema }),\n 'discriminator?': 'unknown',\n 'variants?': 'unknown',\n 'base?': CrossReferenceSchema,\n 'owner?': 'string',\n});\n\nconst ContractMetaSchema = type({\n '[string]': 'unknown',\n});\n\n/**\n * Builds the full SQL contract schema. The storage subtree threads\n * pack contributions through {@link createSqlStorageSchema}; the rest\n * of the contract envelope is family-shared.\n */\nexport function createSqlContractSchema(\n kinds: ReadonlyMap<string, AnyEntityKindDescriptor>,\n): Type<unknown> {\n const storage = createSqlStorageSchema(kinds);\n return 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 'defaultControlPolicy?': ControlPolicySchema,\n 'roots?': type({ '[string]': CrossReferenceSchema }),\n domain: type({\n namespaces: type({\n '[string]': type({\n models: type({ '[string]': ModelSchema }),\n 'valueObjects?': 'Record<string, unknown>',\n 'enum?': type({ '[string]': ContractEnumSchema }),\n }),\n }),\n }),\n storage,\n 'execution?': ExecutionSchema,\n }) as Type<unknown>;\n}\n\nconst SqlContractSchema = createSqlContractSchema(DEFAULT_SQL_KINDS);\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 // Arktype validates the JSON-safe envelope, but the `ColumnDefault`\n // union carries runtime-only `bigint | Date` that the validation DSL\n // can't express (see NOTE above), so bridge the validated shape to the\n // input type. Construction below re-materialises nested IR fields.\n const validated = blindCast<\n SqlStorageInput & { readonly namespaces?: SqlStorageInput['namespaces'] },\n 'arktype validated the JSON envelope but its output type is unknown (ColumnDefault carries runtime-only bigint|Date); bridge to the input shape'\n >(result);\n const namespaces = buildSqlNamespaceMap(validated.namespaces ?? {});\n // Compatibility shim: inject the empty unbound singleton when absent so that\n // production code paths which address __unbound__ for table metadata have a\n // slot to read or write into. The `SqlStorageInput['namespaces']` type no\n // longer requires __unbound__, so this is a runtime convenience, not a type\n // invariant.\n const unbound = namespaces[UNBOUND_NAMESPACE_ID] ?? SqlUnboundNamespace.instance;\n return new SqlStorage({\n storageHash: validated.storageHash,\n ...ifDefined('types', validated.types),\n namespaces: { ...namespaces, [UNBOUND_NAMESPACE_ID]: unbound },\n });\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>>(\n value: unknown,\n contractSchema: Type<unknown>,\n): 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 = contractSchema(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 for (const check of table.checks ?? []) {\n registerNamedObject('check constraint', check.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 const seenCheckDefinitions = new Set<string>();\n for (const check of table.checks ?? []) {\n const signature = JSON.stringify({ column: check.column, valueSet: check.valueSet });\n if (seenCheckDefinitions.has(signature)) {\n errors.push(\n `Namespace \"${namespaceId}\" table \"${tableName}\": duplicate check constraint definition on column \"${check.column}\"`,\n );\n continue;\n }\n seenCheckDefinitions.add(signature);\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 for (const [namespaceId, namespace] of Object.entries(contract.domain.namespaces)) {\n const models = namespace.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const qualifiedName = `${namespaceId}:${modelName}`;\n const storageNamespaceId = model.storage.namespaceId;\n if (storageNamespaceId !== namespaceId) {\n throw new ContractValidationError(\n `Model \"${qualifiedName}\" storage.namespaceId \"${storageNamespaceId}\" does not match domain namespace \"${namespaceId}\"`,\n 'storage',\n );\n }\n\n const storageTable = model.storage.table;\n const storageNs = contract.storage.namespaces[storageNamespaceId];\n const rawTable = storageNs?.entries.table?.[storageTable];\n if (rawTable === undefined) {\n throw new ContractValidationError(\n `Model \"${qualifiedName}\" references non-existent table \"${storageNamespaceId}.${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 \"${qualifiedName}\" 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 \"${qualifiedName}\" 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/**\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 check of table.checks ?? []) {\n if (!columnNames.has(check.column)) {\n throw new ContractValidationError(\n `Namespace \"${namespaceId}\" table \"${tableName}\" check constraint \"${check.name}\" references non-existent column \"${check.column}\"`,\n 'storage',\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 if (fk.target.spaceId === undefined) {\n const targetNamespace = contract.storage.namespaces[fk.target.namespaceId];\n const referencedRaw = targetNamespace?.entries.table?.[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\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\nexport interface ValidateSqlContractFullyOptions {\n /**\n * Precomputed structural schema to validate against. Built once at\n * serializer construction time when the family `ContractSerializer`\n * has folded pack-contributed `validatorSchema` fragments into the\n * per-namespace entry shape; absent for the family-default validator\n * path (no pack contributions). Falls back to the cached default\n * `SqlContractSchema` when omitted.\n */\n readonly contractSchema?: Type<unknown>;\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>>(\n value: unknown,\n options?: ValidateSqlContractFullyOptions,\n): 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 schema = options?.contractSchema ?? SqlContractSchema;\n const validated = validateSqlContractStructure<T>(stripped, schema);\n validateContractDomain({\n roots: validated.roots,\n domain: validated.domain,\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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"}
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@prisma-next/sql-contract",
3
- "version": "0.13.0-dev.34",
3
+ "version": "0.13.0-dev.35",
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.13.0-dev.34",
10
- "@prisma-next/framework-components": "0.13.0-dev.34",
11
- "@prisma-next/utils": "0.13.0-dev.34",
9
+ "@prisma-next/contract": "0.13.0-dev.35",
10
+ "@prisma-next/framework-components": "0.13.0-dev.35",
11
+ "@prisma-next/utils": "0.13.0-dev.35",
12
12
  "arktype": "^2.2.0"
13
13
  },
14
14
  "devDependencies": {
15
- "@prisma-next/test-utils": "0.13.0-dev.34",
16
- "@prisma-next/tsconfig": "0.13.0-dev.34",
17
- "@prisma-next/tsdown": "0.13.0-dev.34",
15
+ "@prisma-next/test-utils": "0.13.0-dev.35",
16
+ "@prisma-next/tsconfig": "0.13.0-dev.35",
17
+ "@prisma-next/tsdown": "0.13.0-dev.35",
18
18
  "tsdown": "0.22.1",
19
19
  "typescript": "5.9.3",
20
20
  "vitest": "4.1.8"
@@ -33,6 +33,7 @@
33
33
  ],
34
34
  "exports": {
35
35
  "./canonicalization-hooks": "./dist/canonicalization-hooks.mjs",
36
+ "./entity-kinds": "./dist/entity-kinds.mjs",
36
37
  "./factories": "./dist/factories.mjs",
37
38
  "./index-type-validation": "./dist/index-type-validation.mjs",
38
39
  "./index-types": "./dist/index-types.mjs",
@@ -0,0 +1,45 @@
1
+ import type {
2
+ AnyEntityKindDescriptor,
3
+ EntityKindDescriptor,
4
+ } from '@prisma-next/framework-components/ir';
5
+ import { StorageTableSchema, StorageValueSetSchema } from './ir/storage-entry-schemas';
6
+ import { StorageTable, type StorageTableInput } from './ir/storage-table';
7
+ import { StorageValueSet, type StorageValueSetInput } from './ir/storage-value-set';
8
+
9
+ export const tableEntityKind: EntityKindDescriptor<StorageTableInput, StorageTable> = {
10
+ kind: 'table',
11
+ schema: StorageTableSchema,
12
+ construct: (input) => new StorageTable(input),
13
+ };
14
+
15
+ export const valueSetEntityKind: EntityKindDescriptor<StorageValueSetInput, StorageValueSet> = {
16
+ kind: 'valueSet',
17
+ schema: StorageValueSetSchema,
18
+ construct: (input) => new StorageValueSet(input),
19
+ };
20
+
21
+ /**
22
+ * Assembles the `kind → descriptor` registry for SQL namespaces: the built-in
23
+ * `table` and `valueSet` kinds plus any target `packKinds`. This builds the
24
+ * lookup table — it does not touch contract data. `hydrateNamespaceEntities`
25
+ * later consumes this registry to turn a namespace's raw entries into IR
26
+ * instances, and `createSqlContractSchema` derives validation from the same
27
+ * registry. Throws on a duplicate kind.
28
+ */
29
+ export function composeSqlEntityKinds(
30
+ packKinds: readonly AnyEntityKindDescriptor[] = [],
31
+ ): ReadonlyMap<string, AnyEntityKindDescriptor> {
32
+ const kinds = new Map<string, AnyEntityKindDescriptor>([
33
+ ['table', tableEntityKind],
34
+ ['valueSet', valueSetEntityKind],
35
+ ]);
36
+ for (const descriptor of packKinds) {
37
+ if (kinds.has(descriptor.kind)) {
38
+ throw new Error(
39
+ `composeSqlEntityKinds: duplicate entity kind "${descriptor.kind}" — each kind may be registered only once`,
40
+ );
41
+ }
42
+ kinds.set(descriptor.kind, descriptor);
43
+ }
44
+ return kinds;
45
+ }
@@ -0,0 +1,5 @@
1
+ export {
2
+ composeSqlEntityKinds,
3
+ tableEntityKind,
4
+ valueSetEntityKind,
5
+ } from '../entity-kinds';