@prisma-next/sql-contract-emitter 0.14.0-dev.4 → 0.14.0-dev.41
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 +7 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +89 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +167 -10
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Contract, ContractModelBase } from "@prisma-next/contract/types";
|
|
1
|
+
import { Contract, ContractModelBase, JsonValue } from "@prisma-next/contract/types";
|
|
2
|
+
import { CodecLookup } from "@prisma-next/framework-components/codec";
|
|
2
3
|
import { GenerateContractTypesOptions, ValidationContext } from "@prisma-next/framework-components/emission";
|
|
3
4
|
|
|
4
5
|
//#region src/index.d.ts
|
|
@@ -9,6 +10,11 @@ declare const sqlEmission: {
|
|
|
9
10
|
readonly generateStorageType: (contract: Contract, storageHashTypeName: string) => string;
|
|
10
11
|
readonly generateModelStorageType: (_modelName: string, model: ContractModelBase) => string;
|
|
11
12
|
readonly resolveFieldTypeParams: (_modelName: string, fieldName: string, model: ContractModelBase, contract: Contract) => Record<string, unknown> | undefined;
|
|
13
|
+
readonly resolveFieldValueSet: (_modelName: string, fieldName: string, model: ContractModelBase, contract: Contract) => {
|
|
14
|
+
readonly encodedValues: readonly JsonValue[];
|
|
15
|
+
readonly codecId: string;
|
|
16
|
+
} | undefined;
|
|
17
|
+
readonly getStorageTypeExports: (contract: Contract, codecLookup?: CodecLookup) => string | undefined;
|
|
12
18
|
readonly getFamilyImports: () => string[];
|
|
13
19
|
readonly getFamilyTypeAliases: (options?: GenerateContractTypesOptions) => string;
|
|
14
20
|
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":";;;;;cA8Ca,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,oDAgCiB,SAAA,UACD,KAAA,EACV,iBAAA,EAAiB,QAAA,EACd,QAAA;IAAA,SACE,aAAA,WAAwB,SAAA;IAAA,SAAsB,OAAA;EAAA;EAAA,2CAmC5B,QAAA,EAAQ,WAAA,GAAgB,WAAA;EAAA;4CAuBzB,4BAAA;EAAA;0DAwBY,YAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { serializeNamespaceId, serializeObjectKey, serializeValue } from "@prisma-next/emitter/domain-type-generation";
|
|
1
|
+
import { renderValueSetType, serializeNamespaceId, serializeObjectKey, serializeValue } from "@prisma-next/emitter/domain-type-generation";
|
|
2
|
+
import { isSafeTypeExpression } from "@prisma-next/emitter/type-expression-safety";
|
|
2
3
|
import { UNBOUND_NAMESPACE_ID, entityAt } from "@prisma-next/framework-components/ir";
|
|
4
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
3
5
|
//#region src/index.ts
|
|
4
6
|
function serializeTypeParamsLiteral(params) {
|
|
5
7
|
if (!params || Object.keys(params).length === 0) return "Record<string, never>";
|
|
@@ -121,6 +123,38 @@ const sqlEmission = {
|
|
|
121
123
|
}
|
|
122
124
|
return column.typeParams;
|
|
123
125
|
},
|
|
126
|
+
resolveFieldValueSet(_modelName, fieldName, model, contract) {
|
|
127
|
+
const sqlModel = blindCast(model);
|
|
128
|
+
const storageField = sqlModel.storage?.fields?.[fieldName];
|
|
129
|
+
if (!storageField) return void 0;
|
|
130
|
+
const storage = blindCast(contract.storage);
|
|
131
|
+
if (!storage) return void 0;
|
|
132
|
+
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
133
|
+
if (!storageNamespaceId) return void 0;
|
|
134
|
+
const column = entityAt(storage, {
|
|
135
|
+
namespaceId: storageNamespaceId,
|
|
136
|
+
entityKind: "table",
|
|
137
|
+
entityName: sqlModel.storage.table
|
|
138
|
+
})?.columns[storageField.column];
|
|
139
|
+
if (!column?.valueSet) return void 0;
|
|
140
|
+
const valueSet = entityAt(storage, {
|
|
141
|
+
namespaceId: column.valueSet.namespaceId,
|
|
142
|
+
entityKind: column.valueSet.entityKind,
|
|
143
|
+
entityName: column.valueSet.entityName
|
|
144
|
+
});
|
|
145
|
+
if (!valueSet) return void 0;
|
|
146
|
+
return {
|
|
147
|
+
encodedValues: valueSet.values,
|
|
148
|
+
codecId: column.codecId
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
getStorageTypeExports(contract, codecLookup) {
|
|
152
|
+
const storage = blindCast(contract.storage);
|
|
153
|
+
if (!storage?.namespaces) return void 0;
|
|
154
|
+
const outputMap = generateStorageColumnTypesMap(storage, "output", codecLookup);
|
|
155
|
+
const inputMap = generateStorageColumnTypesMap(storage, "input", codecLookup);
|
|
156
|
+
return [`export type StorageColumnTypes = ${outputMap};`, `export type StorageColumnInputTypes = ${inputMap};`].join("\n");
|
|
157
|
+
},
|
|
124
158
|
getFamilyImports() {
|
|
125
159
|
return [
|
|
126
160
|
"import type {",
|
|
@@ -141,7 +175,7 @@ const sqlEmission = {
|
|
|
141
175
|
].join("\n");
|
|
142
176
|
},
|
|
143
177
|
getTypeMapsExpression() {
|
|
144
|
-
return "TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes>";
|
|
178
|
+
return "TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes, StorageColumnTypes, StorageColumnInputTypes>";
|
|
145
179
|
},
|
|
146
180
|
getContractWrapper(contractBaseName, typeMapsName) {
|
|
147
181
|
return [
|
|
@@ -151,6 +185,58 @@ const sqlEmission = {
|
|
|
151
185
|
].join("\n");
|
|
152
186
|
}
|
|
153
187
|
};
|
|
188
|
+
function columnTypeParams(storage, column) {
|
|
189
|
+
if (column.typeRef) {
|
|
190
|
+
const typeInstance = storage.types?.[column.typeRef];
|
|
191
|
+
if (typeInstance === void 0) return void 0;
|
|
192
|
+
return blindCast(typeInstance).typeParams;
|
|
193
|
+
}
|
|
194
|
+
return column.typeParams;
|
|
195
|
+
}
|
|
196
|
+
function renderRefinedCodecType(column, side, params, codecLookup) {
|
|
197
|
+
if (codecLookup && params && Object.keys(params).length > 0) {
|
|
198
|
+
const rendered = side === "output" ? codecLookup.renderOutputTypeFor(column.codecId, params) : codecLookup.renderInputTypeFor?.(column.codecId, params);
|
|
199
|
+
if (rendered && isSafeTypeExpression(rendered)) return rendered;
|
|
200
|
+
}
|
|
201
|
+
return `CodecTypes[${serializeValue(column.codecId)}][${serializeValue(side)}]`;
|
|
202
|
+
}
|
|
203
|
+
function computeColumnType(storage, column, side, codecLookup) {
|
|
204
|
+
let base;
|
|
205
|
+
if (column.valueSet) {
|
|
206
|
+
const valueSet = entityAt(storage, {
|
|
207
|
+
namespaceId: column.valueSet.namespaceId,
|
|
208
|
+
entityKind: column.valueSet.entityKind,
|
|
209
|
+
entityName: column.valueSet.entityName
|
|
210
|
+
});
|
|
211
|
+
base = valueSet ? renderValueSetType(valueSet.values, column.codecId, side, codecLookup) : void 0;
|
|
212
|
+
}
|
|
213
|
+
if (base === void 0) base = renderRefinedCodecType(column, side, columnTypeParams(storage, column), codecLookup);
|
|
214
|
+
if (column.many === true) base = `ReadonlyArray<${base}>`;
|
|
215
|
+
return column.nullable ? `${base} | null` : base;
|
|
216
|
+
}
|
|
217
|
+
function generateStorageColumnTypesMap(storage, side, codecLookup) {
|
|
218
|
+
const namespaceEntries = Object.entries(storage.namespaces ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
219
|
+
if (namespaceEntries.length === 0) return "Record<string, never>";
|
|
220
|
+
const nsParts = [];
|
|
221
|
+
for (const [nsId, ns] of namespaceEntries) {
|
|
222
|
+
const tables = blindCast(ns.entries.table ?? {});
|
|
223
|
+
const tableEntries = Object.entries(tables).sort(([a], [b]) => a.localeCompare(b));
|
|
224
|
+
const tableParts = [];
|
|
225
|
+
for (const [tableName, table] of tableEntries) {
|
|
226
|
+
const colEntries = Object.entries(table.columns).sort(([a], [b]) => a.localeCompare(b));
|
|
227
|
+
const colParts = [];
|
|
228
|
+
for (const [colName, col] of colEntries) {
|
|
229
|
+
const colType = computeColumnType(storage, col, side, codecLookup);
|
|
230
|
+
colParts.push(`readonly ${serializeObjectKey(colName)}: ${colType}`);
|
|
231
|
+
}
|
|
232
|
+
const colMap = colParts.length > 0 ? `{ ${colParts.join("; ")} }` : "{}";
|
|
233
|
+
tableParts.push(`readonly ${serializeObjectKey(tableName)}: ${colMap}`);
|
|
234
|
+
}
|
|
235
|
+
const tableMap = tableParts.length > 0 ? `{ ${tableParts.join("; ")} }` : "{}";
|
|
236
|
+
nsParts.push(`readonly ${serializeObjectKey(nsId)}: ${tableMap}`);
|
|
237
|
+
}
|
|
238
|
+
return `{ ${nsParts.join("; ")} }`;
|
|
239
|
+
}
|
|
154
240
|
function generateDocumentScopedStorageTypesType(types) {
|
|
155
241
|
if (!types || Object.keys(types).length === 0) return;
|
|
156
242
|
const typeEntries = [];
|
|
@@ -173,12 +259,11 @@ function generateNamespaceValueSetType(valueSet) {
|
|
|
173
259
|
}
|
|
174
260
|
return `{ ${entries.join("; ")} }`;
|
|
175
261
|
}
|
|
176
|
-
const SQL_NAMESPACE_KIND_FALLBACK = "sql-namespace";
|
|
177
262
|
function namespaceSerializedKind(ns) {
|
|
178
263
|
const kind = ns.kind;
|
|
179
264
|
if (kind === "schema") return `readonly kind: '${ns.id === UNBOUND_NAMESPACE_ID ? "postgres-unbound-schema" : "postgres-schema"}'`;
|
|
180
265
|
if (typeof kind === "string") return `readonly kind: ${serializeValue(kind)}`;
|
|
181
|
-
|
|
266
|
+
throw new Error(`Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`);
|
|
182
267
|
}
|
|
183
268
|
function generateTableLiteralType(table) {
|
|
184
269
|
const columns = [];
|
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, 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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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["col","codecShape"],"sources":["../src/index.ts"],"sourcesContent":["import type {\n Contract,\n ContractModel,\n ContractModelBase,\n JsonValue,\n} from '@prisma-next/contract/types';\nimport {\n renderValueSetType,\n serializeNamespaceId,\n serializeObjectKey,\n serializeValue,\n} from '@prisma-next/emitter/domain-type-generation';\nimport { isSafeTypeExpression } from '@prisma-next/emitter/type-expression-safety';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type {\n GenerateContractTypesOptions,\n ValidationContext,\n} from '@prisma-next/framework-components/emission';\nimport {\n entityAt,\n type Namespace,\n UNBOUND_NAMESPACE_ID,\n} from '@prisma-next/framework-components/ir';\nimport type {\n SqlModelStorage,\n SqlStorage,\n StorageColumn,\n StorageTable,\n StorageTypeInstance,\n StorageValueSet,\n} from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\n\nfunction serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return 'Record<string, never>';\n }\n\n const entries: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n entries.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);\n }\n\n return `{ ${entries.join('; ')} }`;\n}\n\nexport const sqlEmission = {\n id: 'sql',\n\n validateTypes(contract: Contract, _ctx: ValidationContext): void {\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n return;\n }\n\n const typeIdRegex = /^([^/]+)\\/([^@]+)@(\\d+)$/;\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n for (const [colName, colUnknown] of Object.entries(table.columns)) {\n const col = colUnknown as { codecId?: string };\n const codecId = col.codecId;\n if (!codecId) {\n throw new Error(`Column \"${colName}\" in table \"${tableName}\" is missing codecId`);\n }\n\n const match = codecId.match(typeIdRegex);\n if (!match?.[1]) {\n throw new Error(\n `Column \"${colName}\" in table \"${tableName}\" has invalid codec ID format \"${codecId}\". Expected format: ns/name@version`,\n );\n }\n }\n }\n }\n },\n\n validateStructure(contract: Contract): void {\n if (contract.targetFamily !== 'sql') {\n throw new Error(`Expected targetFamily \"sql\", got \"${contract.targetFamily}\"`);\n }\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage?.namespaces) {\n throw new Error('SQL contract must have storage.namespaces');\n }\n\n const tableNamesSeenAcrossNamespaces = new Map<string, string>();\n for (const [nsId, ns] of Object.entries(storage.namespaces)) {\n for (const tableName of Object.keys(ns.entries.table ?? {})) {\n const existingNs = tableNamesSeenAcrossNamespaces.get(tableName);\n if (existingNs !== undefined && existingNs !== nsId) {\n throw new Error(\n `Duplicate table name \"${tableName}\" in namespaces \"${existingNs}\" and \"${nsId}\"`,\n );\n }\n tableNamesSeenAcrossNamespaces.set(tableName, nsId);\n }\n }\n\n const tableNames = new Set<string>();\n for (const ns of Object.values(storage.namespaces)) {\n for (const t of Object.keys(ns.entries.table ?? {})) {\n tableNames.add(t);\n }\n }\n\n for (const [namespaceId, domainNs] of Object.entries(contract.domain.namespaces)) {\n const models = domainNs.models as Record<string, ContractModel<SqlModelStorage>>;\n for (const [modelName, model] of Object.entries(models)) {\n const qualifiedName = `${namespaceId}:${modelName}`;\n if (!model.storage?.table) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.table`);\n }\n if (!model.storage.namespaceId) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.namespaceId`);\n }\n if (model.storage.namespaceId !== namespaceId) {\n throw new Error(\n `Model \"${qualifiedName}\" storage.namespaceId \"${model.storage.namespaceId}\" does not match domain namespace \"${namespaceId}\"`,\n );\n }\n\n const tableName = model.storage.table;\n const table = entityAt<StorageTable>(storage, {\n namespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) {\n throw new Error(\n `Model \"${qualifiedName}\" references non-existent table \"${namespaceId}.${tableName}\"`,\n );\n }\n const columnNames = new Set(Object.keys(table.columns));\n const storageFields = model.storage.fields;\n if (!storageFields || Object.keys(storageFields).length === 0) {\n throw new Error(`Model \"${qualifiedName}\" is missing storage.fields`);\n }\n\n for (const [fieldName, field] of Object.entries(storageFields)) {\n if (!field.column) {\n throw new Error(\n `Model \"${qualifiedName}\" field \"${fieldName}\" is missing column property`,\n );\n }\n\n if (!columnNames.has(field.column)) {\n throw new Error(\n `Model \"${qualifiedName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${tableName}\"`,\n );\n }\n }\n\n if (!model.relations || typeof model.relations !== 'object') {\n throw new Error(\n `Model \"${qualifiedName}\" is missing required field \"relations\" (must be an object)`,\n );\n }\n }\n }\n\n for (const ns of Object.values(storage.namespaces)) {\n for (const [tableName, table] of Object.entries(ns.entries.table ?? {})) {\n const columnNames = new Set(Object.keys(table.columns));\n\n if (!Array.isArray(table.uniques)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"uniques\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.indexes)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"indexes\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.foreignKeys)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"foreignKeys\" (must be an array)`,\n );\n }\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const colName of unique.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const index of table.indexes) {\n for (const colName of index.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.source.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n );\n }\n }\n\n const referencedTable = entityAt<StorageTable>(storage, {\n namespaceId: fk.target.namespaceId,\n entityKind: 'table',\n entityName: fk.target.tableName,\n });\n if (!referencedTable) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.target.tableName}\" in namespace \"${fk.target.namespaceId}\"`,\n );\n }\n\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.target.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.target.tableName}\"`,\n );\n }\n }\n\n if (fk.source.columns.length !== fk.target.columns.length) {\n throw new Error(\n `Table \"${tableName}\" foreignKey column count (${fk.source.columns.length}) does not match referenced column count (${fk.target.columns.length})`,\n );\n }\n }\n }\n }\n },\n\n generateStorageType(contract: Contract, storageHashTypeName: string): string {\n const storage = contract.storage as unknown as SqlStorage;\n const namespacesType = generateStorageNamespacesType(storage.namespaces);\n const docTypes = generateDocumentScopedStorageTypesType(storage.types);\n const typesClause = docTypes === undefined ? '' : `; readonly types: ${docTypes}`;\n return `{ readonly namespaces: ${namespacesType}${typesClause}; readonly storageHash: ${storageHashTypeName} }`;\n },\n\n generateModelStorageType(_modelName: string, model: ContractModelBase): string {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const tableName = sqlModel.storage.table;\n const storageFields = sqlModel.storage.fields;\n\n const storageParts = [\n `readonly table: ${serializeValue(tableName)}`,\n `readonly namespaceId: ${serializeValue(sqlModel.storage.namespaceId)}`,\n ];\n if (Object.keys(storageFields).length > 0) {\n const fieldParts: string[] = [];\n for (const [fieldName, field] of Object.entries(storageFields)) {\n fieldParts.push(\n `readonly ${serializeObjectKey(fieldName)}: { readonly column: ${serializeValue(field.column)} }`,\n );\n }\n storageParts.push(`readonly fields: { ${fieldParts.join('; ')} }`);\n }\n\n return `{ ${storageParts.join('; ')} }`;\n },\n\n resolveFieldTypeParams(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): Record<string, unknown> | undefined {\n const sqlModel = model as ContractModel<SqlModelStorage>;\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = contract.storage as unknown as SqlStorage | undefined;\n if (!storage) return undefined;\n\n const tableName = sqlModel.storage.table;\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: tableName,\n });\n if (!table) return undefined;\n\n const column = table.columns[storageField.column];\n if (!column) return undefined;\n\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n const codecShape = typeInstance as Partial<StorageTypeInstance>;\n return codecShape.typeParams;\n }\n return column.typeParams;\n },\n\n resolveFieldValueSet(\n _modelName: string,\n fieldName: string,\n model: ContractModelBase,\n contract: Contract,\n ): { readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefined {\n const sqlModel = blindCast<\n ContractModel<SqlModelStorage>,\n 'a sql-family model carries SqlModelStorage in storage'\n >(model);\n const storageField = sqlModel.storage?.fields?.[fieldName];\n if (!storageField) return undefined;\n\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage) return undefined;\n\n const storageNamespaceId = sqlModel.storage.namespaceId;\n if (!storageNamespaceId) return undefined;\n\n const table = entityAt<StorageTable>(storage, {\n namespaceId: storageNamespaceId,\n entityKind: 'table',\n entityName: sqlModel.storage.table,\n });\n const column = table?.columns[storageField.column];\n if (!column?.valueSet) return undefined;\n\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n if (!valueSet) return undefined;\n\n return { encodedValues: valueSet.values, codecId: column.codecId };\n },\n\n getStorageTypeExports(contract: Contract, codecLookup?: CodecLookup): string | undefined {\n const storage = blindCast<\n SqlStorage | undefined,\n 'contract.storage is SqlStorage for sql family'\n >(contract.storage);\n if (!storage?.namespaces) return undefined;\n const outputMap = generateStorageColumnTypesMap(storage, 'output', codecLookup);\n const inputMap = generateStorageColumnTypesMap(storage, 'input', codecLookup);\n return [\n `export type StorageColumnTypes = ${outputMap};`,\n `export type StorageColumnInputTypes = ${inputMap};`,\n ].join('\\n');\n },\n\n getFamilyImports(): string[] {\n return [\n 'import type {',\n ' ContractWithTypeMaps,',\n ' TypeMaps as TypeMapsType,',\n \"} from '@prisma-next/sql-contract/types';\",\n ];\n },\n\n getFamilyTypeAliases(options?: GenerateContractTypesOptions): string {\n const queryOperationTypeImports = options?.queryOperationTypeImports ?? [];\n const queryOperationAliases = queryOperationTypeImports\n .filter((imp) => imp.named === 'QueryOperationTypes')\n .map((imp) => `${imp.alias}<CodecTypes>`);\n const queryOperationTypes =\n queryOperationAliases.length > 0\n ? queryOperationAliases.join(' & ')\n : 'Record<string, never>';\n\n return [\n 'export type LaneCodecTypes = CodecTypes;',\n `export type QueryOperationTypes = ${queryOperationTypes};`,\n 'type DefaultLiteralValue<CodecId extends string, _Encoded> =',\n ' CodecId extends keyof CodecTypes',\n \" ? CodecTypes[CodecId]['output']\",\n ' : _Encoded;',\n ].join('\\n');\n },\n\n getTypeMapsExpression(): string {\n return 'TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes, StorageColumnTypes, StorageColumnInputTypes>';\n },\n\n getContractWrapper(contractBaseName: string, typeMapsName: string): string {\n return [\n `export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,\n '',\n \"export type Namespaces = Contract['storage']['namespaces'];\",\n ].join('\\n');\n },\n} as const;\n\ntype ColumnTypeSide = 'output' | 'input';\n\nfunction columnTypeParams(\n storage: SqlStorage,\n column: StorageColumn,\n): Record<string, unknown> | undefined {\n if (column.typeRef) {\n const typeInstance = storage.types?.[column.typeRef];\n if (typeInstance === undefined) return undefined;\n return blindCast<\n Partial<StorageTypeInstance>,\n 'storage.types entries are codec-instance triples carrying optional typeParams'\n >(typeInstance).typeParams;\n }\n return column.typeParams;\n}\n\nfunction renderRefinedCodecType(\n column: StorageColumn,\n side: ColumnTypeSide,\n params: Record<string, unknown> | undefined,\n codecLookup: CodecLookup | undefined,\n): string {\n if (codecLookup && params && Object.keys(params).length > 0) {\n const rendered =\n side === 'output'\n ? codecLookup.renderOutputTypeFor(column.codecId, params)\n : codecLookup.renderInputTypeFor?.(column.codecId, params);\n if (rendered && isSafeTypeExpression(rendered)) {\n return rendered;\n }\n }\n return `CodecTypes[${serializeValue(column.codecId)}][${serializeValue(side)}]`;\n}\n\nfunction computeColumnType(\n storage: SqlStorage,\n column: StorageColumn,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n let base: string | undefined;\n if (column.valueSet) {\n const valueSet = entityAt<StorageValueSet>(storage, {\n namespaceId: column.valueSet.namespaceId,\n entityKind: column.valueSet.entityKind,\n entityName: column.valueSet.entityName,\n });\n base = valueSet\n ? renderValueSetType(valueSet.values, column.codecId, side, codecLookup)\n : undefined;\n }\n if (base === undefined) {\n base = renderRefinedCodecType(column, side, columnTypeParams(storage, column), codecLookup);\n }\n if (column.many === true) base = `ReadonlyArray<${base}>`;\n return column.nullable ? `${base} | null` : base;\n}\n\nfunction generateStorageColumnTypesMap(\n storage: SqlStorage,\n side: ColumnTypeSide,\n codecLookup: CodecLookup | undefined,\n): string {\n const namespaceEntries = Object.entries(storage.namespaces ?? {}).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n if (namespaceEntries.length === 0) return 'Record<string, never>';\n\n const nsParts: string[] = [];\n for (const [nsId, ns] of namespaceEntries) {\n const tables = blindCast<\n Readonly<Record<string, StorageTable>>,\n 'same pattern as generateTablesMapType below'\n >(ns.entries.table ?? {});\n const tableEntries = Object.entries(tables).sort(([a], [b]) => a.localeCompare(b));\n const tableParts: string[] = [];\n\n for (const [tableName, table] of tableEntries) {\n const colEntries = Object.entries(table.columns).sort(([a], [b]) => a.localeCompare(b));\n const colParts: string[] = [];\n\n for (const [colName, col] of colEntries) {\n const colType = computeColumnType(storage, col, side, codecLookup);\n colParts.push(`readonly ${serializeObjectKey(colName)}: ${colType}`);\n }\n\n const colMap = colParts.length > 0 ? `{ ${colParts.join('; ')} }` : '{}';\n tableParts.push(`readonly ${serializeObjectKey(tableName)}: ${colMap}`);\n }\n\n const tableMap = tableParts.length > 0 ? `{ ${tableParts.join('; ')} }` : '{}';\n nsParts.push(`readonly ${serializeObjectKey(nsId)}: ${tableMap}`);\n }\n\n return `{ ${nsParts.join('; ')} }`;\n}\n\nfunction generateDocumentScopedStorageTypesType(types: SqlStorage['types']): string | undefined {\n if (!types || Object.keys(types).length === 0) {\n return undefined;\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n const codecInstanceShape = typeInstance as Partial<StorageTypeInstance>;\n if (\n typeof codecInstanceShape.codecId !== 'string' ||\n typeof codecInstanceShape.nativeType !== 'string'\n ) {\n throw new Error(\n `Unknown storage type kind for \"${typeName}\" in document-scoped storage.types; expected a codec-instance triple.`,\n );\n }\n const codecId = serializeValue(codecInstanceShape.codecId);\n const nativeType = serializeValue(codecInstanceShape.nativeType);\n const typeParamsStr = serializeTypeParamsLiteral(codecInstanceShape.typeParams);\n typeEntries.push(\n `readonly ${typeName}: { readonly kind: 'codec-instance'; readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,\n );\n }\n\n return `{ ${typeEntries.join('; ')} }`;\n}\n\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\nfunction namespaceSerializedKind(ns: Namespace): string {\n const kind = ns.kind;\n if (kind === 'schema') {\n const id = ns.id;\n const lit = id === UNBOUND_NAMESPACE_ID ? 'postgres-unbound-schema' : 'postgres-schema';\n return `readonly kind: '${lit}'`;\n }\n if (typeof kind === 'string') {\n return `readonly kind: ${serializeValue(kind)}`;\n }\n throw new Error(\n `Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`,\n );\n}\n\nfunction generateTableLiteralType(table: StorageTable): string {\n const columns: string[] = [];\n for (const [colName, col] of Object.entries(table.columns)) {\n const nullable = col.nullable ? 'true' : 'false';\n const nativeType = serializeValue(col.nativeType);\n const codecId = serializeValue(col.codecId);\n const defaultSpec = col.default\n ? col.default.kind === 'literal'\n ? `; readonly default: { readonly kind: 'literal'; readonly value: DefaultLiteralValue<${codecId}, ${serializeValue(\n col.default.value,\n )}> }`\n : `; readonly default: { readonly kind: 'function'; readonly expression: ${serializeValue(\n col.default.expression,\n )} }`\n : '';\n const typeParamsSpec =\n col.typeParams && Object.keys(col.typeParams).length > 0\n ? `; readonly typeParams: ${serializeTypeParamsLiteral(col.typeParams)}`\n : '';\n const typeRefSpec = col.typeRef ? `; readonly typeRef: ${serializeValue(col.typeRef)}` : '';\n columns.push(\n `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable}${defaultSpec}${typeParamsSpec}${typeRefSpec} }`,\n );\n }\n\n const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];\n\n if (table.primaryKey) {\n const pkCols = table.primaryKey.columns.map((c) => serializeValue(c)).join(', ');\n const 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.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.41",
|
|
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.14.0-dev.
|
|
10
|
-
"@prisma-next/emitter": "0.14.0-dev.
|
|
11
|
-
"@prisma-next/framework-components": "0.14.0-dev.
|
|
12
|
-
"@prisma-next/sql-contract": "0.14.0-dev.
|
|
13
|
-
"@prisma-next/utils": "0.14.0-dev.
|
|
9
|
+
"@prisma-next/contract": "0.14.0-dev.41",
|
|
10
|
+
"@prisma-next/emitter": "0.14.0-dev.41",
|
|
11
|
+
"@prisma-next/framework-components": "0.14.0-dev.41",
|
|
12
|
+
"@prisma-next/sql-contract": "0.14.0-dev.41",
|
|
13
|
+
"@prisma-next/utils": "0.14.0-dev.41"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@prisma-next/test-utils": "0.14.0-dev.
|
|
17
|
-
"@prisma-next/tsconfig": "0.14.0-dev.
|
|
18
|
-
"@prisma-next/tsdown": "0.14.0-dev.
|
|
16
|
+
"@prisma-next/test-utils": "0.14.0-dev.41",
|
|
17
|
+
"@prisma-next/tsconfig": "0.14.0-dev.41",
|
|
18
|
+
"@prisma-next/tsdown": "0.14.0-dev.41",
|
|
19
19
|
"tsdown": "0.22.1",
|
|
20
20
|
"typescript": "5.9.3",
|
|
21
21
|
"vitest": "4.1.8"
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Contract,
|
|
3
|
+
ContractModel,
|
|
4
|
+
ContractModelBase,
|
|
5
|
+
JsonValue,
|
|
6
|
+
} from '@prisma-next/contract/types';
|
|
2
7
|
import {
|
|
8
|
+
renderValueSetType,
|
|
3
9
|
serializeNamespaceId,
|
|
4
10
|
serializeObjectKey,
|
|
5
11
|
serializeValue,
|
|
6
12
|
} from '@prisma-next/emitter/domain-type-generation';
|
|
13
|
+
import { isSafeTypeExpression } from '@prisma-next/emitter/type-expression-safety';
|
|
14
|
+
import type { CodecLookup } from '@prisma-next/framework-components/codec';
|
|
7
15
|
import type {
|
|
8
16
|
GenerateContractTypesOptions,
|
|
9
17
|
ValidationContext,
|
|
@@ -16,10 +24,12 @@ import {
|
|
|
16
24
|
import type {
|
|
17
25
|
SqlModelStorage,
|
|
18
26
|
SqlStorage,
|
|
27
|
+
StorageColumn,
|
|
19
28
|
StorageTable,
|
|
20
29
|
StorageTypeInstance,
|
|
21
30
|
StorageValueSet,
|
|
22
31
|
} from '@prisma-next/sql-contract/types';
|
|
32
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
23
33
|
|
|
24
34
|
function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {
|
|
25
35
|
if (!params || Object.keys(params).length === 0) {
|
|
@@ -305,6 +315,60 @@ export const sqlEmission = {
|
|
|
305
315
|
return column.typeParams;
|
|
306
316
|
},
|
|
307
317
|
|
|
318
|
+
resolveFieldValueSet(
|
|
319
|
+
_modelName: string,
|
|
320
|
+
fieldName: string,
|
|
321
|
+
model: ContractModelBase,
|
|
322
|
+
contract: Contract,
|
|
323
|
+
): { readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefined {
|
|
324
|
+
const sqlModel = blindCast<
|
|
325
|
+
ContractModel<SqlModelStorage>,
|
|
326
|
+
'a sql-family model carries SqlModelStorage in storage'
|
|
327
|
+
>(model);
|
|
328
|
+
const storageField = sqlModel.storage?.fields?.[fieldName];
|
|
329
|
+
if (!storageField) return undefined;
|
|
330
|
+
|
|
331
|
+
const storage = blindCast<
|
|
332
|
+
SqlStorage | undefined,
|
|
333
|
+
'contract.storage is SqlStorage for sql family'
|
|
334
|
+
>(contract.storage);
|
|
335
|
+
if (!storage) return undefined;
|
|
336
|
+
|
|
337
|
+
const storageNamespaceId = sqlModel.storage.namespaceId;
|
|
338
|
+
if (!storageNamespaceId) return undefined;
|
|
339
|
+
|
|
340
|
+
const table = entityAt<StorageTable>(storage, {
|
|
341
|
+
namespaceId: storageNamespaceId,
|
|
342
|
+
entityKind: 'table',
|
|
343
|
+
entityName: sqlModel.storage.table,
|
|
344
|
+
});
|
|
345
|
+
const column = table?.columns[storageField.column];
|
|
346
|
+
if (!column?.valueSet) return undefined;
|
|
347
|
+
|
|
348
|
+
const valueSet = entityAt<StorageValueSet>(storage, {
|
|
349
|
+
namespaceId: column.valueSet.namespaceId,
|
|
350
|
+
entityKind: column.valueSet.entityKind,
|
|
351
|
+
entityName: column.valueSet.entityName,
|
|
352
|
+
});
|
|
353
|
+
if (!valueSet) return undefined;
|
|
354
|
+
|
|
355
|
+
return { encodedValues: valueSet.values, codecId: column.codecId };
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
getStorageTypeExports(contract: Contract, codecLookup?: CodecLookup): string | undefined {
|
|
359
|
+
const storage = blindCast<
|
|
360
|
+
SqlStorage | undefined,
|
|
361
|
+
'contract.storage is SqlStorage for sql family'
|
|
362
|
+
>(contract.storage);
|
|
363
|
+
if (!storage?.namespaces) return undefined;
|
|
364
|
+
const outputMap = generateStorageColumnTypesMap(storage, 'output', codecLookup);
|
|
365
|
+
const inputMap = generateStorageColumnTypesMap(storage, 'input', codecLookup);
|
|
366
|
+
return [
|
|
367
|
+
`export type StorageColumnTypes = ${outputMap};`,
|
|
368
|
+
`export type StorageColumnInputTypes = ${inputMap};`,
|
|
369
|
+
].join('\n');
|
|
370
|
+
},
|
|
371
|
+
|
|
308
372
|
getFamilyImports(): string[] {
|
|
309
373
|
return [
|
|
310
374
|
'import type {',
|
|
@@ -335,7 +399,7 @@ export const sqlEmission = {
|
|
|
335
399
|
},
|
|
336
400
|
|
|
337
401
|
getTypeMapsExpression(): string {
|
|
338
|
-
return 'TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes>';
|
|
402
|
+
return 'TypeMapsType<CodecTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes, StorageColumnTypes, StorageColumnInputTypes>';
|
|
339
403
|
},
|
|
340
404
|
|
|
341
405
|
getContractWrapper(contractBaseName: string, typeMapsName: string): string {
|
|
@@ -347,6 +411,104 @@ export const sqlEmission = {
|
|
|
347
411
|
},
|
|
348
412
|
} as const;
|
|
349
413
|
|
|
414
|
+
type ColumnTypeSide = 'output' | 'input';
|
|
415
|
+
|
|
416
|
+
function columnTypeParams(
|
|
417
|
+
storage: SqlStorage,
|
|
418
|
+
column: StorageColumn,
|
|
419
|
+
): Record<string, unknown> | undefined {
|
|
420
|
+
if (column.typeRef) {
|
|
421
|
+
const typeInstance = storage.types?.[column.typeRef];
|
|
422
|
+
if (typeInstance === undefined) return undefined;
|
|
423
|
+
return blindCast<
|
|
424
|
+
Partial<StorageTypeInstance>,
|
|
425
|
+
'storage.types entries are codec-instance triples carrying optional typeParams'
|
|
426
|
+
>(typeInstance).typeParams;
|
|
427
|
+
}
|
|
428
|
+
return column.typeParams;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function renderRefinedCodecType(
|
|
432
|
+
column: StorageColumn,
|
|
433
|
+
side: ColumnTypeSide,
|
|
434
|
+
params: Record<string, unknown> | undefined,
|
|
435
|
+
codecLookup: CodecLookup | undefined,
|
|
436
|
+
): string {
|
|
437
|
+
if (codecLookup && params && Object.keys(params).length > 0) {
|
|
438
|
+
const rendered =
|
|
439
|
+
side === 'output'
|
|
440
|
+
? codecLookup.renderOutputTypeFor(column.codecId, params)
|
|
441
|
+
: codecLookup.renderInputTypeFor?.(column.codecId, params);
|
|
442
|
+
if (rendered && isSafeTypeExpression(rendered)) {
|
|
443
|
+
return rendered;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return `CodecTypes[${serializeValue(column.codecId)}][${serializeValue(side)}]`;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function computeColumnType(
|
|
450
|
+
storage: SqlStorage,
|
|
451
|
+
column: StorageColumn,
|
|
452
|
+
side: ColumnTypeSide,
|
|
453
|
+
codecLookup: CodecLookup | undefined,
|
|
454
|
+
): string {
|
|
455
|
+
let base: string | undefined;
|
|
456
|
+
if (column.valueSet) {
|
|
457
|
+
const valueSet = entityAt<StorageValueSet>(storage, {
|
|
458
|
+
namespaceId: column.valueSet.namespaceId,
|
|
459
|
+
entityKind: column.valueSet.entityKind,
|
|
460
|
+
entityName: column.valueSet.entityName,
|
|
461
|
+
});
|
|
462
|
+
base = valueSet
|
|
463
|
+
? renderValueSetType(valueSet.values, column.codecId, side, codecLookup)
|
|
464
|
+
: undefined;
|
|
465
|
+
}
|
|
466
|
+
if (base === undefined) {
|
|
467
|
+
base = renderRefinedCodecType(column, side, columnTypeParams(storage, column), codecLookup);
|
|
468
|
+
}
|
|
469
|
+
if (column.many === true) base = `ReadonlyArray<${base}>`;
|
|
470
|
+
return column.nullable ? `${base} | null` : base;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function generateStorageColumnTypesMap(
|
|
474
|
+
storage: SqlStorage,
|
|
475
|
+
side: ColumnTypeSide,
|
|
476
|
+
codecLookup: CodecLookup | undefined,
|
|
477
|
+
): string {
|
|
478
|
+
const namespaceEntries = Object.entries(storage.namespaces ?? {}).sort(([a], [b]) =>
|
|
479
|
+
a.localeCompare(b),
|
|
480
|
+
);
|
|
481
|
+
if (namespaceEntries.length === 0) return 'Record<string, never>';
|
|
482
|
+
|
|
483
|
+
const nsParts: string[] = [];
|
|
484
|
+
for (const [nsId, ns] of namespaceEntries) {
|
|
485
|
+
const tables = blindCast<
|
|
486
|
+
Readonly<Record<string, StorageTable>>,
|
|
487
|
+
'same pattern as generateTablesMapType below'
|
|
488
|
+
>(ns.entries.table ?? {});
|
|
489
|
+
const tableEntries = Object.entries(tables).sort(([a], [b]) => a.localeCompare(b));
|
|
490
|
+
const tableParts: string[] = [];
|
|
491
|
+
|
|
492
|
+
for (const [tableName, table] of tableEntries) {
|
|
493
|
+
const colEntries = Object.entries(table.columns).sort(([a], [b]) => a.localeCompare(b));
|
|
494
|
+
const colParts: string[] = [];
|
|
495
|
+
|
|
496
|
+
for (const [colName, col] of colEntries) {
|
|
497
|
+
const colType = computeColumnType(storage, col, side, codecLookup);
|
|
498
|
+
colParts.push(`readonly ${serializeObjectKey(colName)}: ${colType}`);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const colMap = colParts.length > 0 ? `{ ${colParts.join('; ')} }` : '{}';
|
|
502
|
+
tableParts.push(`readonly ${serializeObjectKey(tableName)}: ${colMap}`);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const tableMap = tableParts.length > 0 ? `{ ${tableParts.join('; ')} }` : '{}';
|
|
506
|
+
nsParts.push(`readonly ${serializeObjectKey(nsId)}: ${tableMap}`);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return `{ ${nsParts.join('; ')} }`;
|
|
510
|
+
}
|
|
511
|
+
|
|
350
512
|
function generateDocumentScopedStorageTypesType(types: SqlStorage['types']): string | undefined {
|
|
351
513
|
if (!types || Object.keys(types).length === 0) {
|
|
352
514
|
return undefined;
|
|
@@ -390,8 +552,6 @@ function generateNamespaceValueSetType(
|
|
|
390
552
|
return `{ ${entries.join('; ')} }`;
|
|
391
553
|
}
|
|
392
554
|
|
|
393
|
-
const SQL_NAMESPACE_KIND_FALLBACK = 'sql-namespace' as const;
|
|
394
|
-
|
|
395
555
|
function namespaceSerializedKind(ns: Namespace): string {
|
|
396
556
|
const kind = ns.kind;
|
|
397
557
|
if (kind === 'schema') {
|
|
@@ -402,12 +562,9 @@ function namespaceSerializedKind(ns: Namespace): string {
|
|
|
402
562
|
if (typeof kind === 'string') {
|
|
403
563
|
return `readonly kind: ${serializeValue(kind)}`;
|
|
404
564
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
// framework-default kind here keeps the emitted `.d.ts` literal
|
|
409
|
-
// structurally assignable to `Namespace`, which now requires `kind`.
|
|
410
|
-
return `readonly kind: '${SQL_NAMESPACE_KIND_FALLBACK}'`;
|
|
565
|
+
throw new Error(
|
|
566
|
+
`Namespace '${ns.id}' has no string kind — all namespaces must be target concretions with a defined kind property.`,
|
|
567
|
+
);
|
|
411
568
|
}
|
|
412
569
|
|
|
413
570
|
function generateTableLiteralType(table: StorageTable): string {
|