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