@prisma-next/sql-contract-emitter 0.12.0-dev.9 → 0.13.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +32 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/src/index.ts +74 -79
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;cAkCa,WAAA;EAAA;qCAGa,QAAA,EAAQ,IAAA,EAAQ,iBAAA;EAAA,uCA6BZ,QAAA;EAAA,yCA2KE,QAAA,EAAQ,mBAAA;EAAA,wDAQK,KAAA,EAAS,aAAA;EAAA,sDAuBhC,SAAA,UACD,KAAA,EACV,aAAA,EAAa,QAAA,EACV,QAAA,KACT,MAAA;EAAA;4CAkD4B,4BAAA;EAAA;0DAwBY,YAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { serializeNamespaceId, serializeObjectKey, serializeValue } from "@prisma-next/emitter/domain-type-generation";
|
|
2
2
|
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
3
3
|
import { isPostgresEnumStorageEntry } from "@prisma-next/sql-contract/types";
|
|
4
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
4
5
|
//#region src/index.ts
|
|
5
6
|
function serializeTypeParamsLiteral(params) {
|
|
6
7
|
if (!params || Object.keys(params).length === 0) return "Record<string, never>";
|
|
@@ -8,39 +9,13 @@ function serializeTypeParamsLiteral(params) {
|
|
|
8
9
|
for (const [key, value] of Object.entries(params)) entries.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);
|
|
9
10
|
return `{ ${entries.join("; ")} }`;
|
|
10
11
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Name-only lookup that walks every namespace until it finds a table
|
|
13
|
-
* with the given name. Survives this slice only for the two model-side
|
|
14
|
-
* call sites whose `SqlModelStorage.table` is still a bare name without
|
|
15
|
-
* a namespace coordinate; both call sites — and this helper — are
|
|
16
|
-
* deleted by TML-2584, which promotes `SqlModelStorage` to carry the
|
|
17
|
-
* model's namespace id so model→table resolution can use explicit
|
|
18
|
-
* coordinates like the FK-ref site already does.
|
|
19
|
-
*/
|
|
20
|
-
function findSqlTable(storage, tableName) {
|
|
21
|
-
for (const [namespaceId, ns] of Object.entries(storage.namespaces)) {
|
|
22
|
-
const table = ns.tables[tableName];
|
|
23
|
-
if (table !== void 0) return {
|
|
24
|
-
table,
|
|
25
|
-
namespaceId
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function assertUniqueSqlTableNames(storage) {
|
|
30
|
-
const seen = /* @__PURE__ */ new Map();
|
|
31
|
-
for (const [namespaceId, ns] of Object.entries(storage.namespaces)) for (const tableName of Object.keys(ns.tables)) {
|
|
32
|
-
const existing = seen.get(tableName);
|
|
33
|
-
if (existing !== void 0 && existing !== namespaceId) throw new Error(`Duplicate table name "${tableName}" in namespaces "${existing}" and "${namespaceId}"`);
|
|
34
|
-
seen.set(tableName, namespaceId);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
12
|
const sqlEmission = {
|
|
38
13
|
id: "sql",
|
|
39
14
|
validateTypes(contract, _ctx) {
|
|
40
15
|
const storage = contract.storage;
|
|
41
16
|
if (!storage?.namespaces) return;
|
|
42
17
|
const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
|
|
43
|
-
for (const ns of Object.values(storage.namespaces)) for (const [tableName, tableUnknown] of Object.entries(ns.
|
|
18
|
+
for (const ns of Object.values(storage.namespaces)) for (const [tableName, tableUnknown] of Object.entries(ns.entries.table)) {
|
|
44
19
|
const table = tableUnknown;
|
|
45
20
|
for (const [colName, colUnknown] of Object.entries(table.columns)) {
|
|
46
21
|
const codecId = colUnknown.codecId;
|
|
@@ -53,18 +28,24 @@ const sqlEmission = {
|
|
|
53
28
|
if (contract.targetFamily !== "sql") throw new Error(`Expected targetFamily "sql", got "${contract.targetFamily}"`);
|
|
54
29
|
const storage = contract.storage;
|
|
55
30
|
if (!storage?.namespaces) throw new Error("SQL contract must have storage.namespaces");
|
|
56
|
-
|
|
31
|
+
const tableNamesSeenAcrossNamespaces = /* @__PURE__ */ new Map();
|
|
32
|
+
for (const [nsId, ns] of Object.entries(storage.namespaces)) for (const tableName of Object.keys(ns.entries.table)) {
|
|
33
|
+
const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
|
|
34
|
+
if (existingNs !== void 0 && existingNs !== nsId) throw new Error(`Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`);
|
|
35
|
+
tableNamesSeenAcrossNamespaces.set(tableName, nsId);
|
|
36
|
+
}
|
|
57
37
|
const tableNames = /* @__PURE__ */ new Set();
|
|
58
|
-
for (const ns of Object.values(storage.namespaces)) for (const t of Object.keys(ns.
|
|
38
|
+
for (const ns of Object.values(storage.namespaces)) for (const t of Object.keys(ns.entries.table)) tableNames.add(t);
|
|
59
39
|
for (const [namespaceId, domainNs] of Object.entries(contract.domain.namespaces)) {
|
|
60
40
|
const models = domainNs.models;
|
|
61
41
|
for (const [modelName, model] of Object.entries(models)) {
|
|
62
42
|
const qualifiedName = `${namespaceId}:${modelName}`;
|
|
63
43
|
if (!model.storage?.table) throw new Error(`Model "${qualifiedName}" is missing storage.table`);
|
|
44
|
+
if (!model.storage.namespaceId) throw new Error(`Model "${qualifiedName}" is missing storage.namespaceId`);
|
|
45
|
+
if (model.storage.namespaceId !== namespaceId) throw new Error(`Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`);
|
|
64
46
|
const tableName = model.storage.table;
|
|
65
|
-
const
|
|
66
|
-
if (!
|
|
67
|
-
const { table } = located;
|
|
47
|
+
const table = storage.namespaces[namespaceId]?.entries.table[tableName];
|
|
48
|
+
if (!table) throw new Error(`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`);
|
|
68
49
|
const columnNames = new Set(Object.keys(table.columns));
|
|
69
50
|
const storageFields = model.storage.fields;
|
|
70
51
|
if (!storageFields || Object.keys(storageFields).length === 0) throw new Error(`Model "${qualifiedName}" is missing storage.fields`);
|
|
@@ -75,7 +56,7 @@ const sqlEmission = {
|
|
|
75
56
|
if (!model.relations || typeof model.relations !== "object") throw new Error(`Model "${qualifiedName}" is missing required field "relations" (must be an object)`);
|
|
76
57
|
}
|
|
77
58
|
}
|
|
78
|
-
for (const ns of Object.values(storage.namespaces)) for (const [tableName, tableUnknown] of Object.entries(ns.
|
|
59
|
+
for (const ns of Object.values(storage.namespaces)) for (const [tableName, tableUnknown] of Object.entries(ns.entries.table)) {
|
|
79
60
|
const table = tableUnknown;
|
|
80
61
|
const columnNames = new Set(Object.keys(table.columns));
|
|
81
62
|
if (!Array.isArray(table.uniques)) throw new Error(`Table "${tableName}" is missing required field "uniques" (must be an array)`);
|
|
@@ -88,7 +69,7 @@ const sqlEmission = {
|
|
|
88
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}"`);
|
|
89
70
|
for (const fk of table.foreignKeys) {
|
|
90
71
|
for (const colName of fk.source.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" foreignKey references non-existent column "${colName}"`);
|
|
91
|
-
const referencedTable = storage.namespaces[fk.target.namespaceId]?.
|
|
72
|
+
const referencedTable = storage.namespaces[fk.target.namespaceId]?.entries.table[fk.target.tableName];
|
|
92
73
|
if (!referencedTable) throw new Error(`Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`);
|
|
93
74
|
const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
|
|
94
75
|
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}"`);
|
|
@@ -106,7 +87,7 @@ const sqlEmission = {
|
|
|
106
87
|
const sqlModel = model;
|
|
107
88
|
const tableName = sqlModel.storage.table;
|
|
108
89
|
const storageFields = sqlModel.storage.fields;
|
|
109
|
-
const storageParts = [`readonly table: ${serializeValue(tableName)}`];
|
|
90
|
+
const storageParts = [`readonly table: ${serializeValue(tableName)}`, `readonly namespaceId: ${serializeValue(sqlModel.storage.namespaceId)}`];
|
|
110
91
|
if (Object.keys(storageFields).length > 0) {
|
|
111
92
|
const fieldParts = [];
|
|
112
93
|
for (const [fieldName, field] of Object.entries(storageFields)) fieldParts.push(`readonly ${serializeObjectKey(fieldName)}: { readonly column: ${serializeValue(field.column)} }`);
|
|
@@ -121,13 +102,15 @@ const sqlEmission = {
|
|
|
121
102
|
const storage = contract.storage;
|
|
122
103
|
if (!storage) return void 0;
|
|
123
104
|
const tableName = sqlModel.storage.table;
|
|
124
|
-
const
|
|
125
|
-
if (!
|
|
126
|
-
const
|
|
105
|
+
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
106
|
+
if (!storageNamespaceId) return void 0;
|
|
107
|
+
const table = storage.namespaces[storageNamespaceId]?.entries.table[tableName];
|
|
108
|
+
if (!table) return void 0;
|
|
109
|
+
const column = table.columns[storageField.column];
|
|
127
110
|
if (!column) return void 0;
|
|
128
111
|
if (column.typeRef) {
|
|
129
|
-
const ns = storage.namespaces[
|
|
130
|
-
const typeInstance = (ns !== void 0
|
|
112
|
+
const ns = storage.namespaces[storageNamespaceId];
|
|
113
|
+
const typeInstance = (ns !== void 0 ? blindCast(ns.entries).type : void 0)?.[column.typeRef] ?? storage.types?.[column.typeRef];
|
|
131
114
|
if (typeInstance === void 0) return void 0;
|
|
132
115
|
if (isPostgresEnumStorageEntry(typeInstance)) return { values: typeInstance.values };
|
|
133
116
|
return typeInstance.typeParams;
|
|
@@ -160,8 +143,7 @@ const sqlEmission = {
|
|
|
160
143
|
return [
|
|
161
144
|
`export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,
|
|
162
145
|
"",
|
|
163
|
-
"export type Namespaces = Contract['storage']['namespaces'];"
|
|
164
|
-
"export type Models = ContractModelsMap<Contract>;"
|
|
146
|
+
"export type Namespaces = Contract['storage']['namespaces'];"
|
|
165
147
|
].join("\n");
|
|
166
148
|
}
|
|
167
149
|
};
|
|
@@ -169,7 +151,7 @@ function generateDocumentScopedStorageTypesType(types) {
|
|
|
169
151
|
if (!types || Object.keys(types).length === 0) return;
|
|
170
152
|
const typeEntries = [];
|
|
171
153
|
for (const [typeName, typeInstance] of Object.entries(types)) {
|
|
172
|
-
if (isPostgresEnumStorageEntry(typeInstance)) throw new Error(`Document-scoped storage.types entry "${typeName}" is a postgres-enum; enums belong under storage.namespaces[namespaceId].
|
|
154
|
+
if (isPostgresEnumStorageEntry(typeInstance)) throw new Error(`Document-scoped storage.types entry "${typeName}" is a postgres-enum; enums belong under storage.namespaces[namespaceId].entries.type`);
|
|
173
155
|
const codecInstanceShape = typeInstance;
|
|
174
156
|
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.`);
|
|
175
157
|
const codecId = serializeValue(codecInstanceShape.codecId);
|
|
@@ -191,13 +173,10 @@ function generatePostgresNamespaceTypesType(types) {
|
|
|
191
173
|
typeEntries.push(`readonly ${serializeObjectKey(typeName)}: { readonly kind: 'postgres-enum'; readonly name: ${name}; readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly values: readonly [${valuesLiteral}] }`);
|
|
192
174
|
continue;
|
|
193
175
|
}
|
|
194
|
-
throw new Error(`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.
|
|
176
|
+
throw new Error(`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.entries.type.`);
|
|
195
177
|
}
|
|
196
178
|
return `{ ${typeEntries.join("; ")} }`;
|
|
197
179
|
}
|
|
198
|
-
function isPostgresSchemaNamespace(ns) {
|
|
199
|
-
return ns.kind === "schema" && "enum" in ns && typeof ns.enum === "object" && ns.enum !== null;
|
|
200
|
-
}
|
|
201
180
|
const SQL_NAMESPACE_KIND_FALLBACK = "sql-namespace";
|
|
202
181
|
function namespaceSerializedKind(ns) {
|
|
203
182
|
const kind = ns.kind;
|
|
@@ -251,9 +230,12 @@ function generateStorageNamespacesType(namespaces) {
|
|
|
251
230
|
const parts = [];
|
|
252
231
|
for (const [name, ns] of entries) {
|
|
253
232
|
const kindSuffix = `; ${namespaceSerializedKind(ns)}`;
|
|
254
|
-
const tablesType = generateTablesMapType(ns.
|
|
255
|
-
const
|
|
256
|
-
|
|
233
|
+
const tablesType = generateTablesMapType(ns.entries.table ?? {});
|
|
234
|
+
const typeSlot = ns.kind === "schema" ? blindCast(blindCast(ns.entries).type) : void 0;
|
|
235
|
+
const entriesParts = [`readonly table: ${tablesType}`];
|
|
236
|
+
if (typeSlot !== void 0) entriesParts.push(`readonly type: ${generatePostgresNamespaceTypesType(typeSlot)}`);
|
|
237
|
+
const entriesType = `{ ${entriesParts.join("; ")} }`;
|
|
238
|
+
parts.push(`readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly entries: ${entriesType} }`);
|
|
257
239
|
}
|
|
258
240
|
return `{ ${parts.join("; ")} }`;
|
|
259
241
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/index.ts"],"sourcesContent":["import type { Contract, ContractModel } from '@prisma-next/contract/types';\nimport {\n serializeNamespaceId,\n serializeObjectKey,\n serializeValue,\n} from '@prisma-next/emitter/domain-type-generation';\nimport type {\n GenerateContractTypesOptions,\n ValidationContext,\n} from '@prisma-next/framework-components/emission';\nimport { type Namespace, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport {\n isPostgresEnumStorageEntry,\n type PostgresEnumStorageEntry,\n type SqlModelStorage,\n type SqlStorage,\n type StorageTable,\n type StorageTypeInstance,\n} from '@prisma-next/sql-contract/types';\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\n/**\n * Name-only lookup that walks every namespace until it finds a table\n * with the given name. Survives this slice only for the two model-side\n * call sites whose `SqlModelStorage.table` is still a bare name without\n * a namespace coordinate; both call sites — and this helper — are\n * deleted by TML-2584, which promotes `SqlModelStorage` to carry the\n * model's namespace id so model→table resolution can use explicit\n * coordinates like the FK-ref site already does.\n */\nfunction findSqlTable(\n storage: SqlStorage,\n tableName: string,\n): { readonly table: StorageTable; readonly namespaceId: string } | undefined {\n for (const [namespaceId, ns] of Object.entries(storage.namespaces)) {\n const table = ns.tables[tableName] as StorageTable | undefined;\n if (table !== undefined) {\n return { table, namespaceId };\n }\n }\n return undefined;\n}\n\nfunction assertUniqueSqlTableNames(storage: SqlStorage): void {\n const seen = new Map<string, string>();\n for (const [namespaceId, ns] of Object.entries(storage.namespaces)) {\n for (const tableName of Object.keys(ns.tables)) {\n const existing = seen.get(tableName);\n if (existing !== undefined && existing !== namespaceId) {\n throw new Error(\n `Duplicate table name \"${tableName}\" in namespaces \"${existing}\" and \"${namespaceId}\"`,\n );\n }\n seen.set(tableName, namespaceId);\n }\n }\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, tableUnknown] of Object.entries(ns.tables)) {\n const table = tableUnknown as StorageTable;\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 assertUniqueSqlTableNames(storage);\n\n const tableNames = new Set<string>();\n for (const ns of Object.values(storage.namespaces)) {\n for (const t of Object.keys(ns.tables)) {\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\n const tableName = model.storage.table;\n const located = findSqlTable(storage, tableName);\n if (!located) {\n throw new Error(`Model \"${qualifiedName}\" references non-existent table \"${tableName}\"`);\n }\n\n const { table } = located;\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, tableUnknown] of Object.entries(ns.tables)) {\n const table = tableUnknown as StorageTable;\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 = storage.namespaces[fk.target.namespaceId]?.tables[\n fk.target.tableName\n ] as StorageTable | undefined;\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: ContractModel): string {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const tableName = sqlModel.storage.table;\n const storageFields = sqlModel.storage.fields;\n\n const storageParts = [`readonly table: ${serializeValue(tableName)}`];\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: ContractModel,\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 located = findSqlTable(storage, tableName);\n if (!located) return undefined;\n\n const column = located.table.columns[storageField.column];\n if (!column) return undefined;\n\n if (column.typeRef) {\n const ns = storage.namespaces[located.namespaceId];\n const nsEnums =\n ns !== undefined && 'enum' in ns\n ? (\n ns as {\n enum?: Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>>;\n }\n ).enum\n : undefined;\n const fromNamespace = nsEnums?.[column.typeRef];\n const typeInstance = fromNamespace ?? storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n if (isPostgresEnumStorageEntry(typeInstance)) {\n return { values: typeInstance.values };\n }\n const codecShape = typeInstance as Partial<StorageTypeInstance>;\n return codecShape.typeParams;\n }\n return column.typeParams;\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>';\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 'export type Models = ContractModelsMap<Contract>;',\n ].join('\\n');\n },\n} as const;\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 if (isPostgresEnumStorageEntry(typeInstance)) {\n throw new Error(\n `Document-scoped storage.types entry \"${typeName}\" is a postgres-enum; enums belong under storage.namespaces[namespaceId].enum`,\n );\n }\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\nfunction generatePostgresNamespaceTypesType(\n types: Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>>,\n): string {\n if (Object.keys(types).length === 0) {\n return 'Record<string, never>';\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n if (isPostgresEnumStorageEntry(typeInstance)) {\n const codecId = serializeValue(typeInstance.codecId);\n const nativeType = serializeValue(typeInstance.nativeType);\n const name = serializeValue(typeInstance.name);\n const valuesLiteral = typeInstance.values.map((v) => serializeValue(v)).join(', ');\n typeEntries.push(\n `readonly ${serializeObjectKey(typeName)}: { readonly kind: 'postgres-enum'; readonly name: ${name}; readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly values: readonly [${valuesLiteral}] }`,\n );\n continue;\n }\n throw new Error(\n `Unknown namespace storage type kind for \"${typeName}\"; expected postgres-enum in namespace.enum.`,\n );\n }\n return `{ ${typeEntries.join('; ')} }`;\n}\n\nfunction isPostgresSchemaNamespace(ns: Namespace): ns is Namespace & {\n readonly enum: Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>>;\n} {\n return (\n (ns as { kind?: unknown }).kind === 'schema' &&\n 'enum' in ns &&\n typeof (ns as { enum?: unknown }).enum === 'object' &&\n (ns as { enum?: unknown }).enum !== null\n );\n}\n\nconst SQL_NAMESPACE_KIND_FALLBACK = 'sql-namespace' as const;\n\nfunction namespaceSerializedKind(ns: Namespace): string {\n const kind = (ns as { kind?: unknown }).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 // Plain-literal namespaces built via the contract-ts DSL bypass the\n // class-level `Object.defineProperty(this, 'kind', { value, enumerable: false })`\n // path, so `ns.kind` is missing on the runtime object. Surfacing the\n // framework-default kind here keeps the emitted `.d.ts` literal\n // structurally assignable to `Namespace`, which now requires `kind`.\n return `readonly kind: '${SQL_NAMESPACE_KIND_FALLBACK}'`;\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 pkName = table.primaryKey.name\n ? `; readonly name: ${serializeValue(table.primaryKey.name)}`\n : '';\n tableParts.push(`primaryKey: { readonly columns: readonly [${pkCols}]${pkName} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => serializeValue(c)).join(', ');\n const name = u.name ? `; readonly name: ${serializeValue(u.name)}` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const cols = i.columns.map((c: string) => serializeValue(c)).join(', ');\n const name = i.name !== undefined ? `; readonly name: ${serializeValue(i.name)}` : '';\n const indexType = i.type !== undefined ? `; readonly type: ${serializeValue(i.type)}` : '';\n const indexOptions =\n i.options !== undefined ? `; readonly options: ${serializeValue(i.options)}` : '';\n return `{ readonly columns: readonly [${cols}]${name}${indexType}${indexOptions} }`;\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 name = fk.name ? `; readonly name: ${serializeValue(fk.name)}` : '';\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 return `{ readonly source: ${srcRef}; readonly target: ${tgtRef}${name}; readonly constraint: ${fk.constraint}; readonly index: ${fk.index} }`;\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(ns.tables as Readonly<Record<string, StorageTable>>);\n const isPg = isPostgresSchemaNamespace(ns);\n const enumClause = isPg\n ? `; readonly enum: ${generatePostgresNamespaceTypesType(ns.enum)}`\n : '';\n parts.push(\n `readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly tables: ${tablesType}${enumClause} }`,\n );\n }\n return `{ ${parts.join('; ')} }`;\n}\n"],"mappings":";;;;AAoBA,SAAS,2BAA2B,QAAqD;CACvF,IAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAC5C,OAAO;CAGT,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,QAAQ,KAAK,YAAY,mBAAmB,GAAG,EAAE,IAAI,eAAe,KAAK,GAAG;CAG9E,OAAO,KAAK,QAAQ,KAAK,IAAI,EAAE;AACjC;;;;;;;;;;AAWA,SAAS,aACP,SACA,WAC4E;CAC5E,KAAK,MAAM,CAAC,aAAa,OAAO,OAAO,QAAQ,QAAQ,UAAU,GAAG;EAClE,MAAM,QAAQ,GAAG,OAAO;EACxB,IAAI,UAAU,KAAA,GACZ,OAAO;GAAE;GAAO;EAAY;CAEhC;AAEF;AAEA,SAAS,0BAA0B,SAA2B;CAC5D,MAAM,uBAAO,IAAI,IAAoB;CACrC,KAAK,MAAM,CAAC,aAAa,OAAO,OAAO,QAAQ,QAAQ,UAAU,GAC/D,KAAK,MAAM,aAAa,OAAO,KAAK,GAAG,MAAM,GAAG;EAC9C,MAAM,WAAW,KAAK,IAAI,SAAS;EACnC,IAAI,aAAa,KAAA,KAAa,aAAa,aACzC,MAAM,IAAI,MACR,yBAAyB,UAAU,mBAAmB,SAAS,SAAS,YAAY,EACtF;EAEF,KAAK,IAAI,WAAW,WAAW;CACjC;AAEJ;AAEA,MAAa,cAAc;CACzB,IAAI;CAEJ,cAAc,UAAoB,MAA+B;EAC/D,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,YACZ;EAGF,MAAM,cAAc;EAEpB,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,GAAG,MAAM,GAAG;GACjE,MAAM,QAAQ;GACd,KAAK,MAAM,CAAC,SAAS,eAAe,OAAO,QAAQ,MAAM,OAAO,GAAG;IAEjE,MAAM,UAAUA,WAAI;IACpB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,WAAW,QAAQ,cAAc,UAAU,qBAAqB;IAIlF,IAAI,CADU,QAAQ,MAAM,WACnB,IAAI,IACX,MAAM,IAAI,MACR,WAAW,QAAQ,cAAc,UAAU,iCAAiC,QAAQ,oCACtF;GAEJ;EACF;CAEJ;CAEA,kBAAkB,UAA0B;EAC1C,IAAI,SAAS,iBAAiB,OAC5B,MAAM,IAAI,MAAM,qCAAqC,SAAS,aAAa,EAAE;EAG/E,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,YACZ,MAAM,IAAI,MAAM,2CAA2C;EAG7D,0BAA0B,OAAO;EAEjC,MAAM,6BAAa,IAAI,IAAY;EACnC,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,KAAK,OAAO,KAAK,GAAG,MAAM,GACnC,WAAW,IAAI,CAAC;EAIpB,KAAK,MAAM,CAAC,aAAa,aAAa,OAAO,QAAQ,SAAS,OAAO,UAAU,GAAG;GAChF,MAAM,SAAS,SAAS;GACxB,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,GAAG;IACvD,MAAM,gBAAgB,GAAG,YAAY,GAAG;IACxC,IAAI,CAAC,MAAM,SAAS,OAClB,MAAM,IAAI,MAAM,UAAU,cAAc,2BAA2B;IAGrE,MAAM,YAAY,MAAM,QAAQ;IAChC,MAAM,UAAU,aAAa,SAAS,SAAS;IAC/C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,UAAU,cAAc,mCAAmC,UAAU,EAAE;IAGzF,MAAM,EAAE,UAAU;IAClB,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;IACtD,MAAM,gBAAgB,MAAM,QAAQ;IACpC,IAAI,CAAC,iBAAiB,OAAO,KAAK,aAAa,EAAE,WAAW,GAC1D,MAAM,IAAI,MAAM,UAAU,cAAc,4BAA4B;IAGtE,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,aAAa,GAAG;KAC9D,IAAI,CAAC,MAAM,QACT,MAAM,IAAI,MACR,UAAU,cAAc,WAAW,UAAU,6BAC/C;KAGF,IAAI,CAAC,YAAY,IAAI,MAAM,MAAM,GAC/B,MAAM,IAAI,MACR,UAAU,cAAc,WAAW,UAAU,oCAAoC,MAAM,OAAO,cAAc,UAAU,EACxH;IAEJ;IAEA,IAAI,CAAC,MAAM,aAAa,OAAO,MAAM,cAAc,UACjD,MAAM,IAAI,MACR,UAAU,cAAc,4DAC1B;GAEJ;EACF;EAEA,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,GAAG,MAAM,GAAG;GACjE,MAAM,QAAQ;GACd,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;GAEtD,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAC9B,MAAM,IAAI,MACR,UAAU,UAAU,yDACtB;GAEF,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAC9B,MAAM,IAAI,MACR,UAAU,UAAU,yDACtB;GAEF,IAAI,CAAC,MAAM,QAAQ,MAAM,WAAW,GAClC,MAAM,IAAI,MACR,UAAU,UAAU,6DACtB;GAGF,IAAI,MAAM;SACH,MAAM,WAAW,MAAM,WAAW,SACrC,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,EAC7E;GAAA;GAKN,KAAK,MAAM,UAAU,MAAM,SACzB,KAAK,MAAM,WAAW,OAAO,SAC3B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,sDAAsD,QAAQ,EACpF;GAKN,KAAK,MAAM,SAAS,MAAM,SACxB,KAAK,MAAM,WAAW,MAAM,SAC1B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,0CAA0C,QAAQ,EACxE;GAKN,KAAK,MAAM,MAAM,MAAM,aAAa;IAClC,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,EAC7E;IAIJ,MAAM,kBAAkB,QAAQ,WAAW,GAAG,OAAO,cAAc,OACjE,GAAG,OAAO;IAEZ,IAAI,CAAC,iBACH,MAAM,IAAI,MACR,UAAU,UAAU,8CAA8C,GAAG,OAAO,UAAU,kBAAkB,GAAG,OAAO,YAAY,EAChI;IAGF,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,gBAAgB,OAAO,CAAC;IAC1E,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,sBAAsB,IAAI,OAAO,GACpC,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,cAAc,GAAG,OAAO,UAAU,EAC/G;IAIJ,IAAI,GAAG,OAAO,QAAQ,WAAW,GAAG,OAAO,QAAQ,QACjD,MAAM,IAAI,MACR,UAAU,UAAU,6BAA6B,GAAG,OAAO,QAAQ,OAAO,4CAA4C,GAAG,OAAO,QAAQ,OAAO,EACjJ;GAEJ;EACF;CAEJ;CAEA,oBAAoB,UAAoB,qBAAqC;EAC3E,MAAM,UAAU,SAAS;EACzB,MAAM,iBAAiB,8BAA8B,QAAQ,UAAU;EACvE,MAAM,WAAW,uCAAuC,QAAQ,KAAK;EAErE,OAAO,0BAA0B,iBADb,aAAa,KAAA,IAAY,KAAK,qBAAqB,WACT,0BAA0B,oBAAoB;CAC9G;CAEA,yBAAyB,YAAoB,OAA8B;EACzE,MAAM,WAAW;EACjB,MAAM,YAAY,SAAS,QAAQ;EACnC,MAAM,gBAAgB,SAAS,QAAQ;EAEvC,MAAM,eAAe,CAAC,mBAAmB,eAAe,SAAS,GAAG;EACpE,IAAI,OAAO,KAAK,aAAa,EAAE,SAAS,GAAG;GACzC,MAAM,aAAuB,CAAC;GAC9B,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,aAAa,GAC3D,WAAW,KACT,YAAY,mBAAmB,SAAS,EAAE,uBAAuB,eAAe,MAAM,MAAM,EAAE,GAChG;GAEF,aAAa,KAAK,sBAAsB,WAAW,KAAK,IAAI,EAAE,GAAG;EACnE;EAEA,OAAO,KAAK,aAAa,KAAK,IAAI,EAAE;CACtC;CAEA,uBACE,YACA,WACA,OACA,UACqC;EACrC,MAAM,WAAW;EACjB,MAAM,eAAe,SAAS,SAAS,SAAS;EAChD,IAAI,CAAC,cAAc,OAAO,KAAA;EAE1B,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,OAAO,KAAA;EAErB,MAAM,YAAY,SAAS,QAAQ;EACnC,MAAM,UAAU,aAAa,SAAS,SAAS;EAC/C,IAAI,CAAC,SAAS,OAAO,KAAA;EAErB,MAAM,SAAS,QAAQ,MAAM,QAAQ,aAAa;EAClD,IAAI,CAAC,QAAQ,OAAO,KAAA;EAEpB,IAAI,OAAO,SAAS;GAClB,MAAM,KAAK,QAAQ,WAAW,QAAQ;GAUtC,MAAM,gBARJ,OAAO,KAAA,KAAa,UAAU,KAExB,GAGA,OACF,KAAA,KAC0B,OAAO,YACD,QAAQ,QAAQ,OAAO;GAC7D,IAAI,iBAAiB,KAAA,GAAW,OAAO,KAAA;GACvC,IAAI,2BAA2B,YAAY,GACzC,OAAO,EAAE,QAAQ,aAAa,OAAO;GAGvC,OAAOC,aAAW;EACpB;EACA,OAAO,OAAO;CAChB;CAEA,mBAA6B;EAC3B,OAAO;GACL;GACA;GACA;GACA;EACF;CACF;CAEA,qBAAqB,SAAgD;EAEnE,MAAM,yBAD4B,SAAS,6BAA6B,CAAC,GAEtE,QAAQ,QAAQ,IAAI,UAAU,qBAAqB,EACnD,KAAK,QAAQ,GAAG,IAAI,MAAM,aAAa;EAM1C,OAAO;GACL;GACA,qCANA,sBAAsB,SAAS,IAC3B,sBAAsB,KAAK,KAAK,IAChC,wBAIqD;GACzD;GACA;GACA;GACA;EACF,EAAE,KAAK,IAAI;CACb;CAEA,wBAAgC;EAC9B,OAAO;CACT;CAEA,mBAAmB,kBAA0B,cAA8B;EACzE,OAAO;GACL,+CAA+C,iBAAiB,IAAI,aAAa;GACjF;GACA;GACA;EACF,EAAE,KAAK,IAAI;CACb;AACF;AAEA,SAAS,uCAAuC,OAAgD;CAC9F,IAAI,CAAC,SAAS,OAAO,KAAK,KAAK,EAAE,WAAW,GAC1C;CAGF,MAAM,cAAwB,CAAC;CAC/B,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,KAAK,GAAG;EAC5D,IAAI,2BAA2B,YAAY,GACzC,MAAM,IAAI,MACR,wCAAwC,SAAS,8EACnD;EAEF,MAAM,qBAAqB;EAC3B,IACE,OAAO,mBAAmB,YAAY,YACtC,OAAO,mBAAmB,eAAe,UAEzC,MAAM,IAAI,MACR,kCAAkC,SAAS,sEAC7C;EAEF,MAAM,UAAU,eAAe,mBAAmB,OAAO;EACzD,MAAM,aAAa,eAAe,mBAAmB,UAAU;EAC/D,MAAM,gBAAgB,2BAA2B,mBAAmB,UAAU;EAC9E,YAAY,KACV,YAAY,SAAS,yDAAyD,QAAQ,yBAAyB,WAAW,yBAAyB,cAAc,GACnK;CACF;CAEA,OAAO,KAAK,YAAY,KAAK,IAAI,EAAE;AACrC;AAEA,SAAS,mCACP,OACQ;CACR,IAAI,OAAO,KAAK,KAAK,EAAE,WAAW,GAChC,OAAO;CAGT,MAAM,cAAwB,CAAC;CAC/B,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,KAAK,GAAG;EAC5D,IAAI,2BAA2B,YAAY,GAAG;GAC5C,MAAM,UAAU,eAAe,aAAa,OAAO;GACnD,MAAM,aAAa,eAAe,aAAa,UAAU;GACzD,MAAM,OAAO,eAAe,aAAa,IAAI;GAC7C,MAAM,gBAAgB,aAAa,OAAO,KAAK,MAAM,eAAe,CAAC,CAAC,EAAE,KAAK,IAAI;GACjF,YAAY,KACV,YAAY,mBAAmB,QAAQ,EAAE,qDAAqD,KAAK,yBAAyB,WAAW,sBAAsB,QAAQ,+BAA+B,cAAc,IACpN;GACA;EACF;EACA,MAAM,IAAI,MACR,4CAA4C,SAAS,6CACvD;CACF;CACA,OAAO,KAAK,YAAY,KAAK,IAAI,EAAE;AACrC;AAEA,SAAS,0BAA0B,IAEjC;CACA,OACG,GAA0B,SAAS,YACpC,UAAU,MACV,OAAQ,GAA0B,SAAS,YAC1C,GAA0B,SAAS;AAExC;AAEA,MAAM,8BAA8B;AAEpC,SAAS,wBAAwB,IAAuB;CACtD,MAAM,OAAQ,GAA0B;CACxC,IAAI,SAAS,UAGX,OAAO,mBAFI,GAAG,OACK,uBAAuB,4BAA4B,kBACxC;CAEhC,IAAI,OAAO,SAAS,UAClB,OAAO,kBAAkB,eAAe,IAAI;CAO9C,OAAO,mBAAmB,4BAA4B;AACxD;AAEA,SAAS,yBAAyB,OAA6B;CAC7D,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,SAAS,QAAQ,OAAO,QAAQ,MAAM,OAAO,GAAG;EAC1D,MAAM,WAAW,IAAI,WAAW,SAAS;EACzC,MAAM,aAAa,eAAe,IAAI,UAAU;EAChD,MAAM,UAAU,eAAe,IAAI,OAAO;EAC1C,MAAM,cAAc,IAAI,UACpB,IAAI,QAAQ,SAAS,YACnB,uFAAuF,QAAQ,IAAI,eACjG,IAAI,QAAQ,KACd,EAAE,OACF,yEAAyE,eACvE,IAAI,QAAQ,UACd,EAAE,MACJ;EACJ,MAAM,iBACJ,IAAI,cAAc,OAAO,KAAK,IAAI,UAAU,EAAE,SAAS,IACnD,0BAA0B,2BAA2B,IAAI,UAAU,MACnE;EACN,MAAM,cAAc,IAAI,UAAU,uBAAuB,eAAe,IAAI,OAAO,MAAM;EACzF,QAAQ,KACN,YAAY,QAAQ,2BAA2B,WAAW,sBAAsB,QAAQ,uBAAuB,WAAW,cAAc,iBAAiB,YAAY,GACvK;CACF;CAEA,MAAM,aAAuB,CAAC,cAAc,QAAQ,KAAK,IAAI,EAAE,GAAG;CAElE,IAAI,MAAM,YAAY;EACpB,MAAM,SAAS,MAAM,WAAW,QAAQ,KAAK,MAAM,eAAe,CAAC,CAAC,EAAE,KAAK,IAAI;EAC/E,MAAM,SAAS,MAAM,WAAW,OAC5B,oBAAoB,eAAe,MAAM,WAAW,IAAI,MACxD;EACJ,WAAW,KAAK,6CAA6C,OAAO,GAAG,OAAO,GAAG;CACnF;CAEA,MAAM,UAAU,MAAM,QACnB,KAAK,MAAM;EAGV,OAAO,iCAFM,EAAE,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,EAAE,KAAK,IAEvB,EAAE,GADhC,EAAE,OAAO,oBAAoB,eAAe,EAAE,IAAI,MAAM,GAChB;CACvD,CAAC,EACA,KAAK,IAAI;CACZ,WAAW,KAAK,sBAAsB,QAAQ,EAAE;CAEhD,MAAM,UAAU,MAAM,QACnB,KAAK,MAAM;EAMV,OAAO,iCALM,EAAE,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,EAAE,KAAK,IAKvB,EAAE,GAJhC,EAAE,SAAS,KAAA,IAAY,oBAAoB,eAAe,EAAE,IAAI,MAAM,KACjE,EAAE,SAAS,KAAA,IAAY,oBAAoB,eAAe,EAAE,IAAI,MAAM,KAEtF,EAAE,YAAY,KAAA,IAAY,uBAAuB,eAAe,EAAE,OAAO,MAAM,GACD;CAClF,CAAC,EACA,KAAK,IAAI;CACZ,WAAW,KAAK,sBAAsB,QAAQ,EAAE;CAEhD,MAAM,MAAM,MAAM,YACf,KAAK,OAAO;EACX,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,EAAE,KAAK,IAAI;EACjF,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,EAAE,KAAK,IAAI;EACjF,MAAM,OAAO,GAAG,OAAO,oBAAoB,eAAe,GAAG,IAAI,MAAM;EAGvE,OAAO,sBAAsB,2BAFa,qBAAqB,OAAO,GAAG,OAAO,WAAW,CAAC,EAAE,wBAAwB,eAAe,GAAG,OAAO,SAAS,EAAE,gCAAgC,QAAQ,KAE9J,qBAAqB,2BADf,qBAAqB,OAAO,GAAG,OAAO,WAAW,CAAC,EAAE,wBAAwB,eAAe,GAAG,OAAO,SAAS,EAAE,gCAAgC,QAAQ,OAChI,KAAK,yBAAyB,GAAG,WAAW,oBAAoB,GAAG,MAAM;CAC7I,CAAC,EACA,KAAK,IAAI;CACZ,WAAW,KAAK,0BAA0B,IAAI,EAAE;CAEhD,OAAO,KAAK,WAAW,KAAK,IAAI,EAAE;AACpC;AAEA,SAAS,sBAAsB,QAAwD;CACrF,MAAM,eAAyB,CAAC;CAChC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,GAC3F,aAAa,KAAK,YAAY,UAAU,IAAI,yBAAyB,KAAK,GAAG;CAE/E,IAAI,aAAa,WAAW,GAM1B,OAAO;CAET,OAAO,KAAK,aAAa,KAAK,IAAI,EAAE;AACtC;AAEA,SAAS,8BAA8B,YAA8C;CACnF,MAAM,UAAU,OAAO,QAAQ,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;CACtF,IAAI,QAAQ,WAAW,GACrB,OAAO;CAET,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,CAAC,MAAM,OAAO,SAAS;EAChC,MAAM,aAAa,KAAK,wBAAwB,EAAE;EAClD,MAAM,aAAa,sBAAsB,GAAG,MAAgD;EAE5F,MAAM,aADO,0BAA0B,EACjB,IAClB,oBAAoB,mCAAmC,GAAG,IAAI,MAC9D;EACJ,MAAM,KACJ,YAAY,mBAAmB,IAAI,EAAE,mBAAmB,eAAe,GAAG,EAAE,IAAI,WAAW,qBAAqB,aAAa,WAAW,GAC1I;CACF;CACA,OAAO,KAAK,MAAM,KAAK,IAAI,EAAE;AAC/B"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/index.ts"],"sourcesContent":["import type { Contract, ContractModel } from '@prisma-next/contract/types';\nimport {\n serializeNamespaceId,\n serializeObjectKey,\n serializeValue,\n} from '@prisma-next/emitter/domain-type-generation';\nimport type {\n GenerateContractTypesOptions,\n ValidationContext,\n} from '@prisma-next/framework-components/emission';\nimport { type Namespace, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport {\n isPostgresEnumStorageEntry,\n type PostgresEnumStorageEntry,\n type SqlModelStorage,\n type SqlStorage,\n type StorageTable,\n type StorageTypeInstance,\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, tableUnknown] of Object.entries(ns.entries.table)) {\n const table = tableUnknown as StorageTable;\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 = storage.namespaces[namespaceId]?.entries.table[tableName] as\n | StorageTable\n | undefined;\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, tableUnknown] of Object.entries(ns.entries.table)) {\n const table = tableUnknown as StorageTable;\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 = storage.namespaces[fk.target.namespaceId]?.entries.table[\n fk.target.tableName\n ] as StorageTable | undefined;\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: ContractModel): 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: ContractModel,\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 = storage.namespaces[storageNamespaceId]?.entries.table[tableName] as\n | StorageTable\n | undefined;\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 ns = storage.namespaces[storageNamespaceId];\n const nsEnums =\n ns !== undefined\n ? blindCast<\n { readonly type?: Readonly<Record<string, PostgresEnumStorageEntry>> },\n 'postgres target namespace entries carry a type slot beyond the family-shared SqlNamespace.entries type'\n >(ns.entries).type\n : undefined;\n const fromNamespace = nsEnums?.[column.typeRef];\n const typeInstance = fromNamespace ?? storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n if (isPostgresEnumStorageEntry(typeInstance)) {\n return { values: typeInstance.values };\n }\n const codecShape = typeInstance as Partial<StorageTypeInstance>;\n return codecShape.typeParams;\n }\n return column.typeParams;\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>';\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\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 if (isPostgresEnumStorageEntry(typeInstance)) {\n throw new Error(\n `Document-scoped storage.types entry \"${typeName}\" is a postgres-enum; enums belong under storage.namespaces[namespaceId].entries.type`,\n );\n }\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\nfunction generatePostgresNamespaceTypesType(\n types: Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>>,\n): string {\n if (Object.keys(types).length === 0) {\n return 'Record<string, never>';\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n if (isPostgresEnumStorageEntry(typeInstance)) {\n const codecId = serializeValue(typeInstance.codecId);\n const nativeType = serializeValue(typeInstance.nativeType);\n const name = serializeValue(typeInstance.name);\n const valuesLiteral = typeInstance.values.map((v) => serializeValue(v)).join(', ');\n typeEntries.push(\n `readonly ${serializeObjectKey(typeName)}: { readonly kind: 'postgres-enum'; readonly name: ${name}; readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly values: readonly [${valuesLiteral}] }`,\n );\n continue;\n }\n throw new Error(\n `Unknown namespace storage type kind for \"${typeName}\"; expected postgres-enum in namespace.entries.type.`,\n );\n }\n return `{ ${typeEntries.join('; ')} }`;\n}\n\nconst SQL_NAMESPACE_KIND_FALLBACK = 'sql-namespace' as const;\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 // Plain-literal namespaces built via the contract-ts DSL bypass the\n // class-level `Object.defineProperty(this, 'kind', { value, enumerable: false })`\n // path, so `ns.kind` is missing on the runtime object. Surfacing the\n // framework-default kind here keeps the emitted `.d.ts` literal\n // structurally assignable to `Namespace`, which now requires `kind`.\n return `readonly kind: '${SQL_NAMESPACE_KIND_FALLBACK}'`;\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 pkName = table.primaryKey.name\n ? `; readonly name: ${serializeValue(table.primaryKey.name)}`\n : '';\n tableParts.push(`primaryKey: { readonly columns: readonly [${pkCols}]${pkName} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => serializeValue(c)).join(', ');\n const name = u.name ? `; readonly name: ${serializeValue(u.name)}` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const cols = i.columns.map((c: string) => serializeValue(c)).join(', ');\n const name = i.name !== undefined ? `; readonly name: ${serializeValue(i.name)}` : '';\n const indexType = i.type !== undefined ? `; readonly type: ${serializeValue(i.type)}` : '';\n const indexOptions =\n i.options !== undefined ? `; readonly options: ${serializeValue(i.options)}` : '';\n return `{ readonly columns: readonly [${cols}]${name}${indexType}${indexOptions} }`;\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 name = fk.name ? `; readonly name: ${serializeValue(fk.name)}` : '';\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 return `{ readonly source: ${srcRef}; readonly target: ${tgtRef}${name}; readonly constraint: ${fk.constraint}; readonly index: ${fk.index} }`;\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 typeSlot =\n ns.kind === 'schema'\n ? blindCast<\n Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>> | undefined,\n 'postgres schema namespace entries carry a type slot beyond the family-shared SqlNamespace.entries type'\n >(\n blindCast<\n { readonly type?: Readonly<Record<string, unknown>> },\n 'access opaque type slot on postgres target namespace entries'\n >(ns.entries).type,\n )\n : undefined;\n const entriesParts = [`readonly table: ${tablesType}`];\n if (typeSlot !== undefined) {\n entriesParts.push(`readonly type: ${generatePostgresNamespaceTypesType(typeSlot)}`);\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":";;;;;AAqBA,SAAS,2BAA2B,QAAqD;CACvF,IAAI,CAAC,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GAC5C,OAAO;CAGT,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,QAAQ,KAAK,YAAY,mBAAmB,GAAG,EAAE,IAAI,eAAe,KAAK,GAAG;CAG9E,OAAO,KAAK,QAAQ,KAAK,IAAI,EAAE;AACjC;AAEA,MAAa,cAAc;CACzB,IAAI;CAEJ,cAAc,UAAoB,MAA+B;EAC/D,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,YACZ;EAGF,MAAM,cAAc;EAEpB,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,GAAG,QAAQ,KAAK,GAAG;GACxE,MAAM,QAAQ;GACd,KAAK,MAAM,CAAC,SAAS,eAAe,OAAO,QAAQ,MAAM,OAAO,GAAG;IAEjE,MAAM,UAAUA,WAAI;IACpB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,WAAW,QAAQ,cAAc,UAAU,qBAAqB;IAIlF,IAAI,CADU,QAAQ,MAAM,WACnB,CAAC,GAAG,IACX,MAAM,IAAI,MACR,WAAW,QAAQ,cAAc,UAAU,iCAAiC,QAAQ,oCACtF;GAEJ;EACF;CAEJ;CAEA,kBAAkB,UAA0B;EAC1C,IAAI,SAAS,iBAAiB,OAC5B,MAAM,IAAI,MAAM,qCAAqC,SAAS,aAAa,EAAE;EAG/E,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,YACZ,MAAM,IAAI,MAAM,2CAA2C;EAG7D,MAAM,iDAAiC,IAAI,IAAoB;EAC/D,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,QAAQ,UAAU,GACxD,KAAK,MAAM,aAAa,OAAO,KAAK,GAAG,QAAQ,KAAK,GAAG;GACrD,MAAM,aAAa,+BAA+B,IAAI,SAAS;GAC/D,IAAI,eAAe,KAAA,KAAa,eAAe,MAC7C,MAAM,IAAI,MACR,yBAAyB,UAAU,mBAAmB,WAAW,SAAS,KAAK,EACjF;GAEF,+BAA+B,IAAI,WAAW,IAAI;EACpD;EAGF,MAAM,6BAAa,IAAI,IAAY;EACnC,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,KAAK,OAAO,KAAK,GAAG,QAAQ,KAAK,GAC1C,WAAW,IAAI,CAAC;EAIpB,KAAK,MAAM,CAAC,aAAa,aAAa,OAAO,QAAQ,SAAS,OAAO,UAAU,GAAG;GAChF,MAAM,SAAS,SAAS;GACxB,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,GAAG;IACvD,MAAM,gBAAgB,GAAG,YAAY,GAAG;IACxC,IAAI,CAAC,MAAM,SAAS,OAClB,MAAM,IAAI,MAAM,UAAU,cAAc,2BAA2B;IAErE,IAAI,CAAC,MAAM,QAAQ,aACjB,MAAM,IAAI,MAAM,UAAU,cAAc,iCAAiC;IAE3E,IAAI,MAAM,QAAQ,gBAAgB,aAChC,MAAM,IAAI,MACR,UAAU,cAAc,yBAAyB,MAAM,QAAQ,YAAY,qCAAqC,YAAY,EAC9H;IAGF,MAAM,YAAY,MAAM,QAAQ;IAChC,MAAM,QAAQ,QAAQ,WAAW,YAAY,EAAE,QAAQ,MAAM;IAG7D,IAAI,CAAC,OACH,MAAM,IAAI,MACR,UAAU,cAAc,mCAAmC,YAAY,GAAG,UAAU,EACtF;IAEF,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;IACtD,MAAM,gBAAgB,MAAM,QAAQ;IACpC,IAAI,CAAC,iBAAiB,OAAO,KAAK,aAAa,CAAC,CAAC,WAAW,GAC1D,MAAM,IAAI,MAAM,UAAU,cAAc,4BAA4B;IAGtE,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,aAAa,GAAG;KAC9D,IAAI,CAAC,MAAM,QACT,MAAM,IAAI,MACR,UAAU,cAAc,WAAW,UAAU,6BAC/C;KAGF,IAAI,CAAC,YAAY,IAAI,MAAM,MAAM,GAC/B,MAAM,IAAI,MACR,UAAU,cAAc,WAAW,UAAU,oCAAoC,MAAM,OAAO,cAAc,UAAU,EACxH;IAEJ;IAEA,IAAI,CAAC,MAAM,aAAa,OAAO,MAAM,cAAc,UACjD,MAAM,IAAI,MACR,UAAU,cAAc,4DAC1B;GAEJ;EACF;EAEA,KAAK,MAAM,MAAM,OAAO,OAAO,QAAQ,UAAU,GAC/C,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,GAAG,QAAQ,KAAK,GAAG;GACxE,MAAM,QAAQ;GACd,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,MAAM,OAAO,CAAC;GAEtD,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAC9B,MAAM,IAAI,MACR,UAAU,UAAU,yDACtB;GAEF,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAC9B,MAAM,IAAI,MACR,UAAU,UAAU,yDACtB;GAEF,IAAI,CAAC,MAAM,QAAQ,MAAM,WAAW,GAClC,MAAM,IAAI,MACR,UAAU,UAAU,6DACtB;GAGF,IAAI,MAAM;SACH,MAAM,WAAW,MAAM,WAAW,SACrC,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,EAC7E;GAAA;GAKN,KAAK,MAAM,UAAU,MAAM,SACzB,KAAK,MAAM,WAAW,OAAO,SAC3B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,sDAAsD,QAAQ,EACpF;GAKN,KAAK,MAAM,SAAS,MAAM,SACxB,KAAK,MAAM,WAAW,MAAM,SAC1B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,0CAA0C,QAAQ,EACxE;GAKN,KAAK,MAAM,MAAM,MAAM,aAAa;IAClC,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,YAAY,IAAI,OAAO,GAC1B,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,EAC7E;IAIJ,MAAM,kBAAkB,QAAQ,WAAW,GAAG,OAAO,YAAY,EAAE,QAAQ,MACzE,GAAG,OAAO;IAEZ,IAAI,CAAC,iBACH,MAAM,IAAI,MACR,UAAU,UAAU,8CAA8C,GAAG,OAAO,UAAU,kBAAkB,GAAG,OAAO,YAAY,EAChI;IAGF,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,gBAAgB,OAAO,CAAC;IAC1E,KAAK,MAAM,WAAW,GAAG,OAAO,SAC9B,IAAI,CAAC,sBAAsB,IAAI,OAAO,GACpC,MAAM,IAAI,MACR,UAAU,UAAU,+CAA+C,QAAQ,cAAc,GAAG,OAAO,UAAU,EAC/G;IAIJ,IAAI,GAAG,OAAO,QAAQ,WAAW,GAAG,OAAO,QAAQ,QACjD,MAAM,IAAI,MACR,UAAU,UAAU,6BAA6B,GAAG,OAAO,QAAQ,OAAO,4CAA4C,GAAG,OAAO,QAAQ,OAAO,EACjJ;GAEJ;EACF;CAEJ;CAEA,oBAAoB,UAAoB,qBAAqC;EAC3E,MAAM,UAAU,SAAS;EACzB,MAAM,iBAAiB,8BAA8B,QAAQ,UAAU;EACvE,MAAM,WAAW,uCAAuC,QAAQ,KAAK;EAErE,OAAO,0BAA0B,iBADb,aAAa,KAAA,IAAY,KAAK,qBAAqB,WACT,0BAA0B,oBAAoB;CAC9G;CAEA,yBAAyB,YAAoB,OAA8B;EACzE,MAAM,WAAW;EACjB,MAAM,YAAY,SAAS,QAAQ;EACnC,MAAM,gBAAgB,SAAS,QAAQ;EAEvC,MAAM,eAAe,CACnB,mBAAmB,eAAe,SAAS,KAC3C,yBAAyB,eAAe,SAAS,QAAQ,WAAW,GACtE;EACA,IAAI,OAAO,KAAK,aAAa,CAAC,CAAC,SAAS,GAAG;GACzC,MAAM,aAAuB,CAAC;GAC9B,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,aAAa,GAC3D,WAAW,KACT,YAAY,mBAAmB,SAAS,EAAE,uBAAuB,eAAe,MAAM,MAAM,EAAE,GAChG;GAEF,aAAa,KAAK,sBAAsB,WAAW,KAAK,IAAI,EAAE,GAAG;EACnE;EAEA,OAAO,KAAK,aAAa,KAAK,IAAI,EAAE;CACtC;CAEA,uBACE,YACA,WACA,OACA,UACqC;EACrC,MAAM,WAAW;EACjB,MAAM,eAAe,SAAS,SAAS,SAAS;EAChD,IAAI,CAAC,cAAc,OAAO,KAAA;EAE1B,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SAAS,OAAO,KAAA;EAErB,MAAM,YAAY,SAAS,QAAQ;EACnC,MAAM,qBAAqB,SAAS,QAAQ;EAC5C,IAAI,CAAC,oBAAoB,OAAO,KAAA;EAEhC,MAAM,QAAQ,QAAQ,WAAW,mBAAmB,EAAE,QAAQ,MAAM;EAGpE,IAAI,CAAC,OAAO,OAAO,KAAA;EAEnB,MAAM,SAAS,MAAM,QAAQ,aAAa;EAC1C,IAAI,CAAC,QAAQ,OAAO,KAAA;EAEpB,IAAI,OAAO,SAAS;GAClB,MAAM,KAAK,QAAQ,WAAW;GAS9B,MAAM,gBAPJ,OAAO,KAAA,IACH,UAGE,GAAG,OAAO,CAAC,CAAC,OACd,KAAA,EAAA,GAC0B,OAAO,YACD,QAAQ,QAAQ,OAAO;GAC7D,IAAI,iBAAiB,KAAA,GAAW,OAAO,KAAA;GACvC,IAAI,2BAA2B,YAAY,GACzC,OAAO,EAAE,QAAQ,aAAa,OAAO;GAGvC,OAAOC,aAAW;EACpB;EACA,OAAO,OAAO;CAChB;CAEA,mBAA6B;EAC3B,OAAO;GACL;GACA;GACA;GACA;EACF;CACF;CAEA,qBAAqB,SAAgD;EAEnE,MAAM,yBAD4B,SAAS,6BAA6B,CAAC,EAAA,CAEtE,QAAQ,QAAQ,IAAI,UAAU,qBAAqB,CAAC,CACpD,KAAK,QAAQ,GAAG,IAAI,MAAM,aAAa;EAM1C,OAAO;GACL;GACA,qCANA,sBAAsB,SAAS,IAC3B,sBAAsB,KAAK,KAAK,IAChC,wBAIqD;GACzD;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;CACb;CAEA,wBAAgC;EAC9B,OAAO;CACT;CAEA,mBAAmB,kBAA0B,cAA8B;EACzE,OAAO;GACL,+CAA+C,iBAAiB,IAAI,aAAa;GACjF;GACA;EACF,CAAC,CAAC,KAAK,IAAI;CACb;AACF;AAEA,SAAS,uCAAuC,OAAgD;CAC9F,IAAI,CAAC,SAAS,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAC1C;CAGF,MAAM,cAAwB,CAAC;CAC/B,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,KAAK,GAAG;EAC5D,IAAI,2BAA2B,YAAY,GACzC,MAAM,IAAI,MACR,wCAAwC,SAAS,sFACnD;EAEF,MAAM,qBAAqB;EAC3B,IACE,OAAO,mBAAmB,YAAY,YACtC,OAAO,mBAAmB,eAAe,UAEzC,MAAM,IAAI,MACR,kCAAkC,SAAS,sEAC7C;EAEF,MAAM,UAAU,eAAe,mBAAmB,OAAO;EACzD,MAAM,aAAa,eAAe,mBAAmB,UAAU;EAC/D,MAAM,gBAAgB,2BAA2B,mBAAmB,UAAU;EAC9E,YAAY,KACV,YAAY,SAAS,yDAAyD,QAAQ,yBAAyB,WAAW,yBAAyB,cAAc,GACnK;CACF;CAEA,OAAO,KAAK,YAAY,KAAK,IAAI,EAAE;AACrC;AAEA,SAAS,mCACP,OACQ;CACR,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAChC,OAAO;CAGT,MAAM,cAAwB,CAAC;CAC/B,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,KAAK,GAAG;EAC5D,IAAI,2BAA2B,YAAY,GAAG;GAC5C,MAAM,UAAU,eAAe,aAAa,OAAO;GACnD,MAAM,aAAa,eAAe,aAAa,UAAU;GACzD,MAAM,OAAO,eAAe,aAAa,IAAI;GAC7C,MAAM,gBAAgB,aAAa,OAAO,KAAK,MAAM,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;GACjF,YAAY,KACV,YAAY,mBAAmB,QAAQ,EAAE,qDAAqD,KAAK,yBAAyB,WAAW,sBAAsB,QAAQ,+BAA+B,cAAc,IACpN;GACA;EACF;EACA,MAAM,IAAI,MACR,4CAA4C,SAAS,qDACvD;CACF;CACA,OAAO,KAAK,YAAY,KAAK,IAAI,EAAE;AACrC;AAEA,MAAM,8BAA8B;AAEpC,SAAS,wBAAwB,IAAuB;CACtD,MAAM,OAAO,GAAG;CAChB,IAAI,SAAS,UAGX,OAAO,mBAFI,GAAG,OACK,uBAAuB,4BAA4B,kBACxC;CAEhC,IAAI,OAAO,SAAS,UAClB,OAAO,kBAAkB,eAAe,IAAI;CAO9C,OAAO,mBAAmB,4BAA4B;AACxD;AAEA,SAAS,yBAAyB,OAA6B;CAC7D,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,SAAS,QAAQ,OAAO,QAAQ,MAAM,OAAO,GAAG;EAC1D,MAAM,WAAW,IAAI,WAAW,SAAS;EACzC,MAAM,aAAa,eAAe,IAAI,UAAU;EAChD,MAAM,UAAU,eAAe,IAAI,OAAO;EAC1C,MAAM,cAAc,IAAI,UACpB,IAAI,QAAQ,SAAS,YACnB,uFAAuF,QAAQ,IAAI,eACjG,IAAI,QAAQ,KACd,EAAE,OACF,yEAAyE,eACvE,IAAI,QAAQ,UACd,EAAE,MACJ;EACJ,MAAM,iBACJ,IAAI,cAAc,OAAO,KAAK,IAAI,UAAU,CAAC,CAAC,SAAS,IACnD,0BAA0B,2BAA2B,IAAI,UAAU,MACnE;EACN,MAAM,cAAc,IAAI,UAAU,uBAAuB,eAAe,IAAI,OAAO,MAAM;EACzF,QAAQ,KACN,YAAY,QAAQ,2BAA2B,WAAW,sBAAsB,QAAQ,uBAAuB,WAAW,cAAc,iBAAiB,YAAY,GACvK;CACF;CAEA,MAAM,aAAuB,CAAC,cAAc,QAAQ,KAAK,IAAI,EAAE,GAAG;CAElE,IAAI,MAAM,YAAY;EACpB,MAAM,SAAS,MAAM,WAAW,QAAQ,KAAK,MAAM,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;EAC/E,MAAM,SAAS,MAAM,WAAW,OAC5B,oBAAoB,eAAe,MAAM,WAAW,IAAI,MACxD;EACJ,WAAW,KAAK,6CAA6C,OAAO,GAAG,OAAO,GAAG;CACnF;CAEA,MAAM,UAAU,MAAM,QACnB,KAAK,MAAM;EAGV,OAAO,iCAFM,EAAE,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAEvB,EAAE,GADhC,EAAE,OAAO,oBAAoB,eAAe,EAAE,IAAI,MAAM,GAChB;CACvD,CAAC,CAAC,CACD,KAAK,IAAI;CACZ,WAAW,KAAK,sBAAsB,QAAQ,EAAE;CAEhD,MAAM,UAAU,MAAM,QACnB,KAAK,MAAM;EAMV,OAAO,iCALM,EAAE,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAKvB,EAAE,GAJhC,EAAE,SAAS,KAAA,IAAY,oBAAoB,eAAe,EAAE,IAAI,MAAM,KACjE,EAAE,SAAS,KAAA,IAAY,oBAAoB,eAAe,EAAE,IAAI,MAAM,KAEtF,EAAE,YAAY,KAAA,IAAY,uBAAuB,eAAe,EAAE,OAAO,MAAM,GACD;CAClF,CAAC,CAAC,CACD,KAAK,IAAI;CACZ,WAAW,KAAK,sBAAsB,QAAQ,EAAE;CAEhD,MAAM,MAAM,MAAM,YACf,KAAK,OAAO;EACX,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;EACjF,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,MAAc,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;EACjF,MAAM,OAAO,GAAG,OAAO,oBAAoB,eAAe,GAAG,IAAI,MAAM;EAGvE,OAAO,sBAAsB,2BAFa,qBAAqB,OAAO,GAAG,OAAO,WAAW,CAAC,EAAE,wBAAwB,eAAe,GAAG,OAAO,SAAS,EAAE,gCAAgC,QAAQ,KAE9J,qBAAqB,2BADf,qBAAqB,OAAO,GAAG,OAAO,WAAW,CAAC,EAAE,wBAAwB,eAAe,GAAG,OAAO,SAAS,EAAE,gCAAgC,QAAQ,OAChI,KAAK,yBAAyB,GAAG,WAAW,oBAAoB,GAAG,MAAM;CAC7I,CAAC,CAAC,CACD,KAAK,IAAI;CACZ,WAAW,KAAK,0BAA0B,IAAI,EAAE;CAEhD,OAAO,KAAK,WAAW,KAAK,IAAI,EAAE;AACpC;AAEA,SAAS,sBAAsB,QAAwD;CACrF,MAAM,eAAyB,CAAC;CAChC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,GAC3F,aAAa,KAAK,YAAY,UAAU,IAAI,yBAAyB,KAAK,GAAG;CAE/E,IAAI,aAAa,WAAW,GAM1B,OAAO;CAET,OAAO,KAAK,aAAa,KAAK,IAAI,EAAE;AACtC;AAEA,SAAS,8BAA8B,YAA8C;CACnF,MAAM,UAAU,OAAO,QAAQ,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;CACtF,IAAI,QAAQ,WAAW,GACrB,OAAO;CAET,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,CAAC,MAAM,OAAO,SAAS;EAChC,MAAM,aAAa,KAAK,wBAAwB,EAAE;EAClD,MAAM,aAAa,sBAChB,GAAG,QAAQ,SAAS,CAAC,CACxB;EACA,MAAM,WACJ,GAAG,SAAS,WACR,UAIE,UAGE,GAAG,OAAO,CAAC,CAAC,IAChB,IACA,KAAA;EACN,MAAM,eAAe,CAAC,mBAAmB,YAAY;EACrD,IAAI,aAAa,KAAA,GACf,aAAa,KAAK,kBAAkB,mCAAmC,QAAQ,GAAG;EAEpF,MAAM,cAAc,KAAK,aAAa,KAAK,IAAI,EAAE;EACjD,MAAM,KACJ,YAAY,mBAAmB,IAAI,EAAE,mBAAmB,eAAe,GAAG,EAAE,IAAI,WAAW,sBAAsB,YAAY,GAC/H;CACF;CACA,OAAO,KAAK,MAAM,KAAK,IAAI,EAAE;AAC/B"}
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-contract-emitter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0-dev.1",
|
|
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.
|
|
10
|
-
"@prisma-next/emitter": "0.
|
|
11
|
-
"@prisma-next/framework-components": "0.
|
|
12
|
-
"@prisma-next/sql-contract": "0.
|
|
13
|
-
"@prisma-next/utils": "0.
|
|
9
|
+
"@prisma-next/contract": "0.13.0-dev.1",
|
|
10
|
+
"@prisma-next/emitter": "0.13.0-dev.1",
|
|
11
|
+
"@prisma-next/framework-components": "0.13.0-dev.1",
|
|
12
|
+
"@prisma-next/sql-contract": "0.13.0-dev.1",
|
|
13
|
+
"@prisma-next/utils": "0.13.0-dev.1"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@prisma-next/test-utils": "0.
|
|
17
|
-
"@prisma-next/tsconfig": "0.
|
|
18
|
-
"@prisma-next/tsdown": "0.
|
|
19
|
-
"tsdown": "0.22.
|
|
16
|
+
"@prisma-next/test-utils": "0.13.0-dev.1",
|
|
17
|
+
"@prisma-next/tsconfig": "0.13.0-dev.1",
|
|
18
|
+
"@prisma-next/tsdown": "0.13.0-dev.1",
|
|
19
|
+
"tsdown": "0.22.1",
|
|
20
20
|
"typescript": "5.9.3",
|
|
21
|
-
"vitest": "4.1.
|
|
21
|
+
"vitest": "4.1.8"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"typescript": ">=5.9"
|
package/src/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type StorageTable,
|
|
18
18
|
type StorageTypeInstance,
|
|
19
19
|
} from '@prisma-next/sql-contract/types';
|
|
20
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
20
21
|
|
|
21
22
|
function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {
|
|
22
23
|
if (!params || Object.keys(params).length === 0) {
|
|
@@ -31,43 +32,6 @@ function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined)
|
|
|
31
32
|
return `{ ${entries.join('; ')} }`;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
/**
|
|
35
|
-
* Name-only lookup that walks every namespace until it finds a table
|
|
36
|
-
* with the given name. Survives this slice only for the two model-side
|
|
37
|
-
* call sites whose `SqlModelStorage.table` is still a bare name without
|
|
38
|
-
* a namespace coordinate; both call sites — and this helper — are
|
|
39
|
-
* deleted by TML-2584, which promotes `SqlModelStorage` to carry the
|
|
40
|
-
* model's namespace id so model→table resolution can use explicit
|
|
41
|
-
* coordinates like the FK-ref site already does.
|
|
42
|
-
*/
|
|
43
|
-
function findSqlTable(
|
|
44
|
-
storage: SqlStorage,
|
|
45
|
-
tableName: string,
|
|
46
|
-
): { readonly table: StorageTable; readonly namespaceId: string } | undefined {
|
|
47
|
-
for (const [namespaceId, ns] of Object.entries(storage.namespaces)) {
|
|
48
|
-
const table = ns.tables[tableName] as StorageTable | undefined;
|
|
49
|
-
if (table !== undefined) {
|
|
50
|
-
return { table, namespaceId };
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function assertUniqueSqlTableNames(storage: SqlStorage): void {
|
|
57
|
-
const seen = new Map<string, string>();
|
|
58
|
-
for (const [namespaceId, ns] of Object.entries(storage.namespaces)) {
|
|
59
|
-
for (const tableName of Object.keys(ns.tables)) {
|
|
60
|
-
const existing = seen.get(tableName);
|
|
61
|
-
if (existing !== undefined && existing !== namespaceId) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Duplicate table name "${tableName}" in namespaces "${existing}" and "${namespaceId}"`,
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
seen.set(tableName, namespaceId);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
35
|
export const sqlEmission = {
|
|
72
36
|
id: 'sql',
|
|
73
37
|
|
|
@@ -80,7 +44,7 @@ export const sqlEmission = {
|
|
|
80
44
|
const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
|
|
81
45
|
|
|
82
46
|
for (const ns of Object.values(storage.namespaces)) {
|
|
83
|
-
for (const [tableName, tableUnknown] of Object.entries(ns.
|
|
47
|
+
for (const [tableName, tableUnknown] of Object.entries(ns.entries.table)) {
|
|
84
48
|
const table = tableUnknown as StorageTable;
|
|
85
49
|
for (const [colName, colUnknown] of Object.entries(table.columns)) {
|
|
86
50
|
const col = colUnknown as { codecId?: string };
|
|
@@ -110,11 +74,22 @@ export const sqlEmission = {
|
|
|
110
74
|
throw new Error('SQL contract must have storage.namespaces');
|
|
111
75
|
}
|
|
112
76
|
|
|
113
|
-
|
|
77
|
+
const tableNamesSeenAcrossNamespaces = new Map<string, string>();
|
|
78
|
+
for (const [nsId, ns] of Object.entries(storage.namespaces)) {
|
|
79
|
+
for (const tableName of Object.keys(ns.entries.table)) {
|
|
80
|
+
const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
|
|
81
|
+
if (existingNs !== undefined && existingNs !== nsId) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
tableNamesSeenAcrossNamespaces.set(tableName, nsId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
114
89
|
|
|
115
90
|
const tableNames = new Set<string>();
|
|
116
91
|
for (const ns of Object.values(storage.namespaces)) {
|
|
117
|
-
for (const t of Object.keys(ns.
|
|
92
|
+
for (const t of Object.keys(ns.entries.table)) {
|
|
118
93
|
tableNames.add(t);
|
|
119
94
|
}
|
|
120
95
|
}
|
|
@@ -126,14 +101,24 @@ export const sqlEmission = {
|
|
|
126
101
|
if (!model.storage?.table) {
|
|
127
102
|
throw new Error(`Model "${qualifiedName}" is missing storage.table`);
|
|
128
103
|
}
|
|
104
|
+
if (!model.storage.namespaceId) {
|
|
105
|
+
throw new Error(`Model "${qualifiedName}" is missing storage.namespaceId`);
|
|
106
|
+
}
|
|
107
|
+
if (model.storage.namespaceId !== namespaceId) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
129
112
|
|
|
130
113
|
const tableName = model.storage.table;
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
114
|
+
const table = storage.namespaces[namespaceId]?.entries.table[tableName] as
|
|
115
|
+
| StorageTable
|
|
116
|
+
| undefined;
|
|
117
|
+
if (!table) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`,
|
|
120
|
+
);
|
|
134
121
|
}
|
|
135
|
-
|
|
136
|
-
const { table } = located;
|
|
137
122
|
const columnNames = new Set(Object.keys(table.columns));
|
|
138
123
|
const storageFields = model.storage.fields;
|
|
139
124
|
if (!storageFields || Object.keys(storageFields).length === 0) {
|
|
@@ -163,7 +148,7 @@ export const sqlEmission = {
|
|
|
163
148
|
}
|
|
164
149
|
|
|
165
150
|
for (const ns of Object.values(storage.namespaces)) {
|
|
166
|
-
for (const [tableName, tableUnknown] of Object.entries(ns.
|
|
151
|
+
for (const [tableName, tableUnknown] of Object.entries(ns.entries.table)) {
|
|
167
152
|
const table = tableUnknown as StorageTable;
|
|
168
153
|
const columnNames = new Set(Object.keys(table.columns));
|
|
169
154
|
|
|
@@ -222,7 +207,7 @@ export const sqlEmission = {
|
|
|
222
207
|
}
|
|
223
208
|
}
|
|
224
209
|
|
|
225
|
-
const referencedTable = storage.namespaces[fk.target.namespaceId]?.
|
|
210
|
+
const referencedTable = storage.namespaces[fk.target.namespaceId]?.entries.table[
|
|
226
211
|
fk.target.tableName
|
|
227
212
|
] as StorageTable | undefined;
|
|
228
213
|
if (!referencedTable) {
|
|
@@ -263,7 +248,10 @@ export const sqlEmission = {
|
|
|
263
248
|
const tableName = sqlModel.storage.table;
|
|
264
249
|
const storageFields = sqlModel.storage.fields;
|
|
265
250
|
|
|
266
|
-
const storageParts = [
|
|
251
|
+
const storageParts = [
|
|
252
|
+
`readonly table: ${serializeValue(tableName)}`,
|
|
253
|
+
`readonly namespaceId: ${serializeValue(sqlModel.storage.namespaceId)}`,
|
|
254
|
+
];
|
|
267
255
|
if (Object.keys(storageFields).length > 0) {
|
|
268
256
|
const fieldParts: string[] = [];
|
|
269
257
|
for (const [fieldName, field] of Object.entries(storageFields)) {
|
|
@@ -291,21 +279,25 @@ export const sqlEmission = {
|
|
|
291
279
|
if (!storage) return undefined;
|
|
292
280
|
|
|
293
281
|
const tableName = sqlModel.storage.table;
|
|
294
|
-
const
|
|
295
|
-
if (!
|
|
282
|
+
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
283
|
+
if (!storageNamespaceId) return undefined;
|
|
284
|
+
|
|
285
|
+
const table = storage.namespaces[storageNamespaceId]?.entries.table[tableName] as
|
|
286
|
+
| StorageTable
|
|
287
|
+
| undefined;
|
|
288
|
+
if (!table) return undefined;
|
|
296
289
|
|
|
297
|
-
const column =
|
|
290
|
+
const column = table.columns[storageField.column];
|
|
298
291
|
if (!column) return undefined;
|
|
299
292
|
|
|
300
293
|
if (column.typeRef) {
|
|
301
|
-
const ns = storage.namespaces[
|
|
294
|
+
const ns = storage.namespaces[storageNamespaceId];
|
|
302
295
|
const nsEnums =
|
|
303
|
-
ns !== undefined
|
|
304
|
-
?
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
).enum
|
|
296
|
+
ns !== undefined
|
|
297
|
+
? blindCast<
|
|
298
|
+
{ readonly type?: Readonly<Record<string, PostgresEnumStorageEntry>> },
|
|
299
|
+
'postgres target namespace entries carry a type slot beyond the family-shared SqlNamespace.entries type'
|
|
300
|
+
>(ns.entries).type
|
|
309
301
|
: undefined;
|
|
310
302
|
const fromNamespace = nsEnums?.[column.typeRef];
|
|
311
303
|
const typeInstance = fromNamespace ?? storage.types?.[column.typeRef];
|
|
@@ -357,7 +349,6 @@ export const sqlEmission = {
|
|
|
357
349
|
`export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,
|
|
358
350
|
'',
|
|
359
351
|
"export type Namespaces = Contract['storage']['namespaces'];",
|
|
360
|
-
'export type Models = ContractModelsMap<Contract>;',
|
|
361
352
|
].join('\n');
|
|
362
353
|
},
|
|
363
354
|
} as const;
|
|
@@ -371,7 +362,7 @@ function generateDocumentScopedStorageTypesType(types: SqlStorage['types']): str
|
|
|
371
362
|
for (const [typeName, typeInstance] of Object.entries(types)) {
|
|
372
363
|
if (isPostgresEnumStorageEntry(typeInstance)) {
|
|
373
364
|
throw new Error(
|
|
374
|
-
`Document-scoped storage.types entry "${typeName}" is a postgres-enum; enums belong under storage.namespaces[namespaceId].
|
|
365
|
+
`Document-scoped storage.types entry "${typeName}" is a postgres-enum; enums belong under storage.namespaces[namespaceId].entries.type`,
|
|
375
366
|
);
|
|
376
367
|
}
|
|
377
368
|
const codecInstanceShape = typeInstance as Partial<StorageTypeInstance>;
|
|
@@ -414,27 +405,16 @@ function generatePostgresNamespaceTypesType(
|
|
|
414
405
|
continue;
|
|
415
406
|
}
|
|
416
407
|
throw new Error(
|
|
417
|
-
`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.
|
|
408
|
+
`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.entries.type.`,
|
|
418
409
|
);
|
|
419
410
|
}
|
|
420
411
|
return `{ ${typeEntries.join('; ')} }`;
|
|
421
412
|
}
|
|
422
413
|
|
|
423
|
-
function isPostgresSchemaNamespace(ns: Namespace): ns is Namespace & {
|
|
424
|
-
readonly enum: Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>>;
|
|
425
|
-
} {
|
|
426
|
-
return (
|
|
427
|
-
(ns as { kind?: unknown }).kind === 'schema' &&
|
|
428
|
-
'enum' in ns &&
|
|
429
|
-
typeof (ns as { enum?: unknown }).enum === 'object' &&
|
|
430
|
-
(ns as { enum?: unknown }).enum !== null
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
414
|
const SQL_NAMESPACE_KIND_FALLBACK = 'sql-namespace' as const;
|
|
435
415
|
|
|
436
416
|
function namespaceSerializedKind(ns: Namespace): string {
|
|
437
|
-
const kind =
|
|
417
|
+
const kind = ns.kind;
|
|
438
418
|
if (kind === 'schema') {
|
|
439
419
|
const id = ns.id;
|
|
440
420
|
const lit = id === UNBOUND_NAMESPACE_ID ? 'postgres-unbound-schema' : 'postgres-schema';
|
|
@@ -546,13 +526,28 @@ function generateStorageNamespacesType(namespaces: SqlStorage['namespaces']): st
|
|
|
546
526
|
const parts: string[] = [];
|
|
547
527
|
for (const [name, ns] of entries) {
|
|
548
528
|
const kindSuffix = `; ${namespaceSerializedKind(ns)}`;
|
|
549
|
-
const tablesType = generateTablesMapType(
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
529
|
+
const tablesType = generateTablesMapType(
|
|
530
|
+
(ns.entries.table ?? {}) as Readonly<Record<string, StorageTable>>,
|
|
531
|
+
);
|
|
532
|
+
const typeSlot =
|
|
533
|
+
ns.kind === 'schema'
|
|
534
|
+
? blindCast<
|
|
535
|
+
Readonly<Record<string, PostgresEnumStorageEntry | StorageTypeInstance>> | undefined,
|
|
536
|
+
'postgres schema namespace entries carry a type slot beyond the family-shared SqlNamespace.entries type'
|
|
537
|
+
>(
|
|
538
|
+
blindCast<
|
|
539
|
+
{ readonly type?: Readonly<Record<string, unknown>> },
|
|
540
|
+
'access opaque type slot on postgres target namespace entries'
|
|
541
|
+
>(ns.entries).type,
|
|
542
|
+
)
|
|
543
|
+
: undefined;
|
|
544
|
+
const entriesParts = [`readonly table: ${tablesType}`];
|
|
545
|
+
if (typeSlot !== undefined) {
|
|
546
|
+
entriesParts.push(`readonly type: ${generatePostgresNamespaceTypesType(typeSlot)}`);
|
|
547
|
+
}
|
|
548
|
+
const entriesType = `{ ${entriesParts.join('; ')} }`;
|
|
554
549
|
parts.push(
|
|
555
|
-
`readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly
|
|
550
|
+
`readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly entries: ${entriesType} }`,
|
|
556
551
|
);
|
|
557
552
|
}
|
|
558
553
|
return `{ ${parts.join('; ')} }`;
|