@prisma-next/sql-contract-ts 0.11.0-dev.9 → 0.12.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/build-contract-BCYW3_wE.mjs +385 -0
- package/dist/build-contract-BCYW3_wE.mjs.map +1 -0
- package/dist/config-types.d.mts +6 -1
- package/dist/config-types.d.mts.map +1 -1
- package/dist/config-types.mjs +11 -1
- package/dist/config-types.mjs.map +1 -1
- package/dist/contract-builder.d.mts +38 -28
- package/dist/contract-builder.d.mts.map +1 -1
- package/dist/contract-builder.mjs +6 -354
- package/dist/contract-builder.mjs.map +1 -1
- package/package.json +21 -10
- package/src/build-contract.ts +103 -31
- package/src/config-types.ts +14 -0
- package/src/contract-builder.ts +8 -19
- package/src/contract-definition.ts +0 -1
- package/src/contract-dsl.ts +0 -2
- package/src/contract-lowering.ts +0 -1
- package/src/contract-types.ts +61 -26
- package/src/exports/config-types.ts +5 -1
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { blindCast } from "@prisma-next/utils/casts";
|
|
2
|
+
import { computeExecutionHash, computeProfileHash, computeStorageHash } from "@prisma-next/contract/hashing";
|
|
3
|
+
import { asNamespaceId, coreHash, crossRef } from "@prisma-next/contract/types";
|
|
4
|
+
import { mergeCapabilityMatrices } from "@prisma-next/contract-authoring";
|
|
5
|
+
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
6
|
+
import { sqlContractCanonicalizationHooks } from "@prisma-next/sql-contract/canonicalization-hooks";
|
|
7
|
+
import { validateIndexTypes } from "@prisma-next/sql-contract/index-type-validation";
|
|
8
|
+
import { createIndexTypeRegistry } from "@prisma-next/sql-contract/index-types";
|
|
9
|
+
import { SqlStorage, StorageTable, applyFkDefaults, buildSqlNamespace, isPostgresEnumStorageEntry, toStorageTypeInstance } from "@prisma-next/sql-contract/types";
|
|
10
|
+
import { validateStorageSemantics } from "@prisma-next/sql-contract/validators";
|
|
11
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
12
|
+
//#region src/build-contract.ts
|
|
13
|
+
function encodeDefaultLiteralValue(value, codecId, codecLookup) {
|
|
14
|
+
const codec = codecLookup?.get(codecId);
|
|
15
|
+
if (codec) return codec.encodeJson(value);
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
function encodeColumnDefault(defaultInput, codecId, codecLookup) {
|
|
19
|
+
if (defaultInput.kind === "function") return {
|
|
20
|
+
kind: "function",
|
|
21
|
+
expression: defaultInput.expression
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
kind: "literal",
|
|
25
|
+
value: encodeDefaultLiteralValue(defaultInput.value, codecId, codecLookup)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function assertStorageSemantics(definition, contract) {
|
|
29
|
+
const semanticErrors = validateStorageSemantics(contract.storage);
|
|
30
|
+
if (semanticErrors.length > 0) throw new Error(`Contract semantic validation failed: ${semanticErrors.join("; ")}`);
|
|
31
|
+
const indexTypeRegistry = createIndexTypeRegistry();
|
|
32
|
+
const packsToRegister = [definition.target, ...Object.values(definition.extensionPacks ?? {})];
|
|
33
|
+
for (const pack of packsToRegister) {
|
|
34
|
+
const registration = pack.indexTypes;
|
|
35
|
+
if (registration === void 0) continue;
|
|
36
|
+
if (typeof registration !== "object" || registration === null || !Array.isArray(registration.entries)) throw new Error(`Pack "${pack.id ?? "<unknown>"}" declares "indexTypes" but its value is not an IndexTypeRegistration (expected an object with an "entries" array; got ${typeof registration}).`);
|
|
37
|
+
for (const entry of registration.entries) indexTypeRegistry.register(entry);
|
|
38
|
+
}
|
|
39
|
+
validateIndexTypes(contract, indexTypeRegistry);
|
|
40
|
+
}
|
|
41
|
+
function assertKnownTargetModel(modelsByName, sourceModelName, targetModelName, context) {
|
|
42
|
+
const targetModel = modelsByName.get(targetModelName);
|
|
43
|
+
if (!targetModel) throw new Error(`${context} on model "${sourceModelName}" references unknown model "${targetModelName}"`);
|
|
44
|
+
return targetModel;
|
|
45
|
+
}
|
|
46
|
+
function assertTargetTableMatches(sourceModelName, targetModel, referencedTableName, context) {
|
|
47
|
+
if (targetModel.tableName !== referencedTableName) throw new Error(`${context} on model "${sourceModelName}" references table "${referencedTableName}" but model "${targetModel.modelName}" maps to "${targetModel.tableName}"`);
|
|
48
|
+
}
|
|
49
|
+
function isValueObjectField(field) {
|
|
50
|
+
return "valueObjectName" in field;
|
|
51
|
+
}
|
|
52
|
+
const JSONB_CODEC_ID = "pg/jsonb@1";
|
|
53
|
+
const JSONB_NATIVE_TYPE = "jsonb";
|
|
54
|
+
function resolveModelNamespaceId(model, modelNameToNamespaceId, targetId) {
|
|
55
|
+
if (model.namespaceId !== void 0 && model.namespaceId.length > 0) return model.namespaceId;
|
|
56
|
+
return modelNameToNamespaceId.get(model.modelName) ?? defaultModelNamespaceId(targetId);
|
|
57
|
+
}
|
|
58
|
+
function buildStorageColumn(field, codecLookup) {
|
|
59
|
+
if (isValueObjectField(field)) {
|
|
60
|
+
const encodedDefault = field.default !== void 0 ? encodeColumnDefault(field.default, JSONB_CODEC_ID, codecLookup) : void 0;
|
|
61
|
+
return {
|
|
62
|
+
nativeType: JSONB_NATIVE_TYPE,
|
|
63
|
+
codecId: JSONB_CODEC_ID,
|
|
64
|
+
nullable: field.nullable,
|
|
65
|
+
...ifDefined("default", encodedDefault)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (field.many) return {
|
|
69
|
+
nativeType: JSONB_NATIVE_TYPE,
|
|
70
|
+
codecId: JSONB_CODEC_ID,
|
|
71
|
+
nullable: field.nullable
|
|
72
|
+
};
|
|
73
|
+
const codecId = field.descriptor.codecId;
|
|
74
|
+
const encodedDefault = field.default !== void 0 ? encodeColumnDefault(field.default, codecId, codecLookup) : void 0;
|
|
75
|
+
return {
|
|
76
|
+
nativeType: field.descriptor.nativeType,
|
|
77
|
+
codecId,
|
|
78
|
+
nullable: field.nullable,
|
|
79
|
+
...ifDefined("typeParams", field.descriptor.typeParams),
|
|
80
|
+
...ifDefined("default", encodedDefault),
|
|
81
|
+
...ifDefined("typeRef", field.descriptor.typeRef)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function buildDomainField(field, column) {
|
|
85
|
+
if (isValueObjectField(field)) return {
|
|
86
|
+
type: {
|
|
87
|
+
kind: "valueObject",
|
|
88
|
+
name: field.valueObjectName
|
|
89
|
+
},
|
|
90
|
+
nullable: field.nullable,
|
|
91
|
+
...field.many ? { many: true } : {}
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
type: {
|
|
95
|
+
kind: "scalar",
|
|
96
|
+
codecId: column.codecId,
|
|
97
|
+
...ifDefined("typeParams", column.typeParams)
|
|
98
|
+
},
|
|
99
|
+
nullable: column.nullable,
|
|
100
|
+
...field.many ? { many: true } : {}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function collectStorageNamespaceCoordinateIds(definition) {
|
|
104
|
+
const ids = /* @__PURE__ */ new Set();
|
|
105
|
+
ids.add(defaultModelNamespaceId(definition.target.targetId));
|
|
106
|
+
for (const id of definition.namespaces ?? []) if (id.length > 0) ids.add(id);
|
|
107
|
+
for (const model of definition.models) if (model.namespaceId !== void 0 && model.namespaceId.length > 0) ids.add(model.namespaceId);
|
|
108
|
+
return ids;
|
|
109
|
+
}
|
|
110
|
+
const POSTGRES_ENUM_NAMESPACE_ID = "public";
|
|
111
|
+
const POSTGRES_DEFAULT_NAMESPACE_ID = "public";
|
|
112
|
+
function defaultModelNamespaceId(targetId) {
|
|
113
|
+
return targetId === "postgres" ? POSTGRES_DEFAULT_NAMESPACE_ID : UNBOUND_NAMESPACE_ID;
|
|
114
|
+
}
|
|
115
|
+
function partitionStorageTypesForTarget(targetId, types, namespaceTypes) {
|
|
116
|
+
const documentTypes = {};
|
|
117
|
+
const namespaceEnumTypesById = {};
|
|
118
|
+
for (const [name, entry] of Object.entries(types)) {
|
|
119
|
+
if (isPostgresEnumStorageEntry(entry)) {
|
|
120
|
+
if (targetId !== "postgres") throw new Error(`buildSqlContractFromDefinition: postgres enum "${name}" is only valid when target is "postgres" (got "${targetId}").`);
|
|
121
|
+
let slot = namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID];
|
|
122
|
+
if (slot === void 0) {
|
|
123
|
+
slot = {};
|
|
124
|
+
namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID] = slot;
|
|
125
|
+
}
|
|
126
|
+
slot[name] = entry;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
documentTypes[name] = entry;
|
|
130
|
+
}
|
|
131
|
+
if (namespaceTypes !== void 0) for (const [nsId, enumsInNs] of Object.entries(namespaceTypes)) for (const [name, entry] of Object.entries(enumsInNs)) {
|
|
132
|
+
if (targetId !== "postgres") throw new Error(`buildSqlContractFromDefinition: postgres enum "${name}" is only valid when target is "postgres" (got "${targetId}").`);
|
|
133
|
+
let slot = namespaceEnumTypesById[nsId];
|
|
134
|
+
if (slot === void 0) {
|
|
135
|
+
slot = {};
|
|
136
|
+
namespaceEnumTypesById[nsId] = slot;
|
|
137
|
+
}
|
|
138
|
+
slot[name] = entry;
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
documentTypes,
|
|
142
|
+
namespaceEnumTypesById
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
146
|
+
const target = definition.target.targetId;
|
|
147
|
+
const targetFamily = "sql";
|
|
148
|
+
const modelsByName = new Map(definition.models.map((m) => [m.modelName, m]));
|
|
149
|
+
const tablesByNamespace = {};
|
|
150
|
+
const tableNameToNamespaceId = /* @__PURE__ */ new Map();
|
|
151
|
+
const modelNameToNamespaceId = /* @__PURE__ */ new Map();
|
|
152
|
+
const executionDefaults = [];
|
|
153
|
+
const modelsByNamespace = {};
|
|
154
|
+
const roots = {};
|
|
155
|
+
for (const semanticModel of definition.models) {
|
|
156
|
+
const tableName = semanticModel.tableName;
|
|
157
|
+
const namespaceId = semanticModel.namespaceId !== void 0 && semanticModel.namespaceId.length > 0 ? semanticModel.namespaceId : defaultModelNamespaceId(target);
|
|
158
|
+
modelNameToNamespaceId.set(semanticModel.modelName, namespaceId);
|
|
159
|
+
roots[tableName] = crossRef(semanticModel.modelName, namespaceId);
|
|
160
|
+
const columns = {};
|
|
161
|
+
const fieldToColumn = {};
|
|
162
|
+
const domainFields = {};
|
|
163
|
+
const domainFieldRefs = {};
|
|
164
|
+
for (const field of semanticModel.fields) {
|
|
165
|
+
const executionDefaultPhases = field.executionDefaults?.onCreate || field.executionDefaults?.onUpdate ? field.executionDefaults : void 0;
|
|
166
|
+
if (executionDefaultPhases) {
|
|
167
|
+
if (field.default !== void 0) throw new Error(`Field "${semanticModel.modelName}.${field.fieldName}" cannot define both default and executionDefaults.`);
|
|
168
|
+
if (field.nullable) throw new Error(`Field "${semanticModel.modelName}.${field.fieldName}" cannot be nullable when executionDefaults are present.`);
|
|
169
|
+
}
|
|
170
|
+
const column = buildStorageColumn(field, codecLookup);
|
|
171
|
+
columns[field.columnName] = column;
|
|
172
|
+
fieldToColumn[field.fieldName] = field.columnName;
|
|
173
|
+
domainFields[field.fieldName] = buildDomainField(field, column);
|
|
174
|
+
if (isValueObjectField(field)) domainFieldRefs[field.fieldName] = {
|
|
175
|
+
kind: "valueObject",
|
|
176
|
+
name: field.valueObjectName,
|
|
177
|
+
...field.many ? { many: true } : {}
|
|
178
|
+
};
|
|
179
|
+
else if (field.many) domainFieldRefs[field.fieldName] = {
|
|
180
|
+
kind: "scalar",
|
|
181
|
+
many: true
|
|
182
|
+
};
|
|
183
|
+
if (executionDefaultPhases) executionDefaults.push({
|
|
184
|
+
ref: {
|
|
185
|
+
table: tableName,
|
|
186
|
+
column: field.columnName
|
|
187
|
+
},
|
|
188
|
+
...ifDefined("onCreate", executionDefaultPhases.onCreate),
|
|
189
|
+
...ifDefined("onUpdate", executionDefaultPhases.onUpdate)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const foreignKeys = (semanticModel.foreignKeys ?? []).map((fk) => {
|
|
193
|
+
const targetModel = assertKnownTargetModel(modelsByName, semanticModel.modelName, fk.references.model, "Foreign key");
|
|
194
|
+
assertTargetTableMatches(semanticModel.modelName, targetModel, fk.references.table, "Foreign key");
|
|
195
|
+
const targetNamespaceId = fk.references.namespaceId ?? (targetModel.namespaceId !== void 0 && targetModel.namespaceId.length > 0 ? targetModel.namespaceId : defaultModelNamespaceId(target));
|
|
196
|
+
return {
|
|
197
|
+
source: {
|
|
198
|
+
namespaceId: asNamespaceId(namespaceId),
|
|
199
|
+
tableName,
|
|
200
|
+
columns: fk.columns
|
|
201
|
+
},
|
|
202
|
+
target: {
|
|
203
|
+
namespaceId: asNamespaceId(targetNamespaceId),
|
|
204
|
+
tableName: fk.references.table,
|
|
205
|
+
columns: fk.references.columns
|
|
206
|
+
},
|
|
207
|
+
...applyFkDefaults({
|
|
208
|
+
...ifDefined("constraint", fk.constraint),
|
|
209
|
+
...ifDefined("index", fk.index)
|
|
210
|
+
}, definition.foreignKeyDefaults),
|
|
211
|
+
...ifDefined("name", fk.name),
|
|
212
|
+
...ifDefined("onDelete", fk.onDelete),
|
|
213
|
+
...ifDefined("onUpdate", fk.onUpdate)
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
const existingNs = tableNameToNamespaceId.get(tableName);
|
|
217
|
+
if (existingNs !== void 0 && existingNs !== namespaceId) throw new Error(`buildSqlContractFromDefinition: table "${tableName}" is mapped in namespace "${namespaceId}" but already exists in namespace "${existingNs}".`);
|
|
218
|
+
tableNameToNamespaceId.set(tableName, namespaceId);
|
|
219
|
+
const tableInput = {
|
|
220
|
+
columns,
|
|
221
|
+
uniques: (semanticModel.uniques ?? []).map((u) => ({
|
|
222
|
+
columns: u.columns,
|
|
223
|
+
...ifDefined("name", u.name)
|
|
224
|
+
})),
|
|
225
|
+
indexes: (semanticModel.indexes ?? []).map((i) => ({
|
|
226
|
+
columns: i.columns,
|
|
227
|
+
...ifDefined("name", i.name),
|
|
228
|
+
...ifDefined("type", i.type),
|
|
229
|
+
...ifDefined("options", i.options)
|
|
230
|
+
})),
|
|
231
|
+
foreignKeys,
|
|
232
|
+
...semanticModel.id ? { primaryKey: {
|
|
233
|
+
columns: semanticModel.id.columns,
|
|
234
|
+
...ifDefined("name", semanticModel.id.name)
|
|
235
|
+
} } : {}
|
|
236
|
+
};
|
|
237
|
+
let nsTables = tablesByNamespace[namespaceId];
|
|
238
|
+
if (nsTables === void 0) {
|
|
239
|
+
nsTables = {};
|
|
240
|
+
tablesByNamespace[namespaceId] = nsTables;
|
|
241
|
+
}
|
|
242
|
+
if (nsTables[tableName] !== void 0) throw new Error(`buildSqlContractFromDefinition: duplicate table "${tableName}" in namespace "${namespaceId}".`);
|
|
243
|
+
nsTables[tableName] = new StorageTable(tableInput);
|
|
244
|
+
const storageFields = {};
|
|
245
|
+
for (const [fieldName, columnName] of Object.entries(fieldToColumn)) storageFields[fieldName] = { column: columnName };
|
|
246
|
+
const columnToField = new Map(Object.entries(fieldToColumn).map(([field, col]) => [col, field]));
|
|
247
|
+
const modelRelations = {};
|
|
248
|
+
for (const relation of semanticModel.relations ?? []) {
|
|
249
|
+
const targetModel = assertKnownTargetModel(modelsByName, semanticModel.modelName, relation.toModel, "Relation");
|
|
250
|
+
assertTargetTableMatches(semanticModel.modelName, targetModel, relation.toTable, "Relation");
|
|
251
|
+
if (relation.cardinality === "N:M" && !relation.through) throw new Error(`Relation "${semanticModel.modelName}.${relation.fieldName}" with cardinality "N:M" requires through metadata`);
|
|
252
|
+
const targetColumnToField = new Map(targetModel.fields.map((f) => [f.columnName, f.fieldName]));
|
|
253
|
+
modelRelations[relation.fieldName] = {
|
|
254
|
+
to: crossRef(relation.toModel, resolveModelNamespaceId(targetModel, modelNameToNamespaceId, target)),
|
|
255
|
+
cardinality: relation.cardinality,
|
|
256
|
+
on: {
|
|
257
|
+
localFields: relation.on.parentColumns.map((col) => columnToField.get(col) ?? col),
|
|
258
|
+
targetFields: relation.on.childColumns.map((col) => targetColumnToField.get(col) ?? col)
|
|
259
|
+
},
|
|
260
|
+
...relation.through ? { through: {
|
|
261
|
+
table: relation.through.table,
|
|
262
|
+
parentCols: relation.through.parentColumns,
|
|
263
|
+
childCols: relation.through.childColumns
|
|
264
|
+
} } : void 0
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
let namespaceModels = modelsByNamespace[namespaceId];
|
|
268
|
+
if (namespaceModels === void 0) {
|
|
269
|
+
namespaceModels = {};
|
|
270
|
+
modelsByNamespace[namespaceId] = namespaceModels;
|
|
271
|
+
}
|
|
272
|
+
namespaceModels[semanticModel.modelName] = {
|
|
273
|
+
storage: {
|
|
274
|
+
table: tableName,
|
|
275
|
+
fields: storageFields
|
|
276
|
+
},
|
|
277
|
+
fields: domainFields,
|
|
278
|
+
relations: modelRelations
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const rawStorageTypes = definition.storageTypes ?? {};
|
|
282
|
+
const { documentTypes, namespaceEnumTypesById } = partitionStorageTypesForTarget(target, Object.fromEntries(Object.entries(rawStorageTypes).map(([name, entry]) => {
|
|
283
|
+
if (isPostgresEnumStorageEntry(entry)) return [name, entry];
|
|
284
|
+
if (entry.kind === "codec-instance") return [name, entry];
|
|
285
|
+
return [name, toStorageTypeInstance({
|
|
286
|
+
codecId: entry.codecId,
|
|
287
|
+
nativeType: entry.nativeType,
|
|
288
|
+
typeParams: entry.typeParams ?? {}
|
|
289
|
+
})];
|
|
290
|
+
})), definition.namespaceTypes);
|
|
291
|
+
const namespaceCoordinateIds = collectStorageNamespaceCoordinateIds(definition);
|
|
292
|
+
for (const id of Object.keys(namespaceEnumTypesById)) namespaceCoordinateIds.add(id);
|
|
293
|
+
const { createNamespace } = definition;
|
|
294
|
+
const namespaces = blindCast(Object.fromEntries([...namespaceCoordinateIds].sort().map((id) => {
|
|
295
|
+
const enumTypes = namespaceEnumTypesById[id];
|
|
296
|
+
const nsInput = {
|
|
297
|
+
id,
|
|
298
|
+
tables: tablesByNamespace[id] ?? {},
|
|
299
|
+
...ifDefined("enum", enumTypes)
|
|
300
|
+
};
|
|
301
|
+
return [id, createNamespace ? createNamespace(nsInput) : buildSqlNamespace(nsInput)];
|
|
302
|
+
})));
|
|
303
|
+
const storageWithoutHash = {
|
|
304
|
+
...Object.keys(documentTypes).length > 0 ? { types: documentTypes } : {},
|
|
305
|
+
namespaces
|
|
306
|
+
};
|
|
307
|
+
const storageHash = definition.storageHash ? coreHash(definition.storageHash) : computeStorageHash({
|
|
308
|
+
target,
|
|
309
|
+
targetFamily,
|
|
310
|
+
storage: storageWithoutHash,
|
|
311
|
+
...sqlContractCanonicalizationHooks
|
|
312
|
+
});
|
|
313
|
+
const storage = new SqlStorage({
|
|
314
|
+
...storageWithoutHash,
|
|
315
|
+
storageHash
|
|
316
|
+
});
|
|
317
|
+
const executionSection = executionDefaults.length > 0 ? { mutations: { defaults: executionDefaults.sort((a, b) => {
|
|
318
|
+
const tableCompare = a.ref.table.localeCompare(b.ref.table);
|
|
319
|
+
if (tableCompare !== 0) return tableCompare;
|
|
320
|
+
return a.ref.column.localeCompare(b.ref.column);
|
|
321
|
+
}) } } : void 0;
|
|
322
|
+
const extensionNamespaces = definition.extensionPacks ? Object.values(definition.extensionPacks).map((pack) => pack.id) : void 0;
|
|
323
|
+
const extensionPacks = { ...definition.extensionPacks || {} };
|
|
324
|
+
if (extensionNamespaces) {
|
|
325
|
+
for (const namespace of extensionNamespaces) if (!Object.hasOwn(extensionPacks, namespace)) extensionPacks[namespace] = {};
|
|
326
|
+
}
|
|
327
|
+
const extensionPackCapabilitySources = definition.extensionPacks ? Object.values(definition.extensionPacks).map((pack) => pack.capabilities) : [];
|
|
328
|
+
const capabilities = mergeCapabilityMatrices(definition.target.capabilities, ...extensionPackCapabilitySources);
|
|
329
|
+
const profileHash = computeProfileHash({
|
|
330
|
+
target,
|
|
331
|
+
targetFamily,
|
|
332
|
+
capabilities: {}
|
|
333
|
+
});
|
|
334
|
+
const executionWithHash = executionSection ? {
|
|
335
|
+
...executionSection,
|
|
336
|
+
executionHash: computeExecutionHash({
|
|
337
|
+
target,
|
|
338
|
+
targetFamily,
|
|
339
|
+
execution: executionSection
|
|
340
|
+
})
|
|
341
|
+
} : void 0;
|
|
342
|
+
const valueObjects = definition.valueObjects && definition.valueObjects.length > 0 ? Object.fromEntries(definition.valueObjects.map((vo) => [vo.name, { fields: Object.fromEntries(vo.fields.map((f) => [f.fieldName, isValueObjectField(f) ? {
|
|
343
|
+
type: {
|
|
344
|
+
kind: "valueObject",
|
|
345
|
+
name: f.valueObjectName
|
|
346
|
+
},
|
|
347
|
+
nullable: f.nullable,
|
|
348
|
+
...f.many ? { many: true } : {}
|
|
349
|
+
} : {
|
|
350
|
+
type: {
|
|
351
|
+
kind: "scalar",
|
|
352
|
+
codecId: f.descriptor.codecId,
|
|
353
|
+
...ifDefined("typeParams", f.descriptor.typeParams)
|
|
354
|
+
},
|
|
355
|
+
nullable: f.nullable
|
|
356
|
+
}])) }])) : void 0;
|
|
357
|
+
const defaultNamespaceId = defaultModelNamespaceId(target);
|
|
358
|
+
const domainNamespaceIds = new Set(Object.keys(modelsByNamespace));
|
|
359
|
+
if (domainNamespaceIds.size === 0) domainNamespaceIds.add(defaultNamespaceId);
|
|
360
|
+
if (valueObjects !== void 0) domainNamespaceIds.add(defaultNamespaceId);
|
|
361
|
+
const contract = {
|
|
362
|
+
target,
|
|
363
|
+
targetFamily,
|
|
364
|
+
domain: { namespaces: Object.fromEntries([...domainNamespaceIds].sort().map((namespaceId) => {
|
|
365
|
+
const modelsInNs = modelsByNamespace[namespaceId] ?? {};
|
|
366
|
+
return [namespaceId, namespaceId === defaultNamespaceId && valueObjects !== void 0 ? {
|
|
367
|
+
models: modelsInNs,
|
|
368
|
+
valueObjects
|
|
369
|
+
} : { models: modelsInNs }];
|
|
370
|
+
})) },
|
|
371
|
+
roots,
|
|
372
|
+
storage,
|
|
373
|
+
...executionWithHash ? { execution: executionWithHash } : {},
|
|
374
|
+
extensionPacks,
|
|
375
|
+
capabilities,
|
|
376
|
+
profileHash,
|
|
377
|
+
meta: {}
|
|
378
|
+
};
|
|
379
|
+
assertStorageSemantics(definition, contract);
|
|
380
|
+
return contract;
|
|
381
|
+
}
|
|
382
|
+
//#endregion
|
|
383
|
+
export { buildSqlContractFromDefinition as t };
|
|
384
|
+
|
|
385
|
+
//# sourceMappingURL=build-contract-BCYW3_wE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-contract-BCYW3_wE.mjs","names":[],"sources":["../src/build-contract.ts"],"sourcesContent":["import {\n computeExecutionHash,\n computeProfileHash,\n computeStorageHash,\n} from '@prisma-next/contract/hashing';\nimport {\n asNamespaceId,\n type ColumnDefault,\n type ColumnDefaultLiteralInputValue,\n type Contract,\n type ContractField,\n type ContractModel,\n type ContractRelation,\n type ContractValueObject,\n type CrossReference,\n coreHash,\n crossRef,\n type ExecutionMutationDefault,\n type JsonValue,\n type StorageHashBase,\n} from '@prisma-next/contract/types';\nimport { type CapabilityMatrix, mergeCapabilityMatrices } from '@prisma-next/contract-authoring';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { sqlContractCanonicalizationHooks } from '@prisma-next/sql-contract/canonicalization-hooks';\nimport { validateIndexTypes } from '@prisma-next/sql-contract/index-type-validation';\nimport {\n createIndexTypeRegistry,\n type IndexTypeMap,\n type IndexTypeRegistration,\n} from '@prisma-next/sql-contract/index-types';\nimport {\n applyFkDefaults,\n buildSqlNamespace,\n isPostgresEnumStorageEntry,\n type PostgresEnumStorageEntry,\n type SqlNamespaceTablesInput,\n SqlStorage,\n type SqlStorageInput,\n type StorageColumn,\n StorageTable,\n type StorageTableInput,\n type StorageTypeInstance,\n toStorageTypeInstance,\n} from '@prisma-next/sql-contract/types';\nimport { validateStorageSemantics } from '@prisma-next/sql-contract/validators';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type {\n ContractDefinition,\n FieldNode,\n ModelNode,\n ValueObjectFieldNode,\n} from './contract-definition';\n\ntype DomainFieldRef =\n | { readonly kind: 'scalar'; readonly many?: boolean }\n | { readonly kind: 'valueObject'; readonly name: string; readonly many?: boolean };\n\nfunction encodeDefaultLiteralValue(\n value: ColumnDefaultLiteralInputValue,\n codecId: string,\n codecLookup?: CodecLookup,\n): JsonValue {\n const codec = codecLookup?.get(codecId);\n if (codec) {\n return codec.encodeJson(value);\n }\n return value as JsonValue;\n}\n\nfunction encodeColumnDefault(\n defaultInput: ColumnDefault,\n codecId: string,\n codecLookup?: CodecLookup,\n): ColumnDefault {\n if (defaultInput.kind === 'function') {\n return { kind: 'function', expression: defaultInput.expression };\n }\n return {\n kind: 'literal',\n value: encodeDefaultLiteralValue(defaultInput.value, codecId, codecLookup),\n };\n}\n\nfunction assertStorageSemantics(\n definition: ContractDefinition,\n contract: Contract<SqlStorage>,\n): void {\n const semanticErrors = validateStorageSemantics(contract.storage);\n if (semanticErrors.length > 0) {\n throw new Error(`Contract semantic validation failed: ${semanticErrors.join('; ')}`);\n }\n\n const indexTypeRegistry = createIndexTypeRegistry();\n const packsToRegister: ReadonlyArray<{ readonly id?: string; readonly indexTypes?: unknown }> = [\n definition.target,\n ...Object.values(definition.extensionPacks ?? {}),\n ];\n for (const pack of packsToRegister) {\n const registration = pack.indexTypes;\n if (registration === undefined) continue;\n if (\n typeof registration !== 'object' ||\n registration === null ||\n !Array.isArray((registration as { entries?: unknown }).entries)\n ) {\n throw new Error(\n `Pack \"${pack.id ?? '<unknown>'}\" declares \"indexTypes\" but its value is not an IndexTypeRegistration (expected an object with an \"entries\" array; got ${typeof registration}).`,\n );\n }\n for (const entry of (registration as IndexTypeRegistration<IndexTypeMap>).entries) {\n indexTypeRegistry.register(entry);\n }\n }\n validateIndexTypes(contract, indexTypeRegistry);\n}\n\nfunction assertKnownTargetModel(\n modelsByName: ReadonlyMap<string, ModelNode>,\n sourceModelName: string,\n targetModelName: string,\n context: string,\n): ModelNode {\n const targetModel = modelsByName.get(targetModelName);\n if (!targetModel) {\n throw new Error(\n `${context} on model \"${sourceModelName}\" references unknown model \"${targetModelName}\"`,\n );\n }\n return targetModel;\n}\n\nfunction assertTargetTableMatches(\n sourceModelName: string,\n targetModel: ModelNode,\n referencedTableName: string,\n context: string,\n): void {\n if (targetModel.tableName !== referencedTableName) {\n throw new Error(\n `${context} on model \"${sourceModelName}\" references table \"${referencedTableName}\" but model \"${targetModel.modelName}\" maps to \"${targetModel.tableName}\"`,\n );\n }\n}\n\nfunction isValueObjectField(\n field: FieldNode | ValueObjectFieldNode,\n): field is ValueObjectFieldNode {\n return 'valueObjectName' in field;\n}\n\nconst JSONB_CODEC_ID = 'pg/jsonb@1';\nconst JSONB_NATIVE_TYPE = 'jsonb';\n\nfunction resolveModelNamespaceId(\n model: ModelNode,\n modelNameToNamespaceId: ReadonlyMap<string, string>,\n targetId: string,\n): string {\n if (model.namespaceId !== undefined && model.namespaceId.length > 0) {\n return model.namespaceId;\n }\n return modelNameToNamespaceId.get(model.modelName) ?? defaultModelNamespaceId(targetId);\n}\n\nfunction buildStorageColumn(\n field: FieldNode | ValueObjectFieldNode,\n codecLookup?: CodecLookup,\n): StorageColumn {\n if (isValueObjectField(field)) {\n const encodedDefault =\n field.default !== undefined\n ? encodeColumnDefault(field.default, JSONB_CODEC_ID, codecLookup)\n : undefined;\n\n return {\n nativeType: JSONB_NATIVE_TYPE,\n codecId: JSONB_CODEC_ID,\n nullable: field.nullable,\n ...ifDefined('default', encodedDefault),\n };\n }\n\n if (field.many) {\n return {\n nativeType: JSONB_NATIVE_TYPE,\n codecId: JSONB_CODEC_ID,\n nullable: field.nullable,\n };\n }\n\n const codecId = field.descriptor.codecId;\n const encodedDefault =\n field.default !== undefined\n ? encodeColumnDefault(field.default, codecId, codecLookup)\n : undefined;\n\n return {\n nativeType: field.descriptor.nativeType,\n codecId,\n nullable: field.nullable,\n ...ifDefined('typeParams', field.descriptor.typeParams),\n ...ifDefined('default', encodedDefault),\n ...ifDefined('typeRef', field.descriptor.typeRef),\n };\n}\n\nfunction buildDomainField(\n field: FieldNode | ValueObjectFieldNode,\n column: StorageColumn,\n): ContractField {\n if (isValueObjectField(field)) {\n return {\n type: { kind: 'valueObject', name: field.valueObjectName },\n nullable: field.nullable,\n ...(field.many ? { many: true } : {}),\n };\n }\n\n return {\n type: {\n kind: 'scalar',\n codecId: column.codecId,\n ...ifDefined('typeParams', column.typeParams),\n },\n nullable: column.nullable,\n ...(field.many ? { many: true } : {}),\n };\n}\n\nfunction collectStorageNamespaceCoordinateIds(definition: ContractDefinition): Set<string> {\n const ids = new Set<string>();\n ids.add(defaultModelNamespaceId(definition.target.targetId));\n for (const id of definition.namespaces ?? []) {\n if (id.length > 0) {\n ids.add(id);\n }\n }\n for (const model of definition.models) {\n if (model.namespaceId !== undefined && model.namespaceId.length > 0) {\n ids.add(model.namespaceId);\n }\n }\n return ids;\n}\n\nconst POSTGRES_ENUM_NAMESPACE_ID = 'public';\nconst POSTGRES_DEFAULT_NAMESPACE_ID = 'public';\n\nfunction defaultModelNamespaceId(targetId: string): string {\n return targetId === 'postgres' ? POSTGRES_DEFAULT_NAMESPACE_ID : UNBOUND_NAMESPACE_ID;\n}\n\nfunction partitionStorageTypesForTarget(\n targetId: string,\n types: Record<string, StorageTypeInstance | PostgresEnumStorageEntry>,\n namespaceTypes?: Readonly<Record<string, Readonly<Record<string, PostgresEnumStorageEntry>>>>,\n): {\n readonly documentTypes: Record<string, StorageTypeInstance | PostgresEnumStorageEntry>;\n readonly namespaceEnumTypesById: Record<string, Record<string, PostgresEnumStorageEntry>>;\n} {\n const documentTypes: Record<string, StorageTypeInstance | PostgresEnumStorageEntry> = {};\n const namespaceEnumTypesById: Record<string, Record<string, PostgresEnumStorageEntry>> = {};\n for (const [name, entry] of Object.entries(types)) {\n if (isPostgresEnumStorageEntry(entry)) {\n if (targetId !== 'postgres') {\n throw new Error(\n `buildSqlContractFromDefinition: postgres enum \"${name}\" is only valid when target is \"postgres\" (got \"${targetId}\").`,\n );\n }\n let slot = namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID];\n if (slot === undefined) {\n slot = {};\n namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID] = slot;\n }\n slot[name] = entry;\n continue;\n }\n documentTypes[name] = entry;\n }\n if (namespaceTypes !== undefined) {\n for (const [nsId, enumsInNs] of Object.entries(namespaceTypes)) {\n for (const [name, entry] of Object.entries(enumsInNs)) {\n if (targetId !== 'postgres') {\n throw new Error(\n `buildSqlContractFromDefinition: postgres enum \"${name}\" is only valid when target is \"postgres\" (got \"${targetId}\").`,\n );\n }\n let slot = namespaceEnumTypesById[nsId];\n if (slot === undefined) {\n slot = {};\n namespaceEnumTypesById[nsId] = slot;\n }\n slot[name] = entry;\n }\n }\n }\n return { documentTypes, namespaceEnumTypesById };\n}\n\nexport function buildSqlContractFromDefinition(\n definition: ContractDefinition,\n codecLookup?: CodecLookup,\n): Contract<SqlStorage> {\n const target = definition.target.targetId;\n const targetFamily = 'sql';\n const modelsByName = new Map(definition.models.map((m) => [m.modelName, m]));\n\n const tablesByNamespace: Record<string, Record<string, StorageTable>> = {};\n const tableNameToNamespaceId = new Map<string, string>();\n const modelNameToNamespaceId = new Map<string, string>();\n const executionDefaults: ExecutionMutationDefault[] = [];\n const modelsByNamespace: Record<string, Record<string, ContractModel>> = {};\n const roots: Record<string, CrossReference> = {};\n\n for (const semanticModel of definition.models) {\n const tableName = semanticModel.tableName;\n const namespaceId =\n semanticModel.namespaceId !== undefined && semanticModel.namespaceId.length > 0\n ? semanticModel.namespaceId\n : defaultModelNamespaceId(target);\n modelNameToNamespaceId.set(semanticModel.modelName, namespaceId);\n roots[tableName] = crossRef(semanticModel.modelName, namespaceId);\n\n // --- Build storage table ---\n\n const columns: Record<string, StorageColumn> = {};\n const fieldToColumn: Record<string, string> = {};\n const domainFields: Record<string, ContractField> = {};\n const domainFieldRefs: Record<string, DomainFieldRef> = {};\n\n for (const field of semanticModel.fields) {\n const executionDefaultPhases =\n field.executionDefaults?.onCreate || field.executionDefaults?.onUpdate\n ? field.executionDefaults\n : undefined;\n if (executionDefaultPhases) {\n if (field.default !== undefined) {\n throw new Error(\n `Field \"${semanticModel.modelName}.${field.fieldName}\" cannot define both default and executionDefaults.`,\n );\n }\n if (field.nullable) {\n throw new Error(\n `Field \"${semanticModel.modelName}.${field.fieldName}\" cannot be nullable when executionDefaults are present.`,\n );\n }\n }\n\n const column = buildStorageColumn(field, codecLookup);\n columns[field.columnName] = column;\n fieldToColumn[field.fieldName] = field.columnName;\n\n domainFields[field.fieldName] = buildDomainField(field, column);\n\n if (isValueObjectField(field)) {\n domainFieldRefs[field.fieldName] = {\n kind: 'valueObject',\n name: field.valueObjectName,\n ...(field.many ? { many: true } : {}),\n };\n } else if (field.many) {\n domainFieldRefs[field.fieldName] = { kind: 'scalar', many: true };\n }\n\n if (executionDefaultPhases) {\n executionDefaults.push({\n ref: { table: tableName, column: field.columnName },\n ...ifDefined('onCreate', executionDefaultPhases.onCreate),\n ...ifDefined('onUpdate', executionDefaultPhases.onUpdate),\n });\n }\n }\n\n const foreignKeys = (semanticModel.foreignKeys ?? []).map((fk) => {\n const targetModel = assertKnownTargetModel(\n modelsByName,\n semanticModel.modelName,\n fk.references.model,\n 'Foreign key',\n );\n assertTargetTableMatches(\n semanticModel.modelName,\n targetModel,\n fk.references.table,\n 'Foreign key',\n );\n const targetNamespaceId =\n fk.references.namespaceId ??\n (targetModel.namespaceId !== undefined && targetModel.namespaceId.length > 0\n ? targetModel.namespaceId\n : defaultModelNamespaceId(target));\n return {\n source: { namespaceId: asNamespaceId(namespaceId), tableName, columns: fk.columns },\n target: {\n namespaceId: asNamespaceId(targetNamespaceId),\n tableName: fk.references.table,\n columns: fk.references.columns,\n },\n ...applyFkDefaults(\n {\n ...ifDefined('constraint', fk.constraint),\n ...ifDefined('index', fk.index),\n },\n definition.foreignKeyDefaults,\n ),\n ...ifDefined('name', fk.name),\n ...ifDefined('onDelete', fk.onDelete),\n ...ifDefined('onUpdate', fk.onUpdate),\n };\n });\n\n const existingNs = tableNameToNamespaceId.get(tableName);\n if (existingNs !== undefined && existingNs !== namespaceId) {\n throw new Error(\n `buildSqlContractFromDefinition: table \"${tableName}\" is mapped in namespace \"${namespaceId}\" but already exists in namespace \"${existingNs}\".`,\n );\n }\n tableNameToNamespaceId.set(tableName, namespaceId);\n\n const tableInput: StorageTableInput = {\n columns,\n uniques: (semanticModel.uniques ?? []).map((u) => ({\n columns: u.columns,\n ...ifDefined('name', u.name),\n })),\n indexes: (semanticModel.indexes ?? []).map((i) => ({\n columns: i.columns,\n ...ifDefined('name', i.name),\n ...ifDefined('type', i.type),\n ...ifDefined('options', i.options),\n })),\n foreignKeys,\n ...(semanticModel.id\n ? {\n primaryKey: {\n columns: semanticModel.id.columns,\n ...ifDefined('name', semanticModel.id.name),\n },\n }\n : {}),\n };\n\n let nsTables = tablesByNamespace[namespaceId];\n if (nsTables === undefined) {\n nsTables = {};\n tablesByNamespace[namespaceId] = nsTables;\n }\n if (nsTables[tableName] !== undefined) {\n throw new Error(\n `buildSqlContractFromDefinition: duplicate table \"${tableName}\" in namespace \"${namespaceId}\".`,\n );\n }\n nsTables[tableName] = new StorageTable(tableInput);\n\n // --- Build contract model ---\n\n const storageFields: Record<string, { readonly column: string }> = {};\n for (const [fieldName, columnName] of Object.entries(fieldToColumn)) {\n storageFields[fieldName] = { column: columnName };\n }\n\n const columnToField = new Map(\n Object.entries(fieldToColumn).map(([field, col]) => [col, field]),\n );\n const modelRelations: Record<string, ContractRelation> = {};\n for (const relation of semanticModel.relations ?? []) {\n const targetModel = assertKnownTargetModel(\n modelsByName,\n semanticModel.modelName,\n relation.toModel,\n 'Relation',\n );\n assertTargetTableMatches(semanticModel.modelName, targetModel, relation.toTable, 'Relation');\n\n if (relation.cardinality === 'N:M' && !relation.through) {\n throw new Error(\n `Relation \"${semanticModel.modelName}.${relation.fieldName}\" with cardinality \"N:M\" requires through metadata`,\n );\n }\n\n const targetColumnToField = new Map(\n targetModel.fields.map((f) => [f.columnName, f.fieldName]),\n );\n\n modelRelations[relation.fieldName] = {\n to: crossRef(\n relation.toModel,\n resolveModelNamespaceId(targetModel, modelNameToNamespaceId, target),\n ),\n // RelationDefinition.cardinality includes 'N:M' which isn't in\n // ContractReferenceRelation yet — cast is needed until the contract\n // type is extended to cover many-to-many.\n cardinality: relation.cardinality as ContractRelation['cardinality'],\n on: {\n localFields: relation.on.parentColumns.map((col) => columnToField.get(col) ?? col),\n targetFields: relation.on.childColumns.map((col) => targetColumnToField.get(col) ?? col),\n },\n ...(relation.through\n ? {\n through: {\n table: relation.through.table,\n parentCols: relation.through.parentColumns,\n childCols: relation.through.childColumns,\n },\n }\n : undefined),\n };\n }\n\n let namespaceModels = modelsByNamespace[namespaceId];\n if (namespaceModels === undefined) {\n namespaceModels = {};\n modelsByNamespace[namespaceId] = namespaceModels;\n }\n namespaceModels[semanticModel.modelName] = {\n storage: {\n table: tableName,\n fields: storageFields,\n },\n fields: domainFields,\n relations: modelRelations,\n };\n }\n\n // --- Assemble contract ---\n\n // Normalise raw codec-triple inputs to the `kind: 'codec-instance'`\n // discriminator shape before hashing so the storageHash matches the\n // persisted JSON envelope produced from the SqlStorage class instance\n // (which always carries the discriminator).\n const rawStorageTypes = (definition.storageTypes ?? {}) as Record<\n string,\n StorageTypeInstance | PostgresEnumStorageEntry\n >;\n const storageTypes = Object.fromEntries(\n Object.entries(rawStorageTypes).map(([name, entry]) => {\n if (isPostgresEnumStorageEntry(entry)) return [name, entry];\n if ((entry as { kind?: unknown }).kind === 'codec-instance') return [name, entry];\n return [\n name,\n toStorageTypeInstance({\n codecId: entry.codecId,\n nativeType: entry.nativeType,\n typeParams: (entry as { typeParams?: Record<string, unknown> }).typeParams ?? {},\n }),\n ];\n }),\n );\n const { documentTypes, namespaceEnumTypesById } = partitionStorageTypesForTarget(\n target,\n storageTypes,\n definition.namespaceTypes,\n );\n const namespaceCoordinateIds = collectStorageNamespaceCoordinateIds(definition);\n for (const id of Object.keys(namespaceEnumTypesById)) {\n namespaceCoordinateIds.add(id);\n }\n const { createNamespace } = definition;\n const namespaces = blindCast<\n SqlStorageInput['namespaces'],\n 'contract authoring materialises each namespace coordinate from the model set and explicit namespace list'\n >(\n Object.fromEntries(\n [...namespaceCoordinateIds].sort().map((id) => {\n const enumTypes = namespaceEnumTypesById[id];\n const nsInput: SqlNamespaceTablesInput = {\n id,\n tables: tablesByNamespace[id] ?? {},\n ...ifDefined('enum', enumTypes),\n };\n return [id, createNamespace ? createNamespace(nsInput) : buildSqlNamespace(nsInput)];\n }),\n ),\n );\n const storageWithoutHash = {\n ...(Object.keys(documentTypes).length > 0 ? { types: documentTypes } : {}),\n namespaces,\n };\n const storageHash: StorageHashBase<string> = definition.storageHash\n ? coreHash(definition.storageHash)\n : computeStorageHash({\n target,\n targetFamily,\n storage: storageWithoutHash as Record<string, unknown>,\n ...sqlContractCanonicalizationHooks,\n });\n const storage = new SqlStorage({ ...storageWithoutHash, storageHash });\n\n const executionSection =\n executionDefaults.length > 0\n ? {\n mutations: {\n defaults: executionDefaults.sort((a, b) => {\n const tableCompare = a.ref.table.localeCompare(b.ref.table);\n if (tableCompare !== 0) {\n return tableCompare;\n }\n return a.ref.column.localeCompare(b.ref.column);\n }),\n },\n }\n : undefined;\n\n const extensionNamespaces = definition.extensionPacks\n ? Object.values(definition.extensionPacks).map((pack) => pack.id)\n : undefined;\n\n const extensionPacks: Record<string, unknown> = { ...(definition.extensionPacks || {}) };\n if (extensionNamespaces) {\n for (const namespace of extensionNamespaces) {\n if (!Object.hasOwn(extensionPacks, namespace)) {\n extensionPacks[namespace] = {};\n }\n }\n }\n\n const extensionPackCapabilitySources = definition.extensionPacks\n ? Object.values(definition.extensionPacks).map(\n (pack) => pack.capabilities as CapabilityMatrix | undefined,\n )\n : [];\n const capabilities = mergeCapabilityMatrices(\n definition.target.capabilities as CapabilityMatrix | undefined,\n ...extensionPackCapabilitySources,\n );\n // Internal `profileHash` computation is unchanged from `origin/main`: it\n // continues to fingerprint the author-declared capability subset. With\n // `capabilities` removed from the `defineContract` input that subset is\n // now always empty, so the hash naturally stabilises at `hash({})`.\n const profileHash = computeProfileHash({\n target,\n targetFamily,\n capabilities: {},\n });\n\n const executionWithHash = executionSection\n ? {\n ...executionSection,\n executionHash: computeExecutionHash({ target, targetFamily, execution: executionSection }),\n }\n : undefined;\n\n const valueObjects: Record<string, ContractValueObject> | undefined =\n definition.valueObjects && definition.valueObjects.length > 0\n ? Object.fromEntries(\n definition.valueObjects.map((vo) => [\n vo.name,\n {\n fields: Object.fromEntries(\n vo.fields.map((f) => [\n f.fieldName,\n isValueObjectField(f)\n ? {\n type: { kind: 'valueObject' as const, name: f.valueObjectName },\n nullable: f.nullable,\n ...(f.many ? { many: true } : {}),\n }\n : {\n type: {\n kind: 'scalar' as const,\n codecId: f.descriptor.codecId,\n ...ifDefined('typeParams', f.descriptor.typeParams),\n },\n nullable: f.nullable,\n },\n ]),\n ),\n },\n ]),\n )\n : undefined;\n\n const defaultNamespaceId = defaultModelNamespaceId(target);\n const domainNamespaceIds = new Set(Object.keys(modelsByNamespace));\n if (domainNamespaceIds.size === 0) {\n domainNamespaceIds.add(defaultNamespaceId);\n }\n if (valueObjects !== undefined) {\n domainNamespaceIds.add(defaultNamespaceId);\n }\n const domainNamespaces = Object.fromEntries(\n [...domainNamespaceIds].sort().map((namespaceId) => {\n const modelsInNs = modelsByNamespace[namespaceId] ?? {};\n const namespaceSlice =\n namespaceId === defaultNamespaceId && valueObjects !== undefined\n ? { models: modelsInNs, valueObjects }\n : { models: modelsInNs };\n return [namespaceId, namespaceSlice];\n }),\n );\n\n const contract: Contract<SqlStorage> = {\n target,\n targetFamily,\n domain: { namespaces: domainNamespaces },\n roots,\n storage,\n ...(executionWithHash ? { execution: executionWithHash } : {}),\n extensionPacks,\n capabilities,\n profileHash,\n meta: {},\n };\n\n assertStorageSemantics(definition, contract);\n\n return contract;\n}\n"],"mappings":"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"}
|
package/dist/config-types.d.mts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { Contract } from "@prisma-next/contract/types";
|
|
2
2
|
import { ContractConfig, ContractConfig as ContractConfig$1 } from "@prisma-next/config/config-types";
|
|
3
|
+
import { TargetPackRef } from "@prisma-next/framework-components/components";
|
|
3
4
|
|
|
4
5
|
//#region src/config-types.d.ts
|
|
6
|
+
declare function emptyContract(options: {
|
|
7
|
+
readonly output?: string;
|
|
8
|
+
readonly target: TargetPackRef<'sql', string>;
|
|
9
|
+
}): ContractConfig$1;
|
|
5
10
|
declare function typescriptContract(contract: Contract, output?: string): ContractConfig$1;
|
|
6
11
|
declare function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig$1;
|
|
7
12
|
//#endregion
|
|
8
|
-
export { type ContractConfig, typescriptContract, typescriptContractFromPath };
|
|
13
|
+
export { type ContractConfig, emptyContract, typescriptContract, typescriptContractFromPath };
|
|
9
14
|
//# sourceMappingURL=config-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-types.d.mts","names":[],"sources":["../src/config-types.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-types.d.mts","names":[],"sources":["../src/config-types.ts"],"mappings":";;;;;iBAqBgB,aAAA,CAAc,OAAA;EAAA,SACnB,MAAA;EAAA,SACA,MAAA,EAAQ,aAAA;AAAA,IACf,gBAAc;AAAA,iBASF,kBAAA,CAAmB,QAAA,EAAU,QAAA,EAAU,MAAA,YAAkB,gBAAc;AAAA,iBAWvE,0BAAA,CAA2B,YAAA,UAAsB,MAAA,YAAkB,gBAAc"}
|
package/dist/config-types.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as buildSqlContractFromDefinition } from "./build-contract-BCYW3_wE.mjs";
|
|
1
2
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
2
3
|
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { ok } from "@prisma-next/utils/result";
|
|
@@ -14,6 +15,15 @@ function defaultOutputFromContractPath(contractPath) {
|
|
|
14
15
|
if (ext.length === 0) return `${contractPath}.json`;
|
|
15
16
|
return `${contractPath.slice(0, -ext.length)}.json`;
|
|
16
17
|
}
|
|
18
|
+
function emptyContract(options) {
|
|
19
|
+
return {
|
|
20
|
+
source: { load: async () => ok(buildSqlContractFromDefinition({
|
|
21
|
+
target: options.target,
|
|
22
|
+
models: []
|
|
23
|
+
})) },
|
|
24
|
+
...ifDefined("output", options.output)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
17
27
|
function typescriptContract(contract, output) {
|
|
18
28
|
return {
|
|
19
29
|
source: { load: async () => ok(contract) },
|
|
@@ -37,6 +47,6 @@ function typescriptContractFromPath(contractPath, output) {
|
|
|
37
47
|
};
|
|
38
48
|
}
|
|
39
49
|
//#endregion
|
|
40
|
-
export { typescriptContract, typescriptContractFromPath };
|
|
50
|
+
export { emptyContract, typescriptContract, typescriptContractFromPath };
|
|
41
51
|
|
|
42
52
|
//# sourceMappingURL=config-types.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-types.mjs","names":[],"sources":["../src/config-types.ts"],"sourcesContent":["import { pathToFileURL } from 'node:url';\nimport type { ContractConfig } from '@prisma-next/config/config-types';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { ok } from '@prisma-next/utils/result';\nimport { extname } from 'pathe';\n\n/**\n * Derives the emit output path from the TS contract input so artefacts land\n * colocated with the source (e.g. `prisma/contract.ts` →\n * `prisma/contract.json`). Mirrors the same default-derivation logic in\n * `@prisma-next/sql-contract-psl/provider`.\n */\nfunction defaultOutputFromContractPath(contractPath: string): string {\n const ext = extname(contractPath);\n if (ext.length === 0) return `${contractPath}.json`;\n return `${contractPath.slice(0, -ext.length)}.json`;\n}\n\nexport function typescriptContract(contract: Contract, output?: string): ContractConfig {\n return {\n source: {\n load: async () => ok(contract),\n },\n // The in-memory variant has no input path to anchor on; fall through to\n // the global default in `normalizeContractConfig` when caller doesn't pin it.\n ...ifDefined('output', output),\n };\n}\n\nexport function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig {\n return {\n source: {\n inputs: [contractPath],\n load: async (context) => {\n const [absolutePath] = context.resolvedInputs;\n if (absolutePath === undefined) {\n throw new Error(\n 'typescriptContractFromPath: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.',\n );\n }\n const mod = await import(pathToFileURL(absolutePath).href);\n const contract: Contract | undefined = mod.default ?? mod.contract;\n if (contract === undefined) {\n throw new Error(\n `typescriptContractFromPath: module at \"${absolutePath}\" has no \"default\" or \"contract\" export.`,\n );\n }\n return ok(contract);\n },\n },\n output: output ?? defaultOutputFromContractPath(contractPath),\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-types.mjs","names":[],"sources":["../src/config-types.ts"],"sourcesContent":["import { pathToFileURL } from 'node:url';\nimport type { ContractConfig } from '@prisma-next/config/config-types';\nimport type { Contract } from '@prisma-next/contract/types';\nimport type { TargetPackRef } from '@prisma-next/framework-components/components';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { ok } from '@prisma-next/utils/result';\nimport { extname } from 'pathe';\nimport { buildSqlContractFromDefinition } from './build-contract';\n\n/**\n * Derives the emit output path from the TS contract input so artefacts land\n * colocated with the source (e.g. `prisma/contract.ts` →\n * `prisma/contract.json`). Mirrors the same default-derivation logic in\n * `@prisma-next/sql-contract-psl/provider`.\n */\nfunction defaultOutputFromContractPath(contractPath: string): string {\n const ext = extname(contractPath);\n if (ext.length === 0) return `${contractPath}.json`;\n return `${contractPath.slice(0, -ext.length)}.json`;\n}\n\nexport function emptyContract(options: {\n readonly output?: string;\n readonly target: TargetPackRef<'sql', string>;\n}): ContractConfig {\n return {\n source: {\n load: async () => ok(buildSqlContractFromDefinition({ target: options.target, models: [] })),\n },\n ...ifDefined('output', options.output),\n };\n}\n\nexport function typescriptContract(contract: Contract, output?: string): ContractConfig {\n return {\n source: {\n load: async () => ok(contract),\n },\n // The in-memory variant has no input path to anchor on; fall through to\n // the global default in `normalizeContractConfig` when caller doesn't pin it.\n ...ifDefined('output', output),\n };\n}\n\nexport function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig {\n return {\n source: {\n inputs: [contractPath],\n load: async (context) => {\n const [absolutePath] = context.resolvedInputs;\n if (absolutePath === undefined) {\n throw new Error(\n 'typescriptContractFromPath: context.resolvedInputs is empty. The CLI config loader should populate it positional-matched with source.inputs.',\n );\n }\n const mod = await import(pathToFileURL(absolutePath).href);\n const contract: Contract | undefined = mod.default ?? mod.contract;\n if (contract === undefined) {\n throw new Error(\n `typescriptContractFromPath: module at \"${absolutePath}\" has no \"default\" or \"contract\" export.`,\n );\n }\n return ok(contract);\n },\n },\n output: output ?? defaultOutputFromContractPath(contractPath),\n };\n}\n"],"mappings":";;;;;;;;;;;;AAeA,SAAS,8BAA8B,cAA8B;CACnE,MAAM,MAAM,QAAQ,YAAY;CAChC,IAAI,IAAI,WAAW,GAAG,OAAO,GAAG,aAAa;CAC7C,OAAO,GAAG,aAAa,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE;AAC/C;AAEA,SAAgB,cAAc,SAGX;CACjB,OAAO;EACL,QAAQ,EACN,MAAM,YAAY,GAAG,+BAA+B;GAAE,QAAQ,QAAQ;GAAQ,QAAQ,CAAC;EAAE,CAAC,CAAC,EAC7F;EACA,GAAG,UAAU,UAAU,QAAQ,MAAM;CACvC;AACF;AAEA,SAAgB,mBAAmB,UAAoB,QAAiC;CACtF,OAAO;EACL,QAAQ,EACN,MAAM,YAAY,GAAG,QAAQ,EAC/B;EAGA,GAAG,UAAU,UAAU,MAAM;CAC/B;AACF;AAEA,SAAgB,2BAA2B,cAAsB,QAAiC;CAChG,OAAO;EACL,QAAQ;GACN,QAAQ,CAAC,YAAY;GACrB,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,gBAAgB,QAAQ;IAC/B,IAAI,iBAAiB,KAAA,GACnB,MAAM,IAAI,MACR,8IACF;IAEF,MAAM,MAAM,MAAM,OAAO,cAAc,YAAY,EAAE;IACrD,MAAM,WAAiC,IAAI,WAAW,IAAI;IAC1D,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MACR,0CAA0C,aAAa,yCACzD;IAEF,OAAO,GAAG,QAAQ;GACpB;EACF;EACA,QAAQ,UAAU,8BAA8B,YAAY;CAC9D;AACF"}
|