@prisma-next/sql-contract-emitter 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +33 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +45 -77
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Contract,
|
|
1
|
+
import { Contract, ContractModelBase } from "@prisma-next/contract/types";
|
|
2
2
|
import { GenerateContractTypesOptions, ValidationContext } from "@prisma-next/framework-components/emission";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
@@ -7,8 +7,8 @@ declare const sqlEmission: {
|
|
|
7
7
|
readonly validateTypes: (contract: Contract, _ctx: ValidationContext) => void;
|
|
8
8
|
readonly validateStructure: (contract: Contract) => void;
|
|
9
9
|
readonly generateStorageType: (contract: Contract, storageHashTypeName: string) => string;
|
|
10
|
-
readonly generateModelStorageType: (_modelName: string, model:
|
|
11
|
-
readonly resolveFieldTypeParams: (_modelName: string, fieldName: string, model:
|
|
10
|
+
readonly generateModelStorageType: (_modelName: string, model: ContractModelBase) => string;
|
|
11
|
+
readonly resolveFieldTypeParams: (_modelName: string, fieldName: string, model: ContractModelBase, contract: Contract) => Record<string, unknown> | undefined;
|
|
12
12
|
readonly getFamilyImports: () => string[];
|
|
13
13
|
readonly getFamilyTypeAliases: (options?: GenerateContractTypesOptions) => string;
|
|
14
14
|
readonly getTypeMapsExpression: () => string;
|
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":";;;;cAoCa,WAAA;EAAA;qCAGa,QAAA,EAAQ,IAAA,EAAQ,iBAAA;EAAA,uCA4BZ,QAAA;EAAA,yCA8KE,QAAA,EAAQ,mBAAA;EAAA,wDAQK,KAAA,EAAS,iBAAA;EAAA,sDAuBhC,SAAA,UACD,KAAA,EACV,iBAAA,EAAiB,QAAA,EACd,QAAA,KACT,MAAA;EAAA;4CAwC4B,4BAAA;EAAA;0DAwBY,YAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { serializeNamespaceId, serializeObjectKey, serializeValue } from "@prisma-next/emitter/domain-type-generation";
|
|
2
|
-
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
3
|
-
import { isPostgresEnumStorageEntry } from "@prisma-next/sql-contract/types";
|
|
4
|
-
import { blindCast } from "@prisma-next/utils/casts";
|
|
2
|
+
import { UNBOUND_NAMESPACE_ID, entityAt } from "@prisma-next/framework-components/ir";
|
|
5
3
|
//#region src/index.ts
|
|
6
4
|
function serializeTypeParamsLiteral(params) {
|
|
7
5
|
if (!params || Object.keys(params).length === 0) return "Record<string, never>";
|
|
@@ -15,13 +13,10 @@ const sqlEmission = {
|
|
|
15
13
|
const storage = contract.storage;
|
|
16
14
|
if (!storage?.namespaces) return;
|
|
17
15
|
const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
|
|
18
|
-
for (const ns of Object.values(storage.namespaces)) for (const [tableName,
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (!codecId) throw new Error(`Column "${colName}" in table "${tableName}" is missing codecId`);
|
|
23
|
-
if (!codecId.match(typeIdRegex)?.[1]) throw new Error(`Column "${colName}" in table "${tableName}" has invalid codec ID format "${codecId}". Expected format: ns/name@version`);
|
|
24
|
-
}
|
|
16
|
+
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)) {
|
|
17
|
+
const codecId = colUnknown.codecId;
|
|
18
|
+
if (!codecId) throw new Error(`Column "${colName}" in table "${tableName}" is missing codecId`);
|
|
19
|
+
if (!codecId.match(typeIdRegex)?.[1]) throw new Error(`Column "${colName}" in table "${tableName}" has invalid codec ID format "${codecId}". Expected format: ns/name@version`);
|
|
25
20
|
}
|
|
26
21
|
},
|
|
27
22
|
validateStructure(contract) {
|
|
@@ -29,13 +24,13 @@ const sqlEmission = {
|
|
|
29
24
|
const storage = contract.storage;
|
|
30
25
|
if (!storage?.namespaces) throw new Error("SQL contract must have storage.namespaces");
|
|
31
26
|
const tableNamesSeenAcrossNamespaces = /* @__PURE__ */ new Map();
|
|
32
|
-
for (const [nsId, ns] of Object.entries(storage.namespaces)) for (const tableName of Object.keys(ns.entries.table)) {
|
|
27
|
+
for (const [nsId, ns] of Object.entries(storage.namespaces)) for (const tableName of Object.keys(ns.entries.table ?? {})) {
|
|
33
28
|
const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
|
|
34
29
|
if (existingNs !== void 0 && existingNs !== nsId) throw new Error(`Duplicate table name "${tableName}" in namespaces "${existingNs}" and "${nsId}"`);
|
|
35
30
|
tableNamesSeenAcrossNamespaces.set(tableName, nsId);
|
|
36
31
|
}
|
|
37
32
|
const tableNames = /* @__PURE__ */ new Set();
|
|
38
|
-
for (const ns of Object.values(storage.namespaces)) for (const t of Object.keys(ns.entries.table)) tableNames.add(t);
|
|
33
|
+
for (const ns of Object.values(storage.namespaces)) for (const t of Object.keys(ns.entries.table ?? {})) tableNames.add(t);
|
|
39
34
|
for (const [namespaceId, domainNs] of Object.entries(contract.domain.namespaces)) {
|
|
40
35
|
const models = domainNs.models;
|
|
41
36
|
for (const [modelName, model] of Object.entries(models)) {
|
|
@@ -44,7 +39,11 @@ const sqlEmission = {
|
|
|
44
39
|
if (!model.storage.namespaceId) throw new Error(`Model "${qualifiedName}" is missing storage.namespaceId`);
|
|
45
40
|
if (model.storage.namespaceId !== namespaceId) throw new Error(`Model "${qualifiedName}" storage.namespaceId "${model.storage.namespaceId}" does not match domain namespace "${namespaceId}"`);
|
|
46
41
|
const tableName = model.storage.table;
|
|
47
|
-
const table = storage
|
|
42
|
+
const table = entityAt(storage, {
|
|
43
|
+
namespaceId,
|
|
44
|
+
entityKind: "table",
|
|
45
|
+
entityName: tableName
|
|
46
|
+
});
|
|
48
47
|
if (!table) throw new Error(`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`);
|
|
49
48
|
const columnNames = new Set(Object.keys(table.columns));
|
|
50
49
|
const storageFields = model.storage.fields;
|
|
@@ -56,8 +55,7 @@ const sqlEmission = {
|
|
|
56
55
|
if (!model.relations || typeof model.relations !== "object") throw new Error(`Model "${qualifiedName}" is missing required field "relations" (must be an object)`);
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
|
-
for (const ns of Object.values(storage.namespaces)) for (const [tableName,
|
|
60
|
-
const table = tableUnknown;
|
|
58
|
+
for (const ns of Object.values(storage.namespaces)) for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {
|
|
61
59
|
const columnNames = new Set(Object.keys(table.columns));
|
|
62
60
|
if (!Array.isArray(table.uniques)) throw new Error(`Table "${tableName}" is missing required field "uniques" (must be an array)`);
|
|
63
61
|
if (!Array.isArray(table.indexes)) throw new Error(`Table "${tableName}" is missing required field "indexes" (must be an array)`);
|
|
@@ -69,7 +67,11 @@ const sqlEmission = {
|
|
|
69
67
|
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}"`);
|
|
70
68
|
for (const fk of table.foreignKeys) {
|
|
71
69
|
for (const colName of fk.source.columns) if (!columnNames.has(colName)) throw new Error(`Table "${tableName}" foreignKey references non-existent column "${colName}"`);
|
|
72
|
-
const referencedTable = storage
|
|
70
|
+
const referencedTable = entityAt(storage, {
|
|
71
|
+
namespaceId: fk.target.namespaceId,
|
|
72
|
+
entityKind: "table",
|
|
73
|
+
entityName: fk.target.tableName
|
|
74
|
+
});
|
|
73
75
|
if (!referencedTable) throw new Error(`Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`);
|
|
74
76
|
const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
|
|
75
77
|
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}"`);
|
|
@@ -104,15 +106,17 @@ const sqlEmission = {
|
|
|
104
106
|
const tableName = sqlModel.storage.table;
|
|
105
107
|
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
106
108
|
if (!storageNamespaceId) return void 0;
|
|
107
|
-
const table = storage
|
|
109
|
+
const table = entityAt(storage, {
|
|
110
|
+
namespaceId: storageNamespaceId,
|
|
111
|
+
entityKind: "table",
|
|
112
|
+
entityName: tableName
|
|
113
|
+
});
|
|
108
114
|
if (!table) return void 0;
|
|
109
115
|
const column = table.columns[storageField.column];
|
|
110
116
|
if (!column) return void 0;
|
|
111
117
|
if (column.typeRef) {
|
|
112
|
-
const
|
|
113
|
-
const typeInstance = (ns !== void 0 ? blindCast(ns.entries).type : void 0)?.[column.typeRef] ?? storage.types?.[column.typeRef];
|
|
118
|
+
const typeInstance = storage.types?.[column.typeRef];
|
|
114
119
|
if (typeInstance === void 0) return void 0;
|
|
115
|
-
if (isPostgresEnumStorageEntry(typeInstance)) return { values: typeInstance.values };
|
|
116
120
|
return typeInstance.typeParams;
|
|
117
121
|
}
|
|
118
122
|
return column.typeParams;
|
|
@@ -151,7 +155,6 @@ function generateDocumentScopedStorageTypesType(types) {
|
|
|
151
155
|
if (!types || Object.keys(types).length === 0) return;
|
|
152
156
|
const typeEntries = [];
|
|
153
157
|
for (const [typeName, typeInstance] of Object.entries(types)) {
|
|
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`);
|
|
155
158
|
const codecInstanceShape = typeInstance;
|
|
156
159
|
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.`);
|
|
157
160
|
const codecId = serializeValue(codecInstanceShape.codecId);
|
|
@@ -161,21 +164,14 @@ function generateDocumentScopedStorageTypesType(types) {
|
|
|
161
164
|
}
|
|
162
165
|
return `{ ${typeEntries.join("; ")} }`;
|
|
163
166
|
}
|
|
164
|
-
function
|
|
165
|
-
if (Object.keys(
|
|
166
|
-
const
|
|
167
|
-
for (const [
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const nativeType = serializeValue(typeInstance.nativeType);
|
|
171
|
-
const name = serializeValue(typeInstance.name);
|
|
172
|
-
const valuesLiteral = typeInstance.values.map((v) => serializeValue(v)).join(", ");
|
|
173
|
-
typeEntries.push(`readonly ${serializeObjectKey(typeName)}: { readonly kind: 'postgres-enum'; readonly name: ${name}; readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly values: readonly [${valuesLiteral}] }`);
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
throw new Error(`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.entries.type.`);
|
|
167
|
+
function generateNamespaceValueSetType(valueSet) {
|
|
168
|
+
if (Object.keys(valueSet).length === 0) return "Record<string, never>";
|
|
169
|
+
const entries = [];
|
|
170
|
+
for (const [name, vs] of Object.entries(valueSet)) {
|
|
171
|
+
const valuesLiteral = vs.values.map((v) => serializeValue(v)).join(", ");
|
|
172
|
+
entries.push(`readonly ${serializeObjectKey(name)}: { readonly kind: 'valueSet'; readonly values: readonly [${valuesLiteral}] }`);
|
|
177
173
|
}
|
|
178
|
-
return `{ ${
|
|
174
|
+
return `{ ${entries.join("; ")} }`;
|
|
179
175
|
}
|
|
180
176
|
const SQL_NAMESPACE_KIND_FALLBACK = "sql-namespace";
|
|
181
177
|
function namespaceSerializedKind(ns) {
|
|
@@ -231,9 +227,9 @@ function generateStorageNamespacesType(namespaces) {
|
|
|
231
227
|
for (const [name, ns] of entries) {
|
|
232
228
|
const kindSuffix = `; ${namespaceSerializedKind(ns)}`;
|
|
233
229
|
const tablesType = generateTablesMapType(ns.entries.table ?? {});
|
|
234
|
-
const
|
|
230
|
+
const valueSetSlot = ns.entries.valueSet;
|
|
235
231
|
const entriesParts = [`readonly table: ${tablesType}`];
|
|
236
|
-
if (
|
|
232
|
+
if (valueSetSlot !== void 0 && Object.keys(valueSetSlot).length > 0) entriesParts.push(`readonly valueSet: ${generateNamespaceValueSetType(valueSetSlot)}`);
|
|
237
233
|
const entriesType = `{ ${entriesParts.join("; ")} }`;
|
|
238
234
|
parts.push(`readonly ${serializeObjectKey(name)}: { readonly id: ${serializeValue(ns.id)}${kindSuffix}; readonly entries: ${entriesType} }`);
|
|
239
235
|
}
|
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';\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":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/index.ts"],"sourcesContent":["import type { Contract, ContractModel, ContractModelBase } 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 {\n entityAt,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport type {\n SqlModelStorage,\n SqlStorage,\n StorageTable,\n StorageTypeInstance,\n StorageValueSet,\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\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 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 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 generateNamespaceValueSetType(\n valueSet: Readonly<Record<string, StorageValueSet>>,\n): string {\n if (Object.keys(valueSet).length === 0) {\n return 'Record<string, never>';\n }\n const entries: string[] = [];\n for (const [name, vs] of Object.entries(valueSet)) {\n const valuesLiteral = vs.values.map((v) => serializeValue(v)).join(', ');\n entries.push(\n `readonly ${serializeObjectKey(name)}: { readonly kind: 'valueSet'; readonly values: readonly [${valuesLiteral}] }`,\n );\n }\n return `{ ${entries.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 valueSetSlot = ns.entries.valueSet;\n const entriesParts = [`readonly table: ${tablesType}`];\n if (valueSetSlot !== undefined && Object.keys(valueSetSlot).length > 0) {\n entriesParts.push(`readonly valueSet: ${generateNamespaceValueSetType(valueSetSlot)}`);\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.
|
|
3
|
+
"version": "0.14.0",
|
|
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.14.0",
|
|
10
|
+
"@prisma-next/emitter": "0.14.0",
|
|
11
|
+
"@prisma-next/framework-components": "0.14.0",
|
|
12
|
+
"@prisma-next/sql-contract": "0.14.0",
|
|
13
|
+
"@prisma-next/utils": "0.14.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@prisma-next/test-utils": "0.
|
|
17
|
-
"@prisma-next/tsconfig": "0.
|
|
18
|
-
"@prisma-next/tsdown": "0.
|
|
16
|
+
"@prisma-next/test-utils": "0.14.0",
|
|
17
|
+
"@prisma-next/tsconfig": "0.14.0",
|
|
18
|
+
"@prisma-next/tsdown": "0.14.0",
|
|
19
19
|
"tsdown": "0.22.1",
|
|
20
20
|
"typescript": "5.9.3",
|
|
21
21
|
"vitest": "4.1.8"
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Contract, ContractModel } from '@prisma-next/contract/types';
|
|
1
|
+
import type { Contract, ContractModel, ContractModelBase } from '@prisma-next/contract/types';
|
|
2
2
|
import {
|
|
3
3
|
serializeNamespaceId,
|
|
4
4
|
serializeObjectKey,
|
|
@@ -8,16 +8,18 @@ import type {
|
|
|
8
8
|
GenerateContractTypesOptions,
|
|
9
9
|
ValidationContext,
|
|
10
10
|
} from '@prisma-next/framework-components/emission';
|
|
11
|
-
import { type Namespace, UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
12
11
|
import {
|
|
13
|
-
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
entityAt,
|
|
13
|
+
type Namespace,
|
|
14
|
+
UNBOUND_NAMESPACE_ID,
|
|
15
|
+
} from '@prisma-next/framework-components/ir';
|
|
16
|
+
import type {
|
|
17
|
+
SqlModelStorage,
|
|
18
|
+
SqlStorage,
|
|
19
|
+
StorageTable,
|
|
20
|
+
StorageTypeInstance,
|
|
21
|
+
StorageValueSet,
|
|
19
22
|
} from '@prisma-next/sql-contract/types';
|
|
20
|
-
import { blindCast } from '@prisma-next/utils/casts';
|
|
21
23
|
|
|
22
24
|
function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {
|
|
23
25
|
if (!params || Object.keys(params).length === 0) {
|
|
@@ -44,8 +46,7 @@ export const sqlEmission = {
|
|
|
44
46
|
const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
|
|
45
47
|
|
|
46
48
|
for (const ns of Object.values(storage.namespaces)) {
|
|
47
|
-
for (const [tableName,
|
|
48
|
-
const table = tableUnknown as StorageTable;
|
|
49
|
+
for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {
|
|
49
50
|
for (const [colName, colUnknown] of Object.entries(table.columns)) {
|
|
50
51
|
const col = colUnknown as { codecId?: string };
|
|
51
52
|
const codecId = col.codecId;
|
|
@@ -76,7 +77,7 @@ export const sqlEmission = {
|
|
|
76
77
|
|
|
77
78
|
const tableNamesSeenAcrossNamespaces = new Map<string, string>();
|
|
78
79
|
for (const [nsId, ns] of Object.entries(storage.namespaces)) {
|
|
79
|
-
for (const tableName of Object.keys(ns.entries.table)) {
|
|
80
|
+
for (const tableName of Object.keys(ns.entries.table ?? {})) {
|
|
80
81
|
const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);
|
|
81
82
|
if (existingNs !== undefined && existingNs !== nsId) {
|
|
82
83
|
throw new Error(
|
|
@@ -89,7 +90,7 @@ export const sqlEmission = {
|
|
|
89
90
|
|
|
90
91
|
const tableNames = new Set<string>();
|
|
91
92
|
for (const ns of Object.values(storage.namespaces)) {
|
|
92
|
-
for (const t of Object.keys(ns.entries.table)) {
|
|
93
|
+
for (const t of Object.keys(ns.entries.table ?? {})) {
|
|
93
94
|
tableNames.add(t);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
@@ -111,9 +112,11 @@ export const sqlEmission = {
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
const tableName = model.storage.table;
|
|
114
|
-
const table = storage
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
const table = entityAt<StorageTable>(storage, {
|
|
116
|
+
namespaceId,
|
|
117
|
+
entityKind: 'table',
|
|
118
|
+
entityName: tableName,
|
|
119
|
+
});
|
|
117
120
|
if (!table) {
|
|
118
121
|
throw new Error(
|
|
119
122
|
`Model "${qualifiedName}" references non-existent table "${namespaceId}.${tableName}"`,
|
|
@@ -148,8 +151,7 @@ export const sqlEmission = {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
for (const ns of Object.values(storage.namespaces)) {
|
|
151
|
-
for (const [tableName,
|
|
152
|
-
const table = tableUnknown as StorageTable;
|
|
154
|
+
for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {
|
|
153
155
|
const columnNames = new Set(Object.keys(table.columns));
|
|
154
156
|
|
|
155
157
|
if (!Array.isArray(table.uniques)) {
|
|
@@ -207,9 +209,11 @@ export const sqlEmission = {
|
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
|
|
210
|
-
const referencedTable = storage
|
|
211
|
-
fk.target.
|
|
212
|
-
|
|
212
|
+
const referencedTable = entityAt<StorageTable>(storage, {
|
|
213
|
+
namespaceId: fk.target.namespaceId,
|
|
214
|
+
entityKind: 'table',
|
|
215
|
+
entityName: fk.target.tableName,
|
|
216
|
+
});
|
|
213
217
|
if (!referencedTable) {
|
|
214
218
|
throw new Error(
|
|
215
219
|
`Table "${tableName}" foreignKey references non-existent table "${fk.target.tableName}" in namespace "${fk.target.namespaceId}"`,
|
|
@@ -243,7 +247,7 @@ export const sqlEmission = {
|
|
|
243
247
|
return `{ readonly namespaces: ${namespacesType}${typesClause}; readonly storageHash: ${storageHashTypeName} }`;
|
|
244
248
|
},
|
|
245
249
|
|
|
246
|
-
generateModelStorageType(_modelName: string, model:
|
|
250
|
+
generateModelStorageType(_modelName: string, model: ContractModelBase): string {
|
|
247
251
|
const sqlModel = model as ContractModel<SqlModelStorage>;
|
|
248
252
|
const tableName = sqlModel.storage.table;
|
|
249
253
|
const storageFields = sqlModel.storage.fields;
|
|
@@ -268,7 +272,7 @@ export const sqlEmission = {
|
|
|
268
272
|
resolveFieldTypeParams(
|
|
269
273
|
_modelName: string,
|
|
270
274
|
fieldName: string,
|
|
271
|
-
model:
|
|
275
|
+
model: ContractModelBase,
|
|
272
276
|
contract: Contract,
|
|
273
277
|
): Record<string, unknown> | undefined {
|
|
274
278
|
const sqlModel = model as ContractModel<SqlModelStorage>;
|
|
@@ -282,29 +286,19 @@ export const sqlEmission = {
|
|
|
282
286
|
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
283
287
|
if (!storageNamespaceId) return undefined;
|
|
284
288
|
|
|
285
|
-
const table = storage
|
|
286
|
-
|
|
287
|
-
|
|
289
|
+
const table = entityAt<StorageTable>(storage, {
|
|
290
|
+
namespaceId: storageNamespaceId,
|
|
291
|
+
entityKind: 'table',
|
|
292
|
+
entityName: tableName,
|
|
293
|
+
});
|
|
288
294
|
if (!table) return undefined;
|
|
289
295
|
|
|
290
296
|
const column = table.columns[storageField.column];
|
|
291
297
|
if (!column) return undefined;
|
|
292
298
|
|
|
293
299
|
if (column.typeRef) {
|
|
294
|
-
const
|
|
295
|
-
const nsEnums =
|
|
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
|
|
301
|
-
: undefined;
|
|
302
|
-
const fromNamespace = nsEnums?.[column.typeRef];
|
|
303
|
-
const typeInstance = fromNamespace ?? storage.types?.[column.typeRef];
|
|
300
|
+
const typeInstance = storage.types?.[column.typeRef];
|
|
304
301
|
if (typeInstance === undefined) return undefined;
|
|
305
|
-
if (isPostgresEnumStorageEntry(typeInstance)) {
|
|
306
|
-
return { values: typeInstance.values };
|
|
307
|
-
}
|
|
308
302
|
const codecShape = typeInstance as Partial<StorageTypeInstance>;
|
|
309
303
|
return codecShape.typeParams;
|
|
310
304
|
}
|
|
@@ -360,11 +354,6 @@ function generateDocumentScopedStorageTypesType(types: SqlStorage['types']): str
|
|
|
360
354
|
|
|
361
355
|
const typeEntries: string[] = [];
|
|
362
356
|
for (const [typeName, typeInstance] of Object.entries(types)) {
|
|
363
|
-
if (isPostgresEnumStorageEntry(typeInstance)) {
|
|
364
|
-
throw new Error(
|
|
365
|
-
`Document-scoped storage.types entry "${typeName}" is a postgres-enum; enums belong under storage.namespaces[namespaceId].entries.type`,
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
357
|
const codecInstanceShape = typeInstance as Partial<StorageTypeInstance>;
|
|
369
358
|
if (
|
|
370
359
|
typeof codecInstanceShape.codecId !== 'string' ||
|
|
@@ -385,30 +374,20 @@ function generateDocumentScopedStorageTypesType(types: SqlStorage['types']): str
|
|
|
385
374
|
return `{ ${typeEntries.join('; ')} }`;
|
|
386
375
|
}
|
|
387
376
|
|
|
388
|
-
function
|
|
389
|
-
|
|
377
|
+
function generateNamespaceValueSetType(
|
|
378
|
+
valueSet: Readonly<Record<string, StorageValueSet>>,
|
|
390
379
|
): string {
|
|
391
|
-
if (Object.keys(
|
|
380
|
+
if (Object.keys(valueSet).length === 0) {
|
|
392
381
|
return 'Record<string, never>';
|
|
393
382
|
}
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const nativeType = serializeValue(typeInstance.nativeType);
|
|
400
|
-
const name = serializeValue(typeInstance.name);
|
|
401
|
-
const valuesLiteral = typeInstance.values.map((v) => serializeValue(v)).join(', ');
|
|
402
|
-
typeEntries.push(
|
|
403
|
-
`readonly ${serializeObjectKey(typeName)}: { readonly kind: 'postgres-enum'; readonly name: ${name}; readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly values: readonly [${valuesLiteral}] }`,
|
|
404
|
-
);
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
throw new Error(
|
|
408
|
-
`Unknown namespace storage type kind for "${typeName}"; expected postgres-enum in namespace.entries.type.`,
|
|
383
|
+
const entries: string[] = [];
|
|
384
|
+
for (const [name, vs] of Object.entries(valueSet)) {
|
|
385
|
+
const valuesLiteral = vs.values.map((v) => serializeValue(v)).join(', ');
|
|
386
|
+
entries.push(
|
|
387
|
+
`readonly ${serializeObjectKey(name)}: { readonly kind: 'valueSet'; readonly values: readonly [${valuesLiteral}] }`,
|
|
409
388
|
);
|
|
410
389
|
}
|
|
411
|
-
return `{ ${
|
|
390
|
+
return `{ ${entries.join('; ')} }`;
|
|
412
391
|
}
|
|
413
392
|
|
|
414
393
|
const SQL_NAMESPACE_KIND_FALLBACK = 'sql-namespace' as const;
|
|
@@ -529,21 +508,10 @@ function generateStorageNamespacesType(namespaces: SqlStorage['namespaces']): st
|
|
|
529
508
|
const tablesType = generateTablesMapType(
|
|
530
509
|
(ns.entries.table ?? {}) as Readonly<Record<string, StorageTable>>,
|
|
531
510
|
);
|
|
532
|
-
const
|
|
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;
|
|
511
|
+
const valueSetSlot = ns.entries.valueSet;
|
|
544
512
|
const entriesParts = [`readonly table: ${tablesType}`];
|
|
545
|
-
if (
|
|
546
|
-
entriesParts.push(`readonly
|
|
513
|
+
if (valueSetSlot !== undefined && Object.keys(valueSetSlot).length > 0) {
|
|
514
|
+
entriesParts.push(`readonly valueSet: ${generateNamespaceValueSetType(valueSetSlot)}`);
|
|
547
515
|
}
|
|
548
516
|
const entriesType = `{ ${entriesParts.join('; ')} }`;
|
|
549
517
|
parts.push(
|