@prisma-next/sql-contract-ts 0.11.0-dev.63 → 0.11.0-dev.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,371 +1,10 @@
1
+ import { t as buildSqlContractFromDefinition } from "./build-contract-BEkCxdji.mjs";
1
2
  import { blindCast } from "@prisma-next/utils/casts";
2
- import { computeExecutionHash, computeProfileHash, computeStorageHash } from "@prisma-next/contract/hashing";
3
- import { asNamespaceId, coreHash, crossRef, isColumnDefault } from "@prisma-next/contract/types";
4
- import { createEntityHelpersFromNamespace, 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";
3
+ import { isColumnDefault } from "@prisma-next/contract/types";
4
+ import { createEntityHelpersFromNamespace } from "@prisma-next/contract-authoring";
5
+ import { isPostgresEnumStorageEntry, toStorageTypeInstance } from "@prisma-next/sql-contract/types";
11
6
  import { ifDefined } from "@prisma-next/utils/defined";
12
7
  import { assertNoCrossRegistryCollisions, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringTypeConstructorDescriptor, mergeAuthoringNamespaces, validateAuthoringHelperArguments } from "@prisma-next/framework-components/authoring";
13
- //#region src/build-contract.ts
14
- function encodeDefaultLiteralValue(value, codecId, codecLookup) {
15
- const codec = codecLookup?.get(codecId);
16
- if (codec) return codec.encodeJson(value);
17
- return value;
18
- }
19
- function encodeColumnDefault(defaultInput, codecId, codecLookup) {
20
- if (defaultInput.kind === "function") return {
21
- kind: "function",
22
- expression: defaultInput.expression
23
- };
24
- return {
25
- kind: "literal",
26
- value: encodeDefaultLiteralValue(defaultInput.value, codecId, codecLookup)
27
- };
28
- }
29
- function assertStorageSemantics(definition, contract) {
30
- const semanticErrors = validateStorageSemantics(contract.storage);
31
- if (semanticErrors.length > 0) throw new Error(`Contract semantic validation failed: ${semanticErrors.join("; ")}`);
32
- const indexTypeRegistry = createIndexTypeRegistry();
33
- const packsToRegister = [definition.target, ...Object.values(definition.extensionPacks ?? {})];
34
- for (const pack of packsToRegister) {
35
- const registration = pack.indexTypes;
36
- if (registration === void 0) continue;
37
- 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}).`);
38
- for (const entry of registration.entries) indexTypeRegistry.register(entry);
39
- }
40
- validateIndexTypes(contract, indexTypeRegistry);
41
- }
42
- function assertKnownTargetModel(modelsByName, sourceModelName, targetModelName, context) {
43
- const targetModel = modelsByName.get(targetModelName);
44
- if (!targetModel) throw new Error(`${context} on model "${sourceModelName}" references unknown model "${targetModelName}"`);
45
- return targetModel;
46
- }
47
- function assertTargetTableMatches(sourceModelName, targetModel, referencedTableName, context) {
48
- if (targetModel.tableName !== referencedTableName) throw new Error(`${context} on model "${sourceModelName}" references table "${referencedTableName}" but model "${targetModel.modelName}" maps to "${targetModel.tableName}"`);
49
- }
50
- function isValueObjectField(field) {
51
- return "valueObjectName" in field;
52
- }
53
- const JSONB_CODEC_ID = "pg/jsonb@1";
54
- const JSONB_NATIVE_TYPE = "jsonb";
55
- function resolveModelNamespaceId(model, modelNameToNamespaceId) {
56
- if (model.namespaceId !== void 0 && model.namespaceId.length > 0) return model.namespaceId;
57
- return modelNameToNamespaceId.get(model.modelName) ?? UNBOUND_NAMESPACE_ID;
58
- }
59
- function buildStorageColumn(field, codecLookup) {
60
- if (isValueObjectField(field)) {
61
- const encodedDefault = field.default !== void 0 ? encodeColumnDefault(field.default, JSONB_CODEC_ID, codecLookup) : void 0;
62
- return {
63
- nativeType: JSONB_NATIVE_TYPE,
64
- codecId: JSONB_CODEC_ID,
65
- nullable: field.nullable,
66
- ...ifDefined("default", encodedDefault)
67
- };
68
- }
69
- if (field.many) return {
70
- nativeType: JSONB_NATIVE_TYPE,
71
- codecId: JSONB_CODEC_ID,
72
- nullable: field.nullable
73
- };
74
- const codecId = field.descriptor.codecId;
75
- const encodedDefault = field.default !== void 0 ? encodeColumnDefault(field.default, codecId, codecLookup) : void 0;
76
- return {
77
- nativeType: field.descriptor.nativeType,
78
- codecId,
79
- nullable: field.nullable,
80
- ...ifDefined("typeParams", field.descriptor.typeParams),
81
- ...ifDefined("default", encodedDefault),
82
- ...ifDefined("typeRef", field.descriptor.typeRef)
83
- };
84
- }
85
- function buildDomainField(field, column) {
86
- if (isValueObjectField(field)) return {
87
- type: {
88
- kind: "valueObject",
89
- name: field.valueObjectName
90
- },
91
- nullable: field.nullable,
92
- ...field.many ? { many: true } : {}
93
- };
94
- return {
95
- type: {
96
- kind: "scalar",
97
- codecId: column.codecId,
98
- ...ifDefined("typeParams", column.typeParams)
99
- },
100
- nullable: column.nullable,
101
- ...field.many ? { many: true } : {}
102
- };
103
- }
104
- function collectStorageNamespaceCoordinateIds(definition) {
105
- const ids = /* @__PURE__ */ new Set();
106
- ids.add(UNBOUND_NAMESPACE_ID);
107
- for (const id of definition.namespaces ?? []) if (id.length > 0) ids.add(id);
108
- for (const model of definition.models) if (model.namespaceId !== void 0 && model.namespaceId.length > 0) ids.add(model.namespaceId);
109
- return ids;
110
- }
111
- const POSTGRES_ENUM_NAMESPACE_ID = "public";
112
- function partitionStorageTypesForTarget(targetId, types, namespaceTypes) {
113
- const documentTypes = {};
114
- const namespaceEnumTypesById = {};
115
- for (const [name, entry] of Object.entries(types)) {
116
- if (isPostgresEnumStorageEntry(entry)) {
117
- if (targetId !== "postgres") throw new Error(`buildSqlContractFromDefinition: postgres enum "${name}" is only valid when target is "postgres" (got "${targetId}").`);
118
- let slot = namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID];
119
- if (slot === void 0) {
120
- slot = {};
121
- namespaceEnumTypesById[POSTGRES_ENUM_NAMESPACE_ID] = slot;
122
- }
123
- slot[name] = entry;
124
- continue;
125
- }
126
- documentTypes[name] = entry;
127
- }
128
- if (namespaceTypes !== void 0) for (const [nsId, enumsInNs] of Object.entries(namespaceTypes)) for (const [name, entry] of Object.entries(enumsInNs)) {
129
- if (targetId !== "postgres") throw new Error(`buildSqlContractFromDefinition: postgres enum "${name}" is only valid when target is "postgres" (got "${targetId}").`);
130
- let slot = namespaceEnumTypesById[nsId];
131
- if (slot === void 0) {
132
- slot = {};
133
- namespaceEnumTypesById[nsId] = slot;
134
- }
135
- slot[name] = entry;
136
- }
137
- return {
138
- documentTypes,
139
- namespaceEnumTypesById
140
- };
141
- }
142
- function buildSqlContractFromDefinition(definition, codecLookup) {
143
- const target = definition.target.targetId;
144
- const targetFamily = "sql";
145
- const modelsByName = new Map(definition.models.map((m) => [m.modelName, m]));
146
- const tablesByNamespace = {};
147
- const tableNameToNamespaceId = /* @__PURE__ */ new Map();
148
- const modelNameToNamespaceId = /* @__PURE__ */ new Map();
149
- const executionDefaults = [];
150
- const models = {};
151
- const roots = {};
152
- for (const semanticModel of definition.models) {
153
- const tableName = semanticModel.tableName;
154
- const namespaceId = semanticModel.namespaceId !== void 0 && semanticModel.namespaceId.length > 0 ? semanticModel.namespaceId : UNBOUND_NAMESPACE_ID;
155
- modelNameToNamespaceId.set(semanticModel.modelName, namespaceId);
156
- roots[tableName] = crossRef(semanticModel.modelName, namespaceId);
157
- const columns = {};
158
- const fieldToColumn = {};
159
- const domainFields = {};
160
- const domainFieldRefs = {};
161
- for (const field of semanticModel.fields) {
162
- const executionDefaultPhases = field.executionDefaults?.onCreate || field.executionDefaults?.onUpdate ? field.executionDefaults : void 0;
163
- if (executionDefaultPhases) {
164
- if (field.default !== void 0) throw new Error(`Field "${semanticModel.modelName}.${field.fieldName}" cannot define both default and executionDefaults.`);
165
- if (field.nullable) throw new Error(`Field "${semanticModel.modelName}.${field.fieldName}" cannot be nullable when executionDefaults are present.`);
166
- }
167
- const column = buildStorageColumn(field, codecLookup);
168
- columns[field.columnName] = column;
169
- fieldToColumn[field.fieldName] = field.columnName;
170
- domainFields[field.fieldName] = buildDomainField(field, column);
171
- if (isValueObjectField(field)) domainFieldRefs[field.fieldName] = {
172
- kind: "valueObject",
173
- name: field.valueObjectName,
174
- ...field.many ? { many: true } : {}
175
- };
176
- else if (field.many) domainFieldRefs[field.fieldName] = {
177
- kind: "scalar",
178
- many: true
179
- };
180
- if (executionDefaultPhases) executionDefaults.push({
181
- ref: {
182
- table: tableName,
183
- column: field.columnName
184
- },
185
- ...ifDefined("onCreate", executionDefaultPhases.onCreate),
186
- ...ifDefined("onUpdate", executionDefaultPhases.onUpdate)
187
- });
188
- }
189
- const foreignKeys = (semanticModel.foreignKeys ?? []).map((fk) => {
190
- const targetModel = assertKnownTargetModel(modelsByName, semanticModel.modelName, fk.references.model, "Foreign key");
191
- assertTargetTableMatches(semanticModel.modelName, targetModel, fk.references.table, "Foreign key");
192
- const targetNamespaceId = fk.references.namespaceId ?? (targetModel.namespaceId !== void 0 && targetModel.namespaceId.length > 0 ? targetModel.namespaceId : UNBOUND_NAMESPACE_ID);
193
- return {
194
- source: {
195
- namespaceId: asNamespaceId(namespaceId),
196
- tableName,
197
- columns: fk.columns
198
- },
199
- target: {
200
- namespaceId: asNamespaceId(targetNamespaceId),
201
- tableName: fk.references.table,
202
- columns: fk.references.columns
203
- },
204
- ...applyFkDefaults({
205
- ...ifDefined("constraint", fk.constraint),
206
- ...ifDefined("index", fk.index)
207
- }, definition.foreignKeyDefaults),
208
- ...ifDefined("name", fk.name),
209
- ...ifDefined("onDelete", fk.onDelete),
210
- ...ifDefined("onUpdate", fk.onUpdate)
211
- };
212
- });
213
- const existingNs = tableNameToNamespaceId.get(tableName);
214
- if (existingNs !== void 0 && existingNs !== namespaceId) throw new Error(`buildSqlContractFromDefinition: table "${tableName}" is mapped in namespace "${namespaceId}" but already exists in namespace "${existingNs}".`);
215
- tableNameToNamespaceId.set(tableName, namespaceId);
216
- const tableInput = {
217
- columns,
218
- uniques: (semanticModel.uniques ?? []).map((u) => ({
219
- columns: u.columns,
220
- ...ifDefined("name", u.name)
221
- })),
222
- indexes: (semanticModel.indexes ?? []).map((i) => ({
223
- columns: i.columns,
224
- ...ifDefined("name", i.name),
225
- ...ifDefined("type", i.type),
226
- ...ifDefined("options", i.options)
227
- })),
228
- foreignKeys,
229
- ...semanticModel.id ? { primaryKey: {
230
- columns: semanticModel.id.columns,
231
- ...ifDefined("name", semanticModel.id.name)
232
- } } : {}
233
- };
234
- let nsTables = tablesByNamespace[namespaceId];
235
- if (nsTables === void 0) {
236
- nsTables = {};
237
- tablesByNamespace[namespaceId] = nsTables;
238
- }
239
- if (nsTables[tableName] !== void 0) throw new Error(`buildSqlContractFromDefinition: duplicate table "${tableName}" in namespace "${namespaceId}".`);
240
- nsTables[tableName] = new StorageTable(tableInput);
241
- const storageFields = {};
242
- for (const [fieldName, columnName] of Object.entries(fieldToColumn)) storageFields[fieldName] = { column: columnName };
243
- const columnToField = new Map(Object.entries(fieldToColumn).map(([field, col]) => [col, field]));
244
- const modelRelations = {};
245
- for (const relation of semanticModel.relations ?? []) {
246
- const targetModel = assertKnownTargetModel(modelsByName, semanticModel.modelName, relation.toModel, "Relation");
247
- assertTargetTableMatches(semanticModel.modelName, targetModel, relation.toTable, "Relation");
248
- if (relation.cardinality === "N:M" && !relation.through) throw new Error(`Relation "${semanticModel.modelName}.${relation.fieldName}" with cardinality "N:M" requires through metadata`);
249
- const targetColumnToField = new Map(targetModel.fields.map((f) => [f.columnName, f.fieldName]));
250
- modelRelations[relation.fieldName] = {
251
- to: crossRef(relation.toModel, resolveModelNamespaceId(targetModel, modelNameToNamespaceId)),
252
- cardinality: relation.cardinality,
253
- on: {
254
- localFields: relation.on.parentColumns.map((col) => columnToField.get(col) ?? col),
255
- targetFields: relation.on.childColumns.map((col) => targetColumnToField.get(col) ?? col)
256
- },
257
- ...relation.through ? { through: {
258
- table: relation.through.table,
259
- parentCols: relation.through.parentColumns,
260
- childCols: relation.through.childColumns
261
- } } : void 0
262
- };
263
- }
264
- models[semanticModel.modelName] = {
265
- storage: {
266
- table: tableName,
267
- fields: storageFields
268
- },
269
- fields: domainFields,
270
- relations: modelRelations
271
- };
272
- }
273
- const rawStorageTypes = definition.storageTypes ?? {};
274
- const { documentTypes, namespaceEnumTypesById } = partitionStorageTypesForTarget(target, Object.fromEntries(Object.entries(rawStorageTypes).map(([name, entry]) => {
275
- if (isPostgresEnumStorageEntry(entry)) return [name, entry];
276
- if (entry.kind === "codec-instance") return [name, entry];
277
- return [name, toStorageTypeInstance({
278
- codecId: entry.codecId,
279
- nativeType: entry.nativeType,
280
- typeParams: entry.typeParams ?? {}
281
- })];
282
- })), definition.namespaceTypes);
283
- const namespaceCoordinateIds = collectStorageNamespaceCoordinateIds(definition);
284
- for (const id of Object.keys(namespaceEnumTypesById)) namespaceCoordinateIds.add(id);
285
- const { createNamespace } = definition;
286
- const namespaces = blindCast(Object.fromEntries([...namespaceCoordinateIds].sort().map((id) => {
287
- const enumTypes = namespaceEnumTypesById[id];
288
- const nsInput = {
289
- id,
290
- tables: tablesByNamespace[id] ?? {},
291
- ...ifDefined("enum", enumTypes)
292
- };
293
- return [id, createNamespace ? createNamespace(nsInput) : buildSqlNamespace(nsInput)];
294
- })));
295
- const domainUnboundTypes = Object.keys(documentTypes).length > 0 ? { types: documentTypes } : void 0;
296
- const domain = domainUnboundTypes !== void 0 ? { [UNBOUND_NAMESPACE_ID]: domainUnboundTypes } : void 0;
297
- const storageWithoutHash = {
298
- ...Object.keys(documentTypes).length > 0 ? { types: documentTypes } : {},
299
- namespaces
300
- };
301
- const storageHash = definition.storageHash ? coreHash(definition.storageHash) : computeStorageHash({
302
- target,
303
- targetFamily,
304
- storage: storageWithoutHash,
305
- ...sqlContractCanonicalizationHooks
306
- });
307
- const storage = new SqlStorage({
308
- ...storageWithoutHash,
309
- storageHash
310
- });
311
- const executionSection = executionDefaults.length > 0 ? { mutations: { defaults: executionDefaults.sort((a, b) => {
312
- const tableCompare = a.ref.table.localeCompare(b.ref.table);
313
- if (tableCompare !== 0) return tableCompare;
314
- return a.ref.column.localeCompare(b.ref.column);
315
- }) } } : void 0;
316
- const extensionNamespaces = definition.extensionPacks ? Object.values(definition.extensionPacks).map((pack) => pack.id) : void 0;
317
- const extensionPacks = { ...definition.extensionPacks || {} };
318
- if (extensionNamespaces) {
319
- for (const namespace of extensionNamespaces) if (!Object.hasOwn(extensionPacks, namespace)) extensionPacks[namespace] = {};
320
- }
321
- const extensionPackCapabilitySources = definition.extensionPacks ? Object.values(definition.extensionPacks).map((pack) => pack.capabilities) : [];
322
- const capabilities = mergeCapabilityMatrices(definition.target.capabilities, ...extensionPackCapabilitySources);
323
- const profileHash = computeProfileHash({
324
- target,
325
- targetFamily,
326
- capabilities: {}
327
- });
328
- const executionWithHash = executionSection ? {
329
- ...executionSection,
330
- executionHash: computeExecutionHash({
331
- target,
332
- targetFamily,
333
- execution: executionSection
334
- })
335
- } : void 0;
336
- 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) ? {
337
- type: {
338
- kind: "valueObject",
339
- name: f.valueObjectName
340
- },
341
- nullable: f.nullable,
342
- ...f.many ? { many: true } : {}
343
- } : {
344
- type: {
345
- kind: "scalar",
346
- codecId: f.descriptor.codecId,
347
- ...ifDefined("typeParams", f.descriptor.typeParams)
348
- },
349
- nullable: f.nullable
350
- }])) }])) : void 0;
351
- const contract = {
352
- target,
353
- targetFamily,
354
- models,
355
- roots,
356
- storage,
357
- ...domain !== void 0 ? { domain } : {},
358
- ...executionWithHash ? { execution: executionWithHash } : {},
359
- ...ifDefined("valueObjects", valueObjects),
360
- extensionPacks,
361
- capabilities,
362
- profileHash,
363
- meta: {}
364
- };
365
- assertStorageSemantics(definition, contract);
366
- return contract;
367
- }
368
- //#endregion
369
8
  //#region src/authoring-helper-runtime.ts
370
9
  function isNamedConstraintOptionsLike(value) {
371
10
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;