@prisma-next/sql-contract-emitter 0.16.0-dev.30 → 0.16.0-dev.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;cA8Ca;;qCAGa,UAAQ,MAAQ;yCA4BZ;2CA8KE,UAAQ;0DAQK,OAAS;wDAuBhC,mBACD,OACV,mBAAiB,UACd,aACT;sDAgCiB,mBACD,OACV,mBAAiB,UACd;aACE,wBAAwB;aAAsB;;6CAmC5B,UAAQ,cAAgB;;4CAuBzB;;0DAwBY"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;cA+Ca;;qCAGa,UAAQ,MAAQ;yCAgCZ;2CAyNE,UAAQ;0DAQK,OAAS;wDAuBhC,mBACD,OACV,mBAAiB,UACd,aACT;sDAgCiB,mBACD,OACV,mBAAiB,UACd;aACE,wBAAwB;aAAsB;;6CAmC5B,UAAQ,cAAgB;;4CAuBzB;;0DAwBY"}
package/dist/index.mjs CHANGED
@@ -2,6 +2,19 @@ import { renderValueSetType, serializeNamespaceId, serializeObjectKey, serialize
2
2
  import { isSafeTypeExpression } from "@prisma-next/emitter/type-expression-safety";
3
3
  import { UNBOUND_NAMESPACE_ID, entityAt } from "@prisma-next/framework-components/ir";
4
4
  import { blindCast } from "@prisma-next/utils/casts";
5
+ import { structuredError } from "@prisma-next/utils/structured-error";
6
+ //#region src/errors.ts
7
+ function sqlEmitterError(code, message, options) {
8
+ return structuredError(code, message, options);
9
+ }
10
+ function sqlEmitterValidationError(message, meta) {
11
+ return sqlEmitterError("CONTRACT.VALIDATION_FAILED", message, {
12
+ why: "The contract given to the SQL emitter failed structural validation.",
13
+ fix: "Regenerate the contract from its authoring source; do not hand-edit contract JSON.",
14
+ meta
15
+ });
16
+ }
17
+ //#endregion
5
18
  //#region src/index.ts
6
19
  function serializeTypeParamsLiteral(params) {
7
20
  if (!params || Object.keys(params).length === 0) return "Record<string, never>";
@@ -17,18 +30,32 @@ const sqlEmission = {
17
30
  const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
18
31
  for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) for (const [colName, colUnknown] of Object.entries(table.columns)) {
19
32
  const codecId = colUnknown.codecId;
20
- if (!codecId) throw new Error(`Column "${colName}" in table "${tableName}" is missing codecId`);
21
- if (!codecId.match(typeIdRegex)?.[1]) throw new Error(`Column "${colName}" in table "${tableName}" has invalid codec ID format "${codecId}". Expected format: ns/name@version`);
33
+ if (!codecId) throw sqlEmitterValidationError(`Column "${colName}" in table "${tableName}" is missing codecId`, {
34
+ table: tableName,
35
+ column: colName
36
+ });
37
+ if (!codecId.match(typeIdRegex)?.[1]) throw sqlEmitterValidationError(`Column "${colName}" in table "${tableName}" has invalid codec ID format "${codecId}". Expected format: ns/name@version`, {
38
+ table: tableName,
39
+ column: colName,
40
+ codecId
41
+ });
22
42
  }
23
43
  },
24
44
  validateStructure(contract) {
25
- if (contract.targetFamily !== "sql") throw new Error(`Expected targetFamily "sql", got "${contract.targetFamily}"`);
45
+ if (contract.targetFamily !== "sql") throw sqlEmitterValidationError(`Expected targetFamily "sql", got "${contract.targetFamily}"`, { targetFamily: contract.targetFamily });
26
46
  const storage = contract.storage;
27
- if (!storage?.namespaces) throw new Error("SQL contract must have storage.namespaces");
47
+ if (!storage?.namespaces) throw sqlEmitterValidationError("SQL contract must have storage.namespaces", {});
28
48
  const tableNamesSeenAcrossNamespaces = /* @__PURE__ */ new Map();
29
49
  for (const [nsId, ns] of Object.entries(storage.namespaces)) for (const tableName of Object.keys(ns.entries.table ?? {})) {
30
50
  const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
31
- if (existingNs !== void 0 && existingNs !== nsId) throw new Error(`Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`);
51
+ if (existingNs !== void 0 && existingNs !== nsId) throw sqlEmitterError("CONTRACT.NAME_DUPLICATE", `Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`, {
52
+ why: "Two SQL namespaces declare a table with the same name, which is ambiguous for emission.",
53
+ fix: "Rename one of the tables so every table name is unique across namespaces.",
54
+ meta: {
55
+ table: tableName,
56
+ namespaces: [existingNs, nsId]
57
+ }
58
+ });
32
59
  tableNamesSeenAcrossNamespaces.set(tableName, nsId);
33
60
  }
34
61
  const tableNames = /* @__PURE__ */ new Set();
@@ -37,47 +64,86 @@ const sqlEmission = {
37
64
  const models = domainNs.models;
38
65
  for (const [modelName, model] of Object.entries(models)) {
39
66
  const qualifiedName = `${namespaceId}:${modelName}`;
40
- if (!model.storage?.table) throw new Error(`Model "${qualifiedName}" is missing storage.table`);
41
- if (!model.storage.namespaceId) throw new Error(`Model "${qualifiedName}" is missing storage.namespaceId`);
42
- if (model.storage.namespaceId !== namespaceId) throw new Error(`Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`);
67
+ if (!model.storage?.table) throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing storage.table`, { model: qualifiedName });
68
+ if (!model.storage.namespaceId) throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing storage.namespaceId`, { model: qualifiedName });
69
+ if (model.storage.namespaceId !== namespaceId) throw sqlEmitterValidationError(`Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`, {
70
+ model: qualifiedName,
71
+ storageNamespaceId: model.storage.namespaceId,
72
+ domainNamespaceId: namespaceId
73
+ });
43
74
  const tableName = model.storage.table;
44
75
  const table = entityAt(storage, {
45
76
  namespaceId,
46
77
  entityKind: "table",
47
78
  entityName: tableName
48
79
  });
49
- if (!table) throw new Error(`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`);
80
+ if (!table) throw sqlEmitterValidationError(`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`, {
81
+ model: qualifiedName,
82
+ table: `${namespaceId}.${tableName}`
83
+ });
50
84
  const columnNames = new Set(Object.keys(table.columns));
51
85
  const storageFields = model.storage.fields;
52
- if (!storageFields || Object.keys(storageFields).length === 0) throw new Error(`Model "${qualifiedName}" is missing storage.fields`);
86
+ if (!storageFields || Object.keys(storageFields).length === 0) throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing storage.fields`, { model: qualifiedName });
53
87
  for (const [fieldName, field] of Object.entries(storageFields)) {
54
- if (!field.column) throw new Error(`Model "${qualifiedName}" field "${fieldName}" is missing column property`);
55
- if (!columnNames.has(field.column)) throw new Error(`Model "${qualifiedName}" field "${fieldName}" references non-existent column "${field.column}" in table "${tableName}"`);
88
+ if (!field.column) throw sqlEmitterValidationError(`Model "${qualifiedName}" field "${fieldName}" is missing column property`, {
89
+ model: qualifiedName,
90
+ field: fieldName
91
+ });
92
+ if (!columnNames.has(field.column)) throw sqlEmitterValidationError(`Model "${qualifiedName}" field "${fieldName}" references non-existent column "${field.column}" in table "${tableName}"`, {
93
+ model: qualifiedName,
94
+ field: fieldName,
95
+ column: field.column,
96
+ table: tableName
97
+ });
56
98
  }
57
- if (!model.relations || typeof model.relations !== "object") throw new Error(`Model "${qualifiedName}" is missing required field "relations" (must be an object)`);
99
+ if (!model.relations || typeof model.relations !== "object") throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing required field "relations" (must be an object)`, { model: qualifiedName });
58
100
  }
59
101
  }
60
102
  for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {
61
103
  const columnNames = new Set(Object.keys(table.columns));
62
- if (!Array.isArray(table.uniques)) throw new Error(`Table "${tableName}" is missing required field "uniques" (must be an array)`);
63
- if (!Array.isArray(table.indexes)) throw new Error(`Table "${tableName}" is missing required field "indexes" (must be an array)`);
64
- if (!Array.isArray(table.foreignKeys)) throw new Error(`Table "${tableName}" is missing required field "foreignKeys" (must be an array)`);
104
+ if (!Array.isArray(table.uniques)) throw sqlEmitterValidationError(`Table "${tableName}" is missing required field "uniques" (must be an array)`, { table: tableName });
105
+ if (!Array.isArray(table.indexes)) throw sqlEmitterValidationError(`Table "${tableName}" is missing required field "indexes" (must be an array)`, { table: tableName });
106
+ if (!Array.isArray(table.foreignKeys)) throw sqlEmitterValidationError(`Table "${tableName}" is missing required field "foreignKeys" (must be an array)`, { table: tableName });
65
107
  if (table.primaryKey) {
66
- for (const colName of table.primaryKey.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" primaryKey references non-existent column "${colName}"`);
108
+ for (const colName of table.primaryKey.columns) if (!columnNames.has(colName)) throw sqlEmitterValidationError(`Table "${tableName}" primaryKey references non-existent column "${colName}"`, {
109
+ table: tableName,
110
+ column: colName
111
+ });
67
112
  }
68
- for (const unique of table.uniques) for (const colName of unique.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" unique constraint references non-existent column "${colName}"`);
69
- for (const index of table.indexes) for (const colName of index.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" index references non-existent column "${colName}"`);
113
+ for (const unique of table.uniques) for (const colName of unique.columns) if (!columnNames.has(colName)) throw sqlEmitterValidationError(`Table "${tableName}" unique constraint references non-existent column "${colName}"`, {
114
+ table: tableName,
115
+ column: colName
116
+ });
117
+ for (const index of table.indexes) for (const colName of index.columns) if (!columnNames.has(colName)) throw sqlEmitterValidationError(`Table "${tableName}" index references non-existent column "${colName}"`, {
118
+ table: tableName,
119
+ column: colName
120
+ });
70
121
  for (const fk of table.foreignKeys) {
71
- for (const colName of fk.source.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" foreignKey references non-existent column "${colName}"`);
122
+ for (const colName of fk.source.columns) if (!columnNames.has(colName)) throw sqlEmitterValidationError(`Table "${tableName}" foreignKey references non-existent column "${colName}"`, {
123
+ table: tableName,
124
+ column: colName
125
+ });
72
126
  const referencedTable = entityAt(storage, {
73
127
  namespaceId: fk.target.namespaceId,
74
128
  entityKind: "table",
75
129
  entityName: fk.target.tableName
76
130
  });
77
- if (!referencedTable) throw new Error(`Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`);
131
+ if (!referencedTable) throw sqlEmitterValidationError(`Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`, {
132
+ table: tableName,
133
+ targetTable: fk.target.tableName,
134
+ targetNamespace: fk.target.namespaceId
135
+ });
78
136
  const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
79
- for (const colName of fk.target.columns) if (!referencedColumnNames.has(colName)) throw new Error(`Table "${tableName}" foreignKey references non-existent column "${colName}" in table "${fk.target.tableName}"`);
80
- if (fk.source.columns.length !== fk.target.columns.length) throw new Error(`Table "${tableName}" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`);
137
+ for (const colName of fk.target.columns) if (!referencedColumnNames.has(colName)) throw sqlEmitterValidationError(`Table "${tableName}" foreignKey references non-existent column "${colName}" in table "${fk.target.tableName}"`, {
138
+ table: tableName,
139
+ column: colName,
140
+ targetTable: fk.target.tableName
141
+ });
142
+ if (fk.source.columns.length !== fk.target.columns.length) throw sqlEmitterValidationError(`Table "${tableName}" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`, {
143
+ table: tableName,
144
+ sourceColumnCount: fk.source.columns.length,
145
+ targetColumnCount: fk.target.columns.length
146
+ });
81
147
  }
82
148
  }
83
149
  },
@@ -242,7 +308,11 @@ function generateDocumentScopedStorageTypesType(types) {
242
308
  const typeEntries = [];
243
309
  for (const [typeName, typeInstance] of Object.entries(types)) {
244
310
  const codecInstanceShape = typeInstance;
245
- if (typeof codecInstanceShape.codecId !== "string" || typeof codecInstanceShape.nativeType !== "string") throw new Error(`Unknown storage type kind for "${typeName}" in document-scoped storage.types; expected a codec-instance triple.`);
311
+ if (typeof codecInstanceShape.codecId !== "string" || typeof codecInstanceShape.nativeType !== "string") throw sqlEmitterError("CONTRACT.TYPE_UNKNOWN", `Unknown storage type kind for "${typeName}" in document-scoped storage.types; expected a codec-instance triple.`, {
312
+ why: "A storage.types entry is not a codec-instance triple, so its column type cannot be emitted.",
313
+ fix: "Regenerate the contract from its authoring source; storage.types entries must carry codecId and nativeType.",
314
+ meta: { type: typeName }
315
+ });
246
316
  const codecId = serializeValue(codecInstanceShape.codecId);
247
317
  const nativeType = serializeValue(codecInstanceShape.nativeType);
248
318
  const typeParamsStr = serializeTypeParamsLiteral(codecInstanceShape.typeParams);
@@ -265,7 +335,11 @@ function namespaceSerializedKind(ns) {
265
335
  const kind = ns.kind;
266
336
  if (kind === "schema") return `readonly kind: '${ns.id === UNBOUND_NAMESPACE_ID ? "postgres-unbound-schema" : "postgres-schema"}'`;
267
337
  if (typeof kind === "string") return `readonly kind: ${serializeValue(kind)}`;
268
- throw new Error(`Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`);
338
+ throw sqlEmitterError("CONTRACT.NAMESPACE_INVALID", `Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`, {
339
+ why: "The namespace is not a target concretion, so the emitter cannot serialize its kind.",
340
+ fix: "Regenerate the contract with a target pack that materializes every namespace as a target concretion.",
341
+ meta: { namespace: ns.id }
342
+ });
269
343
  }
270
344
  function generateTableLiteralType(table) {
271
345
  const columns = [];
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/index.ts"],"sourcesContent":["import type {\n Contract,\n ContractModel,\n ContractModelBase,\n JsonValue,\n} from '@prisma-next/contract/types';\nimport {\n renderValueSetType,\n serializeNamespaceId,\n serializeObjectKey,\n serializeValue,\n} from '@prisma-next/emitter/domain-type-generation';\nimport { isSafeTypeExpression } from '@prisma-next/emitter/type-expression-safety';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type {\n GenerateContractTypesOptions,\n ValidationContext,\n} from '@prisma-next/framework-components/emission';\nimport {\n entityAt,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport type {\n SqlModelStorage,\n SqlStorage,\n StorageColumn,\n StorageTable,\n StorageTypeInstance,\n StorageValueSet,\n} from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\n\nfunction serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return 'Record<string, never>';\n }\n\n const entries: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n entries.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);\n }\n\n return `{ ${entries.join('; ')} }`;\n}\n\nexport const sqlEmission = {\n id: 'sql',\n\n validateTypes(contract: Contract, _ctx: ValidationContext): void {\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n return;\n }\n\n const typeIdRegex = /^([^/]+)\\/([^@]+)@(\\d+)$/;\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n for (const [colName, colUnknown] of Object.entries(table.columns)) {\n const col = colUnknown as { codecId?: string };\n const codecId = col.codecId;\n if (!codecId) {\n throw new Error(`Column \"${colName}\" in table \"${tableName}\" is missing codecId`);\n }\n\n const match = codecId.match(typeIdRegex);\n if (!match?.[1]) {\n throw new Error(\n `Column \"${colName}\" in table \"${tableName}\" has invalid codec ID format \"${codecId}\". Expected format: ns/name@version`,\n );\n }\n }\n }\n }\n },\n\n validateStructure(contract: Contract): void {\n if (contract.targetFamily !== 'sql') {\n throw new Error(`Expected targetFamily \"sql\", got \"${contract.targetFamily}\"`);\n }\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n throw new Error('SQL contract must have storage.namespaces');\n }\n\n const tableNamesSeenAcrossNamespaces = new Map<string, string>();\n for (const [nsId, ns] of Object.entries(storage.namespaces)) {\n for (const tableName of Object.keys(ns.entries.table ?? {})) {\n const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);\n if (existingNs !== undefined && existingNs !== nsId) {\n throw new Error(\n `Duplicate table name \"${tableName}\" in namespaces \"${existingNs}\" and \"${nsId}\"`,\n );\n }\n tableNamesSeenAcrossNamespaces.set(tableName, nsId);\n }\n }\n\n const tableNames = new Set<string>();\n for (const ns of Object.values(storage.namespaces)) {\n for (const t of Object.keys(ns.entries.table ?? {})) {\n tableNames.add(t);\n }\n }\n\n for (const [namespaceId, domainNs] of Object.entries(contract.domain.namespaces)) {\n const models = domainNs.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const qualifiedName = `${namespaceId}:${modelName}`;\n if (!model.storage?.table) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.table`);\n }\n if (!model.storage.namespaceId) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.namespaceId`);\n }\n if (model.storage.namespaceId !== namespaceId) {\n throw new Error(\n `Model \"${qualifiedName}\" storage.namespaceId \"${model.storage.namespaceId}\" does not match domain namespace \"${namespaceId}\"`,\n );\n }\n\n const tableName = model.storage.table;\n const table = entityAt<StorageTable>(storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) {\n throw new Error(\n `Model \"${qualifiedName}\" references non-existent table \"${namespaceId}.${tableName}\"`,\n );\n }\n const columnNames = new Set(Object.keys(table.columns));\n const storageFields = model.storage.fields;\n if (!storageFields || Object.keys(storageFields).length === 0) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.fields`);\n }\n\n for (const [fieldName, field] of Object.entries(storageFields)) {\n if (!field.column) {\n throw new Error(\n `Model \"${qualifiedName}\" field \"${fieldName}\" is missing column property`,\n );\n }\n\n if (!columnNames.has(field.column)) {\n throw new Error(\n `Model \"${qualifiedName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${tableName}\"`,\n );\n }\n }\n\n if (!model.relations || typeof model.relations !== 'object') {\n throw new Error(\n `Model \"${qualifiedName}\" is missing required field \"relations\" (must be an object)`,\n );\n }\n }\n }\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n const columnNames = new Set(Object.keys(table.columns));\n\n if (!Array.isArray(table.uniques)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"uniques\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.indexes)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"indexes\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.foreignKeys)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"foreignKeys\" (must be an array)`,\n );\n }\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\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 Error(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\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 Error(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.source.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n );\n }\n }\n\n const referencedTable = entityAt<StorageTable>(storage, {\n namespaceId: fk.target.namespaceId,\n entityKind: 'table',\n entityName: fk.target.tableName,\n });\n if (!referencedTable) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.target.tableName}\" in namespace \"${fk.target.namespaceId}\"`,\n );\n }\n\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 Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.target.tableName}\"`,\n );\n }\n }\n\n if (fk.source.columns.length !== fk.target.columns.length) {\n throw new Error(\n `Table \"${tableName}\" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`,\n );\n }\n }\n }\n }\n },\n\n generateStorageType(contract: Contract, storageHashTypeName: string): string {\n const storage = contract.storage as unknown as SqlStorage;\n const namespacesType = generateStorageNamespacesType(storage.namespaces);\n const docTypes = generateDocumentScopedStorageTypesType(storage.types);\n const typesClause = docTypes === undefined ? '' : `; readonly types: ${docTypes}`;\n return `{ readonly namespaces: ${namespacesType}${typesClause}; readonly storageHash: ${storageHashTypeName} }`;\n },\n\n generateModelStorageType(_modelName: string, model: ContractModelBase): string {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const tableName = sqlModel.storage.table;\n const storageFields = sqlModel.storage.fields;\n\n const storageParts = [\n `readonly table: ${serializeValue(tableName)}`,\n `readonly namespaceId: ${serializeValue(sqlModel.storage.namespaceId)}`,\n ];\n if (Object.keys(storageFields).length > 0) {\n const fieldParts: string[] = [];\n for (const [fieldName, field] of Object.entries(storageFields)) {\n fieldParts.push(\n `readonly ${serializeObjectKey(fieldName)}: { readonly column: ${serializeValue(field.column)} }`,\n );\n }\n storageParts.push(`readonly fields: { ${fieldParts.join('; ')} }`);\n }\n\n return `{ ${storageParts.join('; ')} }`;\n },\n\n resolveFieldTypeParams(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): Record<string, unknown> | undefined {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage) return undefined;\n\n const tableName = sqlModel.storage.table;\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) return undefined;\n\n const column = table.columns[storageField.column];\n if (!column) return undefined;\n\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n const codecShape = typeInstance as Partial<StorageTypeInstance>;\n return codecShape.typeParams;\n }\n return column.typeParams;\n },\n\n resolveFieldValueSet(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): { readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefined {\n const sqlModel = blindCast<\n ContractModel<SqlModelStorage>,\n 'a sql-family model carries SqlModelStorage in storage'\n >(model);\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage) return undefined;\n\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: sqlModel.storage.table,\n });\n const column = table?.columns[storageField.column];\n if (!column?.valueSet) return undefined;\n\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n if (!valueSet) return undefined;\n\n return { encodedValues: valueSet.values, codecId: column.codecId };\n },\n\n getStorageTypeExports(contract: Contract, codecLookup?: CodecLookup): string | undefined {\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage?.namespaces) return undefined;\n const outputMap = generateStorageColumnTypesMap(storage, 'output', codecLookup);\n const inputMap = generateStorageColumnTypesMap(storage, 'input', codecLookup);\n return [\n `export type StorageColumnTypes = ${outputMap};`,\n `export type StorageColumnInputTypes = ${inputMap};`,\n ].join('\\n');\n },\n\n getFamilyImports(): string[] {\n return [\n 'import type {',\n ' ContractWithTypeMaps,',\n ' TypeMaps as TypeMapsType,',\n \"} from '@prisma-next/sql-contract/types';\",\n ];\n },\n\n getFamilyTypeAliases(options?: GenerateContractTypesOptions): string {\n const queryOperationTypeImports = options?.queryOperationTypeImports ?? [];\n const queryOperationAliases = queryOperationTypeImports\n .filter((imp) => imp.named === 'QueryOperationTypes')\n .map((imp) => `${imp.alias}<CodecTypes>`);\n const queryOperationTypes =\n queryOperationAliases.length > 0\n ? queryOperationAliases.join(' & ')\n : 'Record<string, never>';\n\n return [\n 'export type LaneCodecTypes = CodecTypes;',\n `export type QueryOperationTypes = ${queryOperationTypes};`,\n 'type DefaultLiteralValue<CodecId extends string, _Encoded> =',\n ' CodecId extends keyof CodecTypes',\n \" ? CodecTypes[CodecId]['output']\",\n ' : _Encoded;',\n ].join('\\n');\n },\n\n getTypeMapsExpression(): string {\n return 'TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes, StorageColumnTypes, StorageColumnInputTypes>';\n },\n\n getContractWrapper(contractBaseName: string, typeMapsName: string): string {\n return [\n `export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,\n '',\n \"export type Namespaces = Contract['storage']['namespaces'];\",\n ].join('\\n');\n },\n} as const;\n\ntype ColumnTypeSide = 'output' | 'input';\n\nfunction columnTypeParams(\n storage: SqlStorage,\n column: StorageColumn,\n): Record<string, unknown> | undefined {\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n return blindCast<\n Partial<StorageTypeInstance>,\n 'storage.types entries are codec-instance triples carrying optional typeParams'\n >(typeInstance).typeParams;\n }\n return column.typeParams;\n}\n\nfunction renderRefinedCodecType(\n column: StorageColumn,\n side: ColumnTypeSide,\n params: Record<string, unknown> | undefined,\n codecLookup: CodecLookup | undefined,\n): string {\n if (codecLookup && params && Object.keys(params).length > 0) {\n const rendered =\n side === 'output'\n ? codecLookup.renderOutputTypeFor(column.codecId, params)\n : codecLookup.renderInputTypeFor?.(column.codecId, params);\n if (rendered && isSafeTypeExpression(rendered)) {\n return rendered;\n }\n }\n return `CodecTypes[${serializeValue(column.codecId)}][${serializeValue(side)}]`;\n}\n\nfunction computeColumnType(\n storage: SqlStorage,\n column: StorageColumn,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n let base: string | undefined;\n if (column.valueSet) {\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n base = valueSet\n ? renderValueSetType(valueSet.values, column.codecId, side, codecLookup)\n : undefined;\n }\n if (base === undefined) {\n base = renderRefinedCodecType(column, side, columnTypeParams(storage, column), codecLookup);\n }\n if (column.many === true) base = `ReadonlyArray<${base}>`;\n return column.nullable ? `${base} | null` : base;\n}\n\nfunction generateStorageColumnTypesMap(\n storage: SqlStorage,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n const namespaceEntries = Object.entries(storage.namespaces ?? {}).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n if (namespaceEntries.length === 0) return 'Record<string, never>';\n\n const nsParts: string[] = [];\n for (const [nsId, ns] of namespaceEntries) {\n const tables = blindCast<\n Readonly<Record<string, StorageTable>>,\n 'same pattern as generateTablesMapType below'\n >(ns.entries.table ?? {});\n const tableEntries = Object.entries(tables).sort(([a], [b]) => a.localeCompare(b));\n const tableParts: string[] = [];\n\n for (const [tableName, table] of tableEntries) {\n const colEntries = Object.entries(table.columns).sort(([a], [b]) => a.localeCompare(b));\n const colParts: string[] = [];\n\n for (const [colName, col] of colEntries) {\n const colType = computeColumnType(storage, col, side, codecLookup);\n colParts.push(`readonly ${serializeObjectKey(colName)}: ${colType}`);\n }\n\n const colMap = colParts.length > 0 ? `{ ${colParts.join('; ')} }` : '{}';\n tableParts.push(`readonly ${serializeObjectKey(tableName)}: ${colMap}`);\n }\n\n const tableMap = tableParts.length > 0 ? `{ ${tableParts.join('; ')} }` : '{}';\n nsParts.push(`readonly ${serializeObjectKey(nsId)}: ${tableMap}`);\n }\n\n return `{ ${nsParts.join('; ')} }`;\n}\n\nfunction generateDocumentScopedStorageTypesType(types: SqlStorage['types']): string | undefined {\n if (!types || Object.keys(types).length === 0) {\n return undefined;\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n const codecInstanceShape = typeInstance as Partial<StorageTypeInstance>;\n if (\n typeof codecInstanceShape.codecId !== 'string' ||\n typeof codecInstanceShape.nativeType !== 'string'\n ) {\n throw new Error(\n `Unknown storage type kind for \"${typeName}\" in document-scoped storage.types; expected a codec-instance triple.`,\n );\n }\n const codecId = serializeValue(codecInstanceShape.codecId);\n const nativeType = serializeValue(codecInstanceShape.nativeType);\n const typeParamsStr = serializeTypeParamsLiteral(codecInstanceShape.typeParams);\n typeEntries.push(\n `readonly ${typeName}: { readonly kind: 'codec-instance'; readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,\n );\n }\n\n return `{ ${typeEntries.join('; ')} }`;\n}\n\n/**\n * Literalizes the `valueSet` entries slot — a core SQL entity kind (alongside\n * `table`), not a pack-contributed one, so naming it here isn't a\n * family→target layering leak. This is the only non-`table` entries slot with\n * a type-level consumer (`db.nativeEnums`, `packages/3-extensions/postgres`):\n * pack-contributed slots (`role`, `policy`, `native_enum`, …) have none and\n * are not emitted.\n */\nfunction generateValueSetBlockType(valueSets: Readonly<Record<string, StorageValueSet>>): string {\n const entries = Object.entries(valueSets)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, valueSet]) => `readonly ${serializeObjectKey(name)}: ${serializeValue(valueSet)}`);\n return `{ ${entries.join('; ')} }`;\n}\n\nfunction namespaceSerializedKind(ns: Namespace): string {\n const kind = ns.kind;\n if (kind === 'schema') {\n const id = ns.id;\n const lit = id === UNBOUND_NAMESPACE_ID ? 'postgres-unbound-schema' : 'postgres-schema';\n return `readonly kind: '${lit}'`;\n }\n if (typeof kind === 'string') {\n return `readonly kind: ${serializeValue(kind)}`;\n }\n throw new Error(\n `Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`,\n );\n}\n\nfunction generateTableLiteralType(table: StorageTable): string {\n const columns: string[] = [];\n for (const [colName, col] of Object.entries(table.columns)) {\n const nullable = col.nullable ? 'true' : 'false';\n const nativeType = serializeValue(col.nativeType);\n const codecId = serializeValue(col.codecId);\n const defaultSpec = col.default\n ? col.default.kind === 'literal'\n ? `; readonly default: { readonly kind: 'literal'; readonly value: DefaultLiteralValue<${codecId}, ${serializeValue(\n col.default.value,\n )}> }`\n : `; readonly default: { readonly kind: 'function'; readonly expression: ${serializeValue(\n col.default.expression,\n )} }`\n : '';\n const typeParamsSpec =\n col.typeParams && Object.keys(col.typeParams).length > 0\n ? `; readonly typeParams: ${serializeTypeParamsLiteral(col.typeParams)}`\n : '';\n const typeRefSpec = col.typeRef ? `; readonly typeRef: ${serializeValue(col.typeRef)}` : '';\n columns.push(\n `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable}${defaultSpec}${typeParamsSpec}${typeRefSpec} }`,\n );\n }\n\n const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];\n\n if (table.primaryKey) {\n const pkCols = table.primaryKey.columns.map((c) => serializeValue(c)).join(', ');\n const pkParts = [`readonly columns: readonly [${pkCols}]`];\n if (table.primaryKey.name) {\n pkParts.push(`readonly name: ${serializeValue(table.primaryKey.name)}`);\n }\n tableParts.push(`primaryKey: { ${pkParts.join('; ')} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => serializeValue(c)).join(', ');\n const parts = [`readonly columns: readonly [${cols}]`];\n if (u.name) {\n parts.push(`readonly name: ${serializeValue(u.name)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const parts = [`readonly name: ${serializeValue(i.name)}`];\n if (i.prefix !== undefined) {\n parts.push(`readonly prefix: ${serializeValue(i.prefix)}`);\n }\n if (i.columns !== undefined) {\n parts.push(\n `readonly columns: readonly [${i.columns.map((c: string) => serializeValue(c)).join(', ')}]`,\n );\n }\n if (i.expression !== undefined) {\n parts.push(`readonly expression: ${serializeValue(i.expression)}`);\n }\n if (i.where !== undefined) {\n parts.push(`readonly where: ${serializeValue(i.where)}`);\n }\n parts.push(`readonly unique: ${i.unique}`);\n if (i.type !== undefined) {\n parts.push(`readonly type: ${serializeValue(i.type)}`);\n }\n if (i.options !== undefined) {\n parts.push(`readonly options: ${serializeValue(i.options)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`indexes: readonly [${indexes}]`);\n\n const fks = table.foreignKeys\n .map((fk) => {\n const srcCols = fk.source.columns.map((c: string) => serializeValue(c)).join(', ');\n const tgtCols = fk.target.columns.map((c: string) => serializeValue(c)).join(', ');\n const srcRef = `{ readonly namespaceId: ${serializeNamespaceId(String(fk.source.namespaceId))}; readonly tableName: ${serializeValue(fk.source.tableName)}; readonly columns: readonly [${srcCols}] }`;\n const tgtRef = `{ readonly namespaceId: ${serializeNamespaceId(String(fk.target.namespaceId))}; readonly tableName: ${serializeValue(fk.target.tableName)}; readonly columns: readonly [${tgtCols}] }`;\n const parts = [`readonly source: ${srcRef}`, `readonly target: ${tgtRef}`];\n if (fk.name) {\n parts.push(`readonly name: ${serializeValue(fk.name)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`foreignKeys: readonly [${fks}]`);\n\n return `{ ${tableParts.join('; ')} }`;\n}\n\nfunction generateTablesMapType(tables: Readonly<Record<string, StorageTable>>): string {\n const tableEntries: string[] = [];\n for (const [tableName, table] of Object.entries(tables).sort(([a], [b]) => a.localeCompare(b))) {\n tableEntries.push(`readonly ${tableName}: ${generateTableLiteralType(table)}`);\n }\n if (tableEntries.length === 0) {\n // Empty namespaces must emit `{}` (whose `keyof` is `never`), not\n // `Record<string, never>` (whose `keyof` is `string`). The latter\n // collapses `Db<C>` to a string-indexed shape and erases literal\n // table-name inference at every consumer site that walks all\n // namespaces (e.g. `db.sql.<tableName>`).\n return '{}';\n }\n return `{ ${tableEntries.join('; ')} }`;\n}\n\nfunction generateStorageNamespacesType(namespaces: SqlStorage['namespaces']): string {\n const entries = Object.entries(namespaces ?? {}).sort(([a], [b]) => a.localeCompare(b));\n if (entries.length === 0) {\n return 'Record<string, never>';\n }\n const parts: string[] = [];\n for (const [name, ns] of entries) {\n const kindSuffix = `; ${namespaceSerializedKind(ns)}`;\n const tablesType = generateTablesMapType(\n (ns.entries.table ?? {}) as Readonly<Record<string, StorageTable>>,\n );\n const entriesParts = [`readonly table: ${tablesType}`];\n const valueSetEntries = ns.entries.valueSet;\n if (valueSetEntries !== undefined && Object.keys(valueSetEntries).length > 0) {\n entriesParts.push(`readonly valueSet: ${generateValueSetBlockType(valueSetEntries)}`);\n }\n const entriesType = `{ ${entriesParts.join('; ')} }`;\n parts.push(\n `readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly entries: ${entriesType} }`,\n );\n }\n return `{ ${parts.join('; ')} }`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/errors.ts","../src/index.ts"],"sourcesContent":["import type { StructuredError, StructuredErrorOptions } from '@prisma-next/utils/structured-error';\nimport { structuredError } from '@prisma-next/utils/structured-error';\n\ntype SqlEmitterErrorCode =\n | 'CONTRACT.NAME_DUPLICATE'\n | 'CONTRACT.NAMESPACE_INVALID'\n | 'CONTRACT.TYPE_UNKNOWN'\n | 'CONTRACT.VALIDATION_FAILED';\n\nexport function sqlEmitterError(\n code: SqlEmitterErrorCode,\n message: string,\n options?: StructuredErrorOptions,\n): StructuredError {\n return structuredError(code, message, options);\n}\n\nexport function sqlEmitterValidationError(\n message: string,\n meta: Record<string, unknown>,\n): StructuredError {\n return sqlEmitterError('CONTRACT.VALIDATION_FAILED', message, {\n why: 'The contract given to the SQL emitter failed structural validation.',\n fix: 'Regenerate the contract from its authoring source; do not hand-edit contract JSON.',\n meta,\n });\n}\n","import type {\n Contract,\n ContractModel,\n ContractModelBase,\n JsonValue,\n} from '@prisma-next/contract/types';\nimport {\n renderValueSetType,\n serializeNamespaceId,\n serializeObjectKey,\n serializeValue,\n} from '@prisma-next/emitter/domain-type-generation';\nimport { isSafeTypeExpression } from '@prisma-next/emitter/type-expression-safety';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type {\n GenerateContractTypesOptions,\n ValidationContext,\n} from '@prisma-next/framework-components/emission';\nimport {\n entityAt,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport type {\n SqlModelStorage,\n SqlStorage,\n StorageColumn,\n StorageTable,\n StorageTypeInstance,\n StorageValueSet,\n} from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { sqlEmitterError, sqlEmitterValidationError } from './errors';\n\nfunction serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return 'Record<string, never>';\n }\n\n const entries: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n entries.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);\n }\n\n return `{ ${entries.join('; ')} }`;\n}\n\nexport const sqlEmission = {\n id: 'sql',\n\n validateTypes(contract: Contract, _ctx: ValidationContext): void {\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n return;\n }\n\n const typeIdRegex = /^([^/]+)\\/([^@]+)@(\\d+)$/;\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n for (const [colName, colUnknown] of Object.entries(table.columns)) {\n const col = colUnknown as { codecId?: string };\n const codecId = col.codecId;\n if (!codecId) {\n throw sqlEmitterValidationError(\n `Column \"${colName}\" in table \"${tableName}\" is missing codecId`,\n { table: tableName, column: colName },\n );\n }\n\n const match = codecId.match(typeIdRegex);\n if (!match?.[1]) {\n throw sqlEmitterValidationError(\n `Column \"${colName}\" in table \"${tableName}\" has invalid codec ID format \"${codecId}\". Expected format: ns/name@version`,\n { table: tableName, column: colName, codecId },\n );\n }\n }\n }\n }\n },\n\n validateStructure(contract: Contract): void {\n if (contract.targetFamily !== 'sql') {\n throw sqlEmitterValidationError(\n `Expected targetFamily \"sql\", got \"${contract.targetFamily}\"`,\n { targetFamily: contract.targetFamily },\n );\n }\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n throw sqlEmitterValidationError('SQL contract must have storage.namespaces', {});\n }\n\n const tableNamesSeenAcrossNamespaces = new Map<string, string>();\n for (const [nsId, ns] of Object.entries(storage.namespaces)) {\n for (const tableName of Object.keys(ns.entries.table ?? {})) {\n const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);\n if (existingNs !== undefined && existingNs !== nsId) {\n throw sqlEmitterError(\n 'CONTRACT.NAME_DUPLICATE',\n `Duplicate table name \"${tableName}\" in namespaces \"${existingNs}\" and \"${nsId}\"`,\n {\n why: 'Two SQL namespaces declare a table with the same name, which is ambiguous for emission.',\n fix: 'Rename one of the tables so every table name is unique across namespaces.',\n meta: { table: tableName, namespaces: [existingNs, nsId] },\n },\n );\n }\n tableNamesSeenAcrossNamespaces.set(tableName, nsId);\n }\n }\n\n const tableNames = new Set<string>();\n for (const ns of Object.values(storage.namespaces)) {\n for (const t of Object.keys(ns.entries.table ?? {})) {\n tableNames.add(t);\n }\n }\n\n for (const [namespaceId, domainNs] of Object.entries(contract.domain.namespaces)) {\n const models = domainNs.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const qualifiedName = `${namespaceId}:${modelName}`;\n if (!model.storage?.table) {\n throw sqlEmitterValidationError(`Model \"${qualifiedName}\" is missing storage.table`, {\n model: qualifiedName,\n });\n }\n if (!model.storage.namespaceId) {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" is missing storage.namespaceId`,\n { model: qualifiedName },\n );\n }\n if (model.storage.namespaceId !== namespaceId) {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" storage.namespaceId \"${model.storage.namespaceId}\" does not match domain namespace \"${namespaceId}\"`,\n {\n model: qualifiedName,\n storageNamespaceId: model.storage.namespaceId,\n domainNamespaceId: namespaceId,\n },\n );\n }\n\n const tableName = model.storage.table;\n const table = entityAt<StorageTable>(storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" references non-existent table \"${namespaceId}.${tableName}\"`,\n { model: qualifiedName, table: `${namespaceId}.${tableName}` },\n );\n }\n const columnNames = new Set(Object.keys(table.columns));\n const storageFields = model.storage.fields;\n if (!storageFields || Object.keys(storageFields).length === 0) {\n throw sqlEmitterValidationError(`Model \"${qualifiedName}\" is missing storage.fields`, {\n model: qualifiedName,\n });\n }\n\n for (const [fieldName, field] of Object.entries(storageFields)) {\n if (!field.column) {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" field \"${fieldName}\" is missing column property`,\n { model: qualifiedName, field: fieldName },\n );\n }\n\n if (!columnNames.has(field.column)) {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${tableName}\"`,\n { model: qualifiedName, field: fieldName, column: field.column, table: tableName },\n );\n }\n }\n\n if (!model.relations || typeof model.relations !== 'object') {\n throw sqlEmitterValidationError(\n `Model \"${qualifiedName}\" is missing required field \"relations\" (must be an object)`,\n { model: qualifiedName },\n );\n }\n }\n }\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n const columnNames = new Set(Object.keys(table.columns));\n\n if (!Array.isArray(table.uniques)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" is missing required field \"uniques\" (must be an array)`,\n { table: tableName },\n );\n }\n if (!Array.isArray(table.indexes)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" is missing required field \"indexes\" (must be an array)`,\n { table: tableName },\n );\n }\n if (!Array.isArray(table.foreignKeys)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" is missing required field \"foreignKeys\" (must be an array)`,\n { table: tableName },\n );\n }\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n { table: tableName, column: colName },\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 sqlEmitterValidationError(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n { table: tableName, column: colName },\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 sqlEmitterValidationError(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n { table: tableName, column: colName },\n );\n }\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.source.columns) {\n if (!columnNames.has(colName)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n { table: tableName, column: colName },\n );\n }\n }\n\n const referencedTable = entityAt<StorageTable>(storage, {\n namespaceId: fk.target.namespaceId,\n entityKind: 'table',\n entityName: fk.target.tableName,\n });\n if (!referencedTable) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.target.tableName}\" in namespace \"${fk.target.namespaceId}\"`,\n {\n table: tableName,\n targetTable: fk.target.tableName,\n targetNamespace: fk.target.namespaceId,\n },\n );\n }\n\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.target.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.target.tableName}\"`,\n { table: tableName, column: colName, targetTable: fk.target.tableName },\n );\n }\n }\n\n if (fk.source.columns.length !== fk.target.columns.length) {\n throw sqlEmitterValidationError(\n `Table \"${tableName}\" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`,\n {\n table: tableName,\n sourceColumnCount: fk.source.columns.length,\n targetColumnCount: fk.target.columns.length,\n },\n );\n }\n }\n }\n }\n },\n\n generateStorageType(contract: Contract, storageHashTypeName: string): string {\n const storage = contract.storage as unknown as SqlStorage;\n const namespacesType = generateStorageNamespacesType(storage.namespaces);\n const docTypes = generateDocumentScopedStorageTypesType(storage.types);\n const typesClause = docTypes === undefined ? '' : `; readonly types: ${docTypes}`;\n return `{ readonly namespaces: ${namespacesType}${typesClause}; readonly storageHash: ${storageHashTypeName} }`;\n },\n\n generateModelStorageType(_modelName: string, model: ContractModelBase): string {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const tableName = sqlModel.storage.table;\n const storageFields = sqlModel.storage.fields;\n\n const storageParts = [\n `readonly table: ${serializeValue(tableName)}`,\n `readonly namespaceId: ${serializeValue(sqlModel.storage.namespaceId)}`,\n ];\n if (Object.keys(storageFields).length > 0) {\n const fieldParts: string[] = [];\n for (const [fieldName, field] of Object.entries(storageFields)) {\n fieldParts.push(\n `readonly ${serializeObjectKey(fieldName)}: { readonly column: ${serializeValue(field.column)} }`,\n );\n }\n storageParts.push(`readonly fields: { ${fieldParts.join('; ')} }`);\n }\n\n return `{ ${storageParts.join('; ')} }`;\n },\n\n resolveFieldTypeParams(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): Record<string, unknown> | undefined {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage) return undefined;\n\n const tableName = sqlModel.storage.table;\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) return undefined;\n\n const column = table.columns[storageField.column];\n if (!column) return undefined;\n\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n const codecShape = typeInstance as Partial<StorageTypeInstance>;\n return codecShape.typeParams;\n }\n return column.typeParams;\n },\n\n resolveFieldValueSet(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): { readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefined {\n const sqlModel = blindCast<\n ContractModel<SqlModelStorage>,\n 'a sql-family model carries SqlModelStorage in storage'\n >(model);\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage) return undefined;\n\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: sqlModel.storage.table,\n });\n const column = table?.columns[storageField.column];\n if (!column?.valueSet) return undefined;\n\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n if (!valueSet) return undefined;\n\n return { encodedValues: valueSet.values, codecId: column.codecId };\n },\n\n getStorageTypeExports(contract: Contract, codecLookup?: CodecLookup): string | undefined {\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage?.namespaces) return undefined;\n const outputMap = generateStorageColumnTypesMap(storage, 'output', codecLookup);\n const inputMap = generateStorageColumnTypesMap(storage, 'input', codecLookup);\n return [\n `export type StorageColumnTypes = ${outputMap};`,\n `export type StorageColumnInputTypes = ${inputMap};`,\n ].join('\\n');\n },\n\n getFamilyImports(): string[] {\n return [\n 'import type {',\n ' ContractWithTypeMaps,',\n ' TypeMaps as TypeMapsType,',\n \"} from '@prisma-next/sql-contract/types';\",\n ];\n },\n\n getFamilyTypeAliases(options?: GenerateContractTypesOptions): string {\n const queryOperationTypeImports = options?.queryOperationTypeImports ?? [];\n const queryOperationAliases = queryOperationTypeImports\n .filter((imp) => imp.named === 'QueryOperationTypes')\n .map((imp) => `${imp.alias}<CodecTypes>`);\n const queryOperationTypes =\n queryOperationAliases.length > 0\n ? queryOperationAliases.join(' & ')\n : 'Record<string, never>';\n\n return [\n 'export type LaneCodecTypes = CodecTypes;',\n `export type QueryOperationTypes = ${queryOperationTypes};`,\n 'type DefaultLiteralValue<CodecId extends string, _Encoded> =',\n ' CodecId extends keyof CodecTypes',\n \" ? CodecTypes[CodecId]['output']\",\n ' : _Encoded;',\n ].join('\\n');\n },\n\n getTypeMapsExpression(): string {\n return 'TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes, StorageColumnTypes, StorageColumnInputTypes>';\n },\n\n getContractWrapper(contractBaseName: string, typeMapsName: string): string {\n return [\n `export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,\n '',\n \"export type Namespaces = Contract['storage']['namespaces'];\",\n ].join('\\n');\n },\n} as const;\n\ntype ColumnTypeSide = 'output' | 'input';\n\nfunction columnTypeParams(\n storage: SqlStorage,\n column: StorageColumn,\n): Record<string, unknown> | undefined {\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n return blindCast<\n Partial<StorageTypeInstance>,\n 'storage.types entries are codec-instance triples carrying optional typeParams'\n >(typeInstance).typeParams;\n }\n return column.typeParams;\n}\n\nfunction renderRefinedCodecType(\n column: StorageColumn,\n side: ColumnTypeSide,\n params: Record<string, unknown> | undefined,\n codecLookup: CodecLookup | undefined,\n): string {\n if (codecLookup && params && Object.keys(params).length > 0) {\n const rendered =\n side === 'output'\n ? codecLookup.renderOutputTypeFor(column.codecId, params)\n : codecLookup.renderInputTypeFor?.(column.codecId, params);\n if (rendered && isSafeTypeExpression(rendered)) {\n return rendered;\n }\n }\n return `CodecTypes[${serializeValue(column.codecId)}][${serializeValue(side)}]`;\n}\n\nfunction computeColumnType(\n storage: SqlStorage,\n column: StorageColumn,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n let base: string | undefined;\n if (column.valueSet) {\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n base = valueSet\n ? renderValueSetType(valueSet.values, column.codecId, side, codecLookup)\n : undefined;\n }\n if (base === undefined) {\n base = renderRefinedCodecType(column, side, columnTypeParams(storage, column), codecLookup);\n }\n if (column.many === true) base = `ReadonlyArray<${base}>`;\n return column.nullable ? `${base} | null` : base;\n}\n\nfunction generateStorageColumnTypesMap(\n storage: SqlStorage,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n const namespaceEntries = Object.entries(storage.namespaces ?? {}).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n if (namespaceEntries.length === 0) return 'Record<string, never>';\n\n const nsParts: string[] = [];\n for (const [nsId, ns] of namespaceEntries) {\n const tables = blindCast<\n Readonly<Record<string, StorageTable>>,\n 'same pattern as generateTablesMapType below'\n >(ns.entries.table ?? {});\n const tableEntries = Object.entries(tables).sort(([a], [b]) => a.localeCompare(b));\n const tableParts: string[] = [];\n\n for (const [tableName, table] of tableEntries) {\n const colEntries = Object.entries(table.columns).sort(([a], [b]) => a.localeCompare(b));\n const colParts: string[] = [];\n\n for (const [colName, col] of colEntries) {\n const colType = computeColumnType(storage, col, side, codecLookup);\n colParts.push(`readonly ${serializeObjectKey(colName)}: ${colType}`);\n }\n\n const colMap = colParts.length > 0 ? `{ ${colParts.join('; ')} }` : '{}';\n tableParts.push(`readonly ${serializeObjectKey(tableName)}: ${colMap}`);\n }\n\n const tableMap = tableParts.length > 0 ? `{ ${tableParts.join('; ')} }` : '{}';\n nsParts.push(`readonly ${serializeObjectKey(nsId)}: ${tableMap}`);\n }\n\n return `{ ${nsParts.join('; ')} }`;\n}\n\nfunction generateDocumentScopedStorageTypesType(types: SqlStorage['types']): string | undefined {\n if (!types || Object.keys(types).length === 0) {\n return undefined;\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n const codecInstanceShape = typeInstance as Partial<StorageTypeInstance>;\n if (\n typeof codecInstanceShape.codecId !== 'string' ||\n typeof codecInstanceShape.nativeType !== 'string'\n ) {\n throw sqlEmitterError(\n 'CONTRACT.TYPE_UNKNOWN',\n `Unknown storage type kind for \"${typeName}\" in document-scoped storage.types; expected a codec-instance triple.`,\n {\n why: 'A storage.types entry is not a codec-instance triple, so its column type cannot be emitted.',\n fix: 'Regenerate the contract from its authoring source; storage.types entries must carry codecId and nativeType.',\n meta: { type: typeName },\n },\n );\n }\n const codecId = serializeValue(codecInstanceShape.codecId);\n const nativeType = serializeValue(codecInstanceShape.nativeType);\n const typeParamsStr = serializeTypeParamsLiteral(codecInstanceShape.typeParams);\n typeEntries.push(\n `readonly ${typeName}: { readonly kind: 'codec-instance'; readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,\n );\n }\n\n return `{ ${typeEntries.join('; ')} }`;\n}\n\n/**\n * Literalizes the `valueSet` entries slot — a core SQL entity kind (alongside\n * `table`), not a pack-contributed one, so naming it here isn't a\n * family→target layering leak. This is the only non-`table` entries slot with\n * a type-level consumer (`db.nativeEnums`, `packages/3-extensions/postgres`):\n * pack-contributed slots (`role`, `policy`, `native_enum`, …) have none and\n * are not emitted.\n */\nfunction generateValueSetBlockType(valueSets: Readonly<Record<string, StorageValueSet>>): string {\n const entries = Object.entries(valueSets)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, valueSet]) => `readonly ${serializeObjectKey(name)}: ${serializeValue(valueSet)}`);\n return `{ ${entries.join('; ')} }`;\n}\n\nfunction namespaceSerializedKind(ns: Namespace): string {\n const kind = ns.kind;\n if (kind === 'schema') {\n const id = ns.id;\n const lit = id === UNBOUND_NAMESPACE_ID ? 'postgres-unbound-schema' : 'postgres-schema';\n return `readonly kind: '${lit}'`;\n }\n if (typeof kind === 'string') {\n return `readonly kind: ${serializeValue(kind)}`;\n }\n throw sqlEmitterError(\n 'CONTRACT.NAMESPACE_INVALID',\n `Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`,\n {\n why: 'The namespace is not a target concretion, so the emitter cannot serialize its kind.',\n fix: 'Regenerate the contract with a target pack that materializes every namespace as a target concretion.',\n meta: { namespace: ns.id },\n },\n );\n}\n\nfunction generateTableLiteralType(table: StorageTable): string {\n const columns: string[] = [];\n for (const [colName, col] of Object.entries(table.columns)) {\n const nullable = col.nullable ? 'true' : 'false';\n const nativeType = serializeValue(col.nativeType);\n const codecId = serializeValue(col.codecId);\n const defaultSpec = col.default\n ? col.default.kind === 'literal'\n ? `; readonly default: { readonly kind: 'literal'; readonly value: DefaultLiteralValue<${codecId}, ${serializeValue(\n col.default.value,\n )}> }`\n : `; readonly default: { readonly kind: 'function'; readonly expression: ${serializeValue(\n col.default.expression,\n )} }`\n : '';\n const typeParamsSpec =\n col.typeParams && Object.keys(col.typeParams).length > 0\n ? `; readonly typeParams: ${serializeTypeParamsLiteral(col.typeParams)}`\n : '';\n const typeRefSpec = col.typeRef ? `; readonly typeRef: ${serializeValue(col.typeRef)}` : '';\n columns.push(\n `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable}${defaultSpec}${typeParamsSpec}${typeRefSpec} }`,\n );\n }\n\n const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];\n\n if (table.primaryKey) {\n const pkCols = table.primaryKey.columns.map((c) => serializeValue(c)).join(', ');\n const pkParts = [`readonly columns: readonly [${pkCols}]`];\n if (table.primaryKey.name) {\n pkParts.push(`readonly name: ${serializeValue(table.primaryKey.name)}`);\n }\n tableParts.push(`primaryKey: { ${pkParts.join('; ')} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => serializeValue(c)).join(', ');\n const parts = [`readonly columns: readonly [${cols}]`];\n if (u.name) {\n parts.push(`readonly name: ${serializeValue(u.name)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const parts = [`readonly name: ${serializeValue(i.name)}`];\n if (i.prefix !== undefined) {\n parts.push(`readonly prefix: ${serializeValue(i.prefix)}`);\n }\n if (i.columns !== undefined) {\n parts.push(\n `readonly columns: readonly [${i.columns.map((c: string) => serializeValue(c)).join(', ')}]`,\n );\n }\n if (i.expression !== undefined) {\n parts.push(`readonly expression: ${serializeValue(i.expression)}`);\n }\n if (i.where !== undefined) {\n parts.push(`readonly where: ${serializeValue(i.where)}`);\n }\n parts.push(`readonly unique: ${i.unique}`);\n if (i.type !== undefined) {\n parts.push(`readonly type: ${serializeValue(i.type)}`);\n }\n if (i.options !== undefined) {\n parts.push(`readonly options: ${serializeValue(i.options)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`indexes: readonly [${indexes}]`);\n\n const fks = table.foreignKeys\n .map((fk) => {\n const srcCols = fk.source.columns.map((c: string) => serializeValue(c)).join(', ');\n const tgtCols = fk.target.columns.map((c: string) => serializeValue(c)).join(', ');\n const srcRef = `{ readonly namespaceId: ${serializeNamespaceId(String(fk.source.namespaceId))}; readonly tableName: ${serializeValue(fk.source.tableName)}; readonly columns: readonly [${srcCols}] }`;\n const tgtRef = `{ readonly namespaceId: ${serializeNamespaceId(String(fk.target.namespaceId))}; readonly tableName: ${serializeValue(fk.target.tableName)}; readonly columns: readonly [${tgtCols}] }`;\n const parts = [`readonly source: ${srcRef}`, `readonly target: ${tgtRef}`];\n if (fk.name) {\n parts.push(`readonly name: ${serializeValue(fk.name)}`);\n }\n return `{ ${parts.join('; ')} }`;\n })\n .join(', ');\n tableParts.push(`foreignKeys: readonly [${fks}]`);\n\n return `{ ${tableParts.join('; ')} }`;\n}\n\nfunction generateTablesMapType(tables: Readonly<Record<string, StorageTable>>): string {\n const tableEntries: string[] = [];\n for (const [tableName, table] of Object.entries(tables).sort(([a], [b]) => a.localeCompare(b))) {\n tableEntries.push(`readonly ${tableName}: ${generateTableLiteralType(table)}`);\n }\n if (tableEntries.length === 0) {\n // Empty namespaces must emit `{}` (whose `keyof` is `never`), not\n // `Record<string, never>` (whose `keyof` is `string`). The latter\n // collapses `Db<C>` to a string-indexed shape and erases literal\n // table-name inference at every consumer site that walks all\n // namespaces (e.g. `db.sql.<tableName>`).\n return '{}';\n }\n return `{ ${tableEntries.join('; ')} }`;\n}\n\nfunction generateStorageNamespacesType(namespaces: SqlStorage['namespaces']): string {\n const entries = Object.entries(namespaces ?? {}).sort(([a], [b]) => a.localeCompare(b));\n if (entries.length === 0) {\n return 'Record<string, never>';\n }\n const parts: string[] = [];\n for (const [name, ns] of entries) {\n const kindSuffix = `; ${namespaceSerializedKind(ns)}`;\n const tablesType = generateTablesMapType(\n (ns.entries.table ?? {}) as Readonly<Record<string, StorageTable>>,\n );\n const entriesParts = [`readonly table: ${tablesType}`];\n const valueSetEntries = ns.entries.valueSet;\n if (valueSetEntries !== undefined && Object.keys(valueSetEntries).length > 0) {\n entriesParts.push(`readonly valueSet: ${generateValueSetBlockType(valueSetEntries)}`);\n }\n const entriesType = `{ ${entriesParts.join('; ')} }`;\n parts.push(\n `readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly entries: ${entriesType} }`,\n );\n }\n return `{ ${parts.join('; ')} }`;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@prisma-next/sql-contract-emitter",
3
- "version": "0.16.0-dev.30",
3
+ "version": "0.16.0-dev.31",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "SQL emitter hook for Prisma Next",
8
8
  "dependencies": {
9
- "@prisma-next/contract": "0.16.0-dev.30",
10
- "@prisma-next/emitter": "0.16.0-dev.30",
11
- "@prisma-next/framework-components": "0.16.0-dev.30",
12
- "@prisma-next/sql-contract": "0.16.0-dev.30",
13
- "@prisma-next/utils": "0.16.0-dev.30"
9
+ "@prisma-next/contract": "0.16.0-dev.31",
10
+ "@prisma-next/emitter": "0.16.0-dev.31",
11
+ "@prisma-next/framework-components": "0.16.0-dev.31",
12
+ "@prisma-next/sql-contract": "0.16.0-dev.31",
13
+ "@prisma-next/utils": "0.16.0-dev.31"
14
14
  },
15
15
  "devDependencies": {
16
- "@prisma-next/test-utils": "0.16.0-dev.30",
17
- "@prisma-next/tsconfig": "0.16.0-dev.30",
18
- "@prisma-next/tsdown": "0.16.0-dev.30",
16
+ "@prisma-next/test-utils": "0.16.0-dev.31",
17
+ "@prisma-next/tsconfig": "0.16.0-dev.31",
18
+ "@prisma-next/tsdown": "0.16.0-dev.31",
19
19
  "tsdown": "0.22.8",
20
20
  "typescript": "5.9.3",
21
21
  "vitest": "4.1.10"
package/src/errors.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { StructuredError, StructuredErrorOptions } from '@prisma-next/utils/structured-error';
2
+ import { structuredError } from '@prisma-next/utils/structured-error';
3
+
4
+ type SqlEmitterErrorCode =
5
+ | 'CONTRACT.NAME_DUPLICATE'
6
+ | 'CONTRACT.NAMESPACE_INVALID'
7
+ | 'CONTRACT.TYPE_UNKNOWN'
8
+ | 'CONTRACT.VALIDATION_FAILED';
9
+
10
+ export function sqlEmitterError(
11
+ code: SqlEmitterErrorCode,
12
+ message: string,
13
+ options?: StructuredErrorOptions,
14
+ ): StructuredError {
15
+ return structuredError(code, message, options);
16
+ }
17
+
18
+ export function sqlEmitterValidationError(
19
+ message: string,
20
+ meta: Record<string, unknown>,
21
+ ): StructuredError {
22
+ return sqlEmitterError('CONTRACT.VALIDATION_FAILED', message, {
23
+ why: 'The contract given to the SQL emitter failed structural validation.',
24
+ fix: 'Regenerate the contract from its authoring source; do not hand-edit contract JSON.',
25
+ meta,
26
+ });
27
+ }
package/src/index.ts CHANGED
@@ -30,6 +30,7 @@ import type {
30
30
  StorageValueSet,
31
31
  } from '@prisma-next/sql-contract/types';
32
32
  import { blindCast } from '@prisma-next/utils/casts';
33
+ import { sqlEmitterError, sqlEmitterValidationError } from './errors';
33
34
 
34
35
  function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {
35
36
  if (!params || Object.keys(params).length === 0) {
@@ -61,13 +62,17 @@ export const sqlEmission = {
61
62
  const col = colUnknown as { codecId?: string };
62
63
  const codecId = col.codecId;
63
64
  if (!codecId) {
64
- throw new Error(`Column "${colName}" in table "${tableName}" is missing codecId`);
65
+ throw sqlEmitterValidationError(
66
+ `Column "${colName}" in table "${tableName}" is missing codecId`,
67
+ { table: tableName, column: colName },
68
+ );
65
69
  }
66
70
 
67
71
  const match = codecId.match(typeIdRegex);
68
72
  if (!match?.[1]) {
69
- throw new Error(
73
+ throw sqlEmitterValidationError(
70
74
  `Column "${colName}" in table "${tableName}" has invalid codec ID format "${codecId}". Expected format: ns/name@version`,
75
+ { table: tableName, column: colName, codecId },
71
76
  );
72
77
  }
73
78
  }
@@ -77,12 +82,15 @@ export const sqlEmission = {
77
82
 
78
83
  validateStructure(contract: Contract): void {
79
84
  if (contract.targetFamily !== 'sql') {
80
- throw new Error(`Expected targetFamily "sql", got "${contract.targetFamily}"`);
85
+ throw sqlEmitterValidationError(
86
+ `Expected targetFamily "sql", got "${contract.targetFamily}"`,
87
+ { targetFamily: contract.targetFamily },
88
+ );
81
89
  }
82
90
 
83
91
  const storage = contract.storage as unknown as SqlStorage | undefined;
84
92
  if (!storage?.namespaces) {
85
- throw new Error('SQL contract must have storage.namespaces');
93
+ throw sqlEmitterValidationError('SQL contract must have storage.namespaces', {});
86
94
  }
87
95
 
88
96
  const tableNamesSeenAcrossNamespaces = new Map<string, string>();
@@ -90,8 +98,14 @@ export const sqlEmission = {
90
98
  for (const tableName of Object.keys(ns.entries.table ?? {})) {
91
99
  const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
92
100
  if (existingNs !== undefined && existingNs !== nsId) {
93
- throw new Error(
101
+ throw sqlEmitterError(
102
+ 'CONTRACT.NAME_DUPLICATE',
94
103
  `Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`,
104
+ {
105
+ why: 'Two SQL namespaces declare a table with the same name, which is ambiguous for emission.',
106
+ fix: 'Rename one of the tables so every table name is unique across namespaces.',
107
+ meta: { table: tableName, namespaces: [existingNs, nsId] },
108
+ },
95
109
  );
96
110
  }
97
111
  tableNamesSeenAcrossNamespaces.set(tableName, nsId);
@@ -110,14 +124,24 @@ export const sqlEmission = {
110
124
  for (const [modelName, model] of Object.entries(models)) {
111
125
  const qualifiedName = `${namespaceId}:${modelName}`;
112
126
  if (!model.storage?.table) {
113
- throw new Error(`Model "${qualifiedName}" is missing storage.table`);
127
+ throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing storage.table`, {
128
+ model: qualifiedName,
129
+ });
114
130
  }
115
131
  if (!model.storage.namespaceId) {
116
- throw new Error(`Model "${qualifiedName}" is missing storage.namespaceId`);
132
+ throw sqlEmitterValidationError(
133
+ `Model "${qualifiedName}" is missing storage.namespaceId`,
134
+ { model: qualifiedName },
135
+ );
117
136
  }
118
137
  if (model.storage.namespaceId !== namespaceId) {
119
- throw new Error(
138
+ throw sqlEmitterValidationError(
120
139
  `Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`,
140
+ {
141
+ model: qualifiedName,
142
+ storageNamespaceId: model.storage.namespaceId,
143
+ domainNamespaceId: namespaceId,
144
+ },
121
145
  );
122
146
  }
123
147
 
@@ -128,33 +152,39 @@ export const sqlEmission = {
128
152
  entityName: tableName,
129
153
  });
130
154
  if (!table) {
131
- throw new Error(
155
+ throw sqlEmitterValidationError(
132
156
  `Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`,
157
+ { model: qualifiedName, table: `${namespaceId}.${tableName}` },
133
158
  );
134
159
  }
135
160
  const columnNames = new Set(Object.keys(table.columns));
136
161
  const storageFields = model.storage.fields;
137
162
  if (!storageFields || Object.keys(storageFields).length === 0) {
138
- throw new Error(`Model "${qualifiedName}" is missing storage.fields`);
163
+ throw sqlEmitterValidationError(`Model "${qualifiedName}" is missing storage.fields`, {
164
+ model: qualifiedName,
165
+ });
139
166
  }
140
167
 
141
168
  for (const [fieldName, field] of Object.entries(storageFields)) {
142
169
  if (!field.column) {
143
- throw new Error(
170
+ throw sqlEmitterValidationError(
144
171
  `Model "${qualifiedName}" field "${fieldName}" is missing column property`,
172
+ { model: qualifiedName, field: fieldName },
145
173
  );
146
174
  }
147
175
 
148
176
  if (!columnNames.has(field.column)) {
149
- throw new Error(
177
+ throw sqlEmitterValidationError(
150
178
  `Model "${qualifiedName}" field "${fieldName}" references non-existent column "${field.column}" in table "${tableName}"`,
179
+ { model: qualifiedName, field: fieldName, column: field.column, table: tableName },
151
180
  );
152
181
  }
153
182
  }
154
183
 
155
184
  if (!model.relations || typeof model.relations !== 'object') {
156
- throw new Error(
185
+ throw sqlEmitterValidationError(
157
186
  `Model "${qualifiedName}" is missing required field "relations" (must be an object)`,
187
+ { model: qualifiedName },
158
188
  );
159
189
  }
160
190
  }
@@ -165,26 +195,30 @@ export const sqlEmission = {
165
195
  const columnNames = new Set(Object.keys(table.columns));
166
196
 
167
197
  if (!Array.isArray(table.uniques)) {
168
- throw new Error(
198
+ throw sqlEmitterValidationError(
169
199
  `Table "${tableName}" is missing required field "uniques" (must be an array)`,
200
+ { table: tableName },
170
201
  );
171
202
  }
172
203
  if (!Array.isArray(table.indexes)) {
173
- throw new Error(
204
+ throw sqlEmitterValidationError(
174
205
  `Table "${tableName}" is missing required field "indexes" (must be an array)`,
206
+ { table: tableName },
175
207
  );
176
208
  }
177
209
  if (!Array.isArray(table.foreignKeys)) {
178
- throw new Error(
210
+ throw sqlEmitterValidationError(
179
211
  `Table "${tableName}" is missing required field "foreignKeys" (must be an array)`,
212
+ { table: tableName },
180
213
  );
181
214
  }
182
215
 
183
216
  if (table.primaryKey) {
184
217
  for (const colName of table.primaryKey.columns) {
185
218
  if (!columnNames.has(colName)) {
186
- throw new Error(
219
+ throw sqlEmitterValidationError(
187
220
  `Table "${tableName}" primaryKey references non-existent column "${colName}"`,
221
+ { table: tableName, column: colName },
188
222
  );
189
223
  }
190
224
  }
@@ -193,8 +227,9 @@ export const sqlEmission = {
193
227
  for (const unique of table.uniques) {
194
228
  for (const colName of unique.columns) {
195
229
  if (!columnNames.has(colName)) {
196
- throw new Error(
230
+ throw sqlEmitterValidationError(
197
231
  `Table "${tableName}" unique constraint references non-existent column "${colName}"`,
232
+ { table: tableName, column: colName },
198
233
  );
199
234
  }
200
235
  }
@@ -203,8 +238,9 @@ export const sqlEmission = {
203
238
  for (const index of table.indexes) {
204
239
  for (const colName of index.columns) {
205
240
  if (!columnNames.has(colName)) {
206
- throw new Error(
241
+ throw sqlEmitterValidationError(
207
242
  `Table "${tableName}" index references non-existent column "${colName}"`,
243
+ { table: tableName, column: colName },
208
244
  );
209
245
  }
210
246
  }
@@ -213,8 +249,9 @@ export const sqlEmission = {
213
249
  for (const fk of table.foreignKeys) {
214
250
  for (const colName of fk.source.columns) {
215
251
  if (!columnNames.has(colName)) {
216
- throw new Error(
252
+ throw sqlEmitterValidationError(
217
253
  `Table "${tableName}" foreignKey references non-existent column "${colName}"`,
254
+ { table: tableName, column: colName },
218
255
  );
219
256
  }
220
257
  }
@@ -225,23 +262,34 @@ export const sqlEmission = {
225
262
  entityName: fk.target.tableName,
226
263
  });
227
264
  if (!referencedTable) {
228
- throw new Error(
265
+ throw sqlEmitterValidationError(
229
266
  `Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`,
267
+ {
268
+ table: tableName,
269
+ targetTable: fk.target.tableName,
270
+ targetNamespace: fk.target.namespaceId,
271
+ },
230
272
  );
231
273
  }
232
274
 
233
275
  const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
234
276
  for (const colName of fk.target.columns) {
235
277
  if (!referencedColumnNames.has(colName)) {
236
- throw new Error(
278
+ throw sqlEmitterValidationError(
237
279
  `Table "${tableName}" foreignKey references non-existent column "${colName}" in table "${fk.target.tableName}"`,
280
+ { table: tableName, column: colName, targetTable: fk.target.tableName },
238
281
  );
239
282
  }
240
283
  }
241
284
 
242
285
  if (fk.source.columns.length !== fk.target.columns.length) {
243
- throw new Error(
286
+ throw sqlEmitterValidationError(
244
287
  `Table "${tableName}" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`,
288
+ {
289
+ table: tableName,
290
+ sourceColumnCount: fk.source.columns.length,
291
+ targetColumnCount: fk.target.columns.length,
292
+ },
245
293
  );
246
294
  }
247
295
  }
@@ -521,8 +569,14 @@ function generateDocumentScopedStorageTypesType(types: SqlStorage['types']): str
521
569
  typeof codecInstanceShape.codecId !== 'string' ||
522
570
  typeof codecInstanceShape.nativeType !== 'string'
523
571
  ) {
524
- throw new Error(
572
+ throw sqlEmitterError(
573
+ 'CONTRACT.TYPE_UNKNOWN',
525
574
  `Unknown storage type kind for "${typeName}" in document-scoped storage.types; expected a codec-instance triple.`,
575
+ {
576
+ why: 'A storage.types entry is not a codec-instance triple, so its column type cannot be emitted.',
577
+ fix: 'Regenerate the contract from its authoring source; storage.types entries must carry codecId and nativeType.',
578
+ meta: { type: typeName },
579
+ },
526
580
  );
527
581
  }
528
582
  const codecId = serializeValue(codecInstanceShape.codecId);
@@ -561,8 +615,14 @@ function namespaceSerializedKind(ns: Namespace): string {
561
615
  if (typeof kind === 'string') {
562
616
  return `readonly kind: ${serializeValue(kind)}`;
563
617
  }
564
- throw new Error(
618
+ throw sqlEmitterError(
619
+ 'CONTRACT.NAMESPACE_INVALID',
565
620
  `Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`,
621
+ {
622
+ why: 'The namespace is not a target concretion, so the emitter cannot serialize its kind.',
623
+ fix: 'Regenerate the contract with a target pack that materializes every namespace as a target concretion.',
624
+ meta: { namespace: ns.id },
625
+ },
566
626
  );
567
627
  }
568
628