@prisma-next/sql-contract-ts 0.12.0-dev.5 → 0.12.0-dev.50
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/README.md +8 -0
- package/dist/{build-contract-BCYW3_wE.mjs → build-contract-B1odoaHR.mjs} +65 -52
- package/dist/build-contract-B1odoaHR.mjs.map +1 -0
- package/dist/config-types.d.mts +7 -3
- package/dist/config-types.d.mts.map +1 -1
- package/dist/config-types.mjs +12 -9
- package/dist/config-types.mjs.map +1 -1
- package/dist/contract-builder.d.mts +64 -13
- package/dist/contract-builder.d.mts.map +1 -1
- package/dist/contract-builder.mjs +29 -13
- package/dist/contract-builder.mjs.map +1 -1
- package/package.json +10 -10
- package/src/build-contract.ts +91 -59
- package/src/config-types.ts +24 -6
- package/src/contract-builder.ts +131 -15
- package/src/contract-definition.ts +23 -3
- package/src/contract-dsl.ts +3 -0
- package/src/contract-lowering.ts +2 -0
- package/src/contract-types.ts +17 -21
- package/src/exports/contract-builder.ts +1 -0
- package/dist/build-contract-BCYW3_wE.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -260,6 +260,14 @@ export default defineConfig({
|
|
|
260
260
|
});
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
+
Optional third argument (options bag) for `typescriptContract` / `typescriptContractFromPath`, and `defaultControlPolicy` on `emptyContract`:
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
typescriptContract(contract, 'src/prisma/contract.json', { defaultControlPolicy: 'external' });
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The specifier value applies only when the loaded contract omits `defaultControlPolicy` (a value authored on the contract module wins).
|
|
270
|
+
|
|
263
271
|
## Dependencies
|
|
264
272
|
|
|
265
273
|
- **`@prisma-next/config`** - `ContractConfig` types used by `typescriptContract(...)`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
2
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
2
3
|
import { computeExecutionHash, computeProfileHash, computeStorageHash } from "@prisma-next/contract/hashing";
|
|
3
4
|
import { asNamespaceId, coreHash, crossRef } from "@prisma-next/contract/types";
|
|
4
5
|
import { mergeCapabilityMatrices } from "@prisma-next/contract-authoring";
|
|
@@ -8,7 +9,6 @@ import { validateIndexTypes } from "@prisma-next/sql-contract/index-type-validat
|
|
|
8
9
|
import { createIndexTypeRegistry } from "@prisma-next/sql-contract/index-types";
|
|
9
10
|
import { SqlStorage, StorageTable, applyFkDefaults, buildSqlNamespace, isPostgresEnumStorageEntry, toStorageTypeInstance } from "@prisma-next/sql-contract/types";
|
|
10
11
|
import { validateStorageSemantics } from "@prisma-next/sql-contract/validators";
|
|
11
|
-
import { ifDefined } from "@prisma-next/utils/defined";
|
|
12
12
|
//#region src/build-contract.ts
|
|
13
13
|
function encodeDefaultLiteralValue(value, codecId, codecLookup) {
|
|
14
14
|
const codec = codecLookup?.get(codecId);
|
|
@@ -51,9 +51,9 @@ function isValueObjectField(field) {
|
|
|
51
51
|
}
|
|
52
52
|
const JSONB_CODEC_ID = "pg/jsonb@1";
|
|
53
53
|
const JSONB_NATIVE_TYPE = "jsonb";
|
|
54
|
-
function resolveModelNamespaceId(model, modelNameToNamespaceId,
|
|
54
|
+
function resolveModelNamespaceId(model, modelNameToNamespaceId, defaultNamespaceId) {
|
|
55
55
|
if (model.namespaceId !== void 0 && model.namespaceId.length > 0) return model.namespaceId;
|
|
56
|
-
return modelNameToNamespaceId.get(model.modelName) ??
|
|
56
|
+
return modelNameToNamespaceId.get(model.modelName) ?? defaultNamespaceId;
|
|
57
57
|
}
|
|
58
58
|
function buildStorageColumn(field, codecLookup) {
|
|
59
59
|
if (isValueObjectField(field)) {
|
|
@@ -102,16 +102,24 @@ function buildDomainField(field, column) {
|
|
|
102
102
|
}
|
|
103
103
|
function collectStorageNamespaceCoordinateIds(definition) {
|
|
104
104
|
const ids = /* @__PURE__ */ new Set();
|
|
105
|
-
ids.add(
|
|
105
|
+
ids.add(definition.target.defaultNamespaceId);
|
|
106
106
|
for (const id of definition.namespaces ?? []) if (id.length > 0) ids.add(id);
|
|
107
107
|
for (const model of definition.models) if (model.namespaceId !== void 0 && model.namespaceId.length > 0) ids.add(model.namespaceId);
|
|
108
108
|
return ids;
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
function ensureUnboundNamespaceSlot(namespaces, createNamespace) {
|
|
111
|
+
if (Object.hasOwn(namespaces, UNBOUND_NAMESPACE_ID)) return namespaces;
|
|
112
|
+
const unboundInput = {
|
|
113
|
+
id: UNBOUND_NAMESPACE_ID,
|
|
114
|
+
entries: { table: {} }
|
|
115
|
+
};
|
|
116
|
+
const unbound = createNamespace ? createNamespace(unboundInput) : buildSqlNamespace(unboundInput);
|
|
117
|
+
return blindCast({
|
|
118
|
+
[UNBOUND_NAMESPACE_ID]: unbound,
|
|
119
|
+
...namespaces
|
|
120
|
+
});
|
|
114
121
|
}
|
|
122
|
+
const POSTGRES_ENUM_NAMESPACE_ID = "public";
|
|
115
123
|
function partitionStorageTypesForTarget(targetId, types, namespaceTypes) {
|
|
116
124
|
const documentTypes = {};
|
|
117
125
|
const namespaceEnumTypesById = {};
|
|
@@ -144,6 +152,7 @@ function partitionStorageTypesForTarget(targetId, types, namespaceTypes) {
|
|
|
144
152
|
}
|
|
145
153
|
function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
146
154
|
const target = definition.target.targetId;
|
|
155
|
+
const defaultNamespaceId = definition.target.defaultNamespaceId;
|
|
147
156
|
const targetFamily = "sql";
|
|
148
157
|
const modelsByName = new Map(definition.models.map((m) => [m.modelName, m]));
|
|
149
158
|
const tablesByNamespace = {};
|
|
@@ -154,9 +163,9 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
154
163
|
const roots = {};
|
|
155
164
|
for (const semanticModel of definition.models) {
|
|
156
165
|
const tableName = semanticModel.tableName;
|
|
157
|
-
const namespaceId = semanticModel.namespaceId !== void 0 && semanticModel.namespaceId.length > 0 ? semanticModel.namespaceId :
|
|
166
|
+
const namespaceId = semanticModel.namespaceId !== void 0 && semanticModel.namespaceId.length > 0 ? semanticModel.namespaceId : defaultNamespaceId;
|
|
158
167
|
modelNameToNamespaceId.set(semanticModel.modelName, namespaceId);
|
|
159
|
-
roots[tableName] = crossRef(semanticModel.modelName, namespaceId);
|
|
168
|
+
if (!semanticModel.sharesBaseTable) roots[tableName] = crossRef(semanticModel.modelName, namespaceId);
|
|
160
169
|
const columns = {};
|
|
161
170
|
const fieldToColumn = {};
|
|
162
171
|
const domainFields = {};
|
|
@@ -192,7 +201,7 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
192
201
|
const foreignKeys = (semanticModel.foreignKeys ?? []).map((fk) => {
|
|
193
202
|
const targetModel = assertKnownTargetModel(modelsByName, semanticModel.modelName, fk.references.model, "Foreign key");
|
|
194
203
|
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 :
|
|
204
|
+
const targetNamespaceId = fk.references.namespaceId ?? (targetModel.namespaceId !== void 0 && targetModel.namespaceId.length > 0 ? targetModel.namespaceId : defaultNamespaceId);
|
|
196
205
|
return {
|
|
197
206
|
source: {
|
|
198
207
|
namespaceId: asNamespaceId(namespaceId),
|
|
@@ -213,34 +222,37 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
213
222
|
...ifDefined("onUpdate", fk.onUpdate)
|
|
214
223
|
};
|
|
215
224
|
});
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
...
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
nsTables =
|
|
240
|
-
|
|
225
|
+
if (!semanticModel.sharesBaseTable) {
|
|
226
|
+
const existingNs = tableNameToNamespaceId.get(tableName);
|
|
227
|
+
if (existingNs !== void 0 && existingNs !== namespaceId) throw new Error(`buildSqlContractFromDefinition: table "${tableName}" is mapped in namespace "${namespaceId}" but already exists in namespace "${existingNs}".`);
|
|
228
|
+
tableNameToNamespaceId.set(tableName, namespaceId);
|
|
229
|
+
const tableInput = {
|
|
230
|
+
columns,
|
|
231
|
+
...ifDefined("control", semanticModel.control),
|
|
232
|
+
uniques: (semanticModel.uniques ?? []).map((u) => ({
|
|
233
|
+
columns: u.columns,
|
|
234
|
+
...ifDefined("name", u.name)
|
|
235
|
+
})),
|
|
236
|
+
indexes: (semanticModel.indexes ?? []).map((i) => ({
|
|
237
|
+
columns: i.columns,
|
|
238
|
+
...ifDefined("name", i.name),
|
|
239
|
+
...ifDefined("type", i.type),
|
|
240
|
+
...ifDefined("options", i.options)
|
|
241
|
+
})),
|
|
242
|
+
foreignKeys,
|
|
243
|
+
...semanticModel.id ? { primaryKey: {
|
|
244
|
+
columns: semanticModel.id.columns,
|
|
245
|
+
...ifDefined("name", semanticModel.id.name)
|
|
246
|
+
} } : {}
|
|
247
|
+
};
|
|
248
|
+
let nsTables = tablesByNamespace[namespaceId];
|
|
249
|
+
if (nsTables === void 0) {
|
|
250
|
+
nsTables = {};
|
|
251
|
+
tablesByNamespace[namespaceId] = nsTables;
|
|
252
|
+
}
|
|
253
|
+
if (nsTables[tableName] !== void 0) throw new Error(`buildSqlContractFromDefinition: duplicate table "${tableName}" in namespace "${namespaceId}".`);
|
|
254
|
+
nsTables[tableName] = new StorageTable(tableInput);
|
|
241
255
|
}
|
|
242
|
-
if (nsTables[tableName] !== void 0) throw new Error(`buildSqlContractFromDefinition: duplicate table "${tableName}" in namespace "${namespaceId}".`);
|
|
243
|
-
nsTables[tableName] = new StorageTable(tableInput);
|
|
244
256
|
const storageFields = {};
|
|
245
257
|
for (const [fieldName, columnName] of Object.entries(fieldToColumn)) storageFields[fieldName] = { column: columnName };
|
|
246
258
|
const columnToField = new Map(Object.entries(fieldToColumn).map(([field, col]) => [col, field]));
|
|
@@ -251,7 +263,7 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
251
263
|
if (relation.cardinality === "N:M" && !relation.through) throw new Error(`Relation "${semanticModel.modelName}.${relation.fieldName}" with cardinality "N:M" requires through metadata`);
|
|
252
264
|
const targetColumnToField = new Map(targetModel.fields.map((f) => [f.columnName, f.fieldName]));
|
|
253
265
|
modelRelations[relation.fieldName] = {
|
|
254
|
-
to: crossRef(relation.toModel, resolveModelNamespaceId(targetModel, modelNameToNamespaceId,
|
|
266
|
+
to: crossRef(relation.toModel, resolveModelNamespaceId(targetModel, modelNameToNamespaceId, defaultNamespaceId)),
|
|
255
267
|
cardinality: relation.cardinality,
|
|
256
268
|
on: {
|
|
257
269
|
localFields: relation.on.parentColumns.map((col) => columnToField.get(col) ?? col),
|
|
@@ -272,6 +284,7 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
272
284
|
namespaceModels[semanticModel.modelName] = {
|
|
273
285
|
storage: {
|
|
274
286
|
table: tableName,
|
|
287
|
+
namespaceId,
|
|
275
288
|
fields: storageFields
|
|
276
289
|
},
|
|
277
290
|
fields: domainFields,
|
|
@@ -295,14 +308,13 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
295
308
|
const enumTypes = namespaceEnumTypesById[id];
|
|
296
309
|
const nsInput = {
|
|
297
310
|
id,
|
|
298
|
-
|
|
299
|
-
...ifDefined("enum", enumTypes)
|
|
311
|
+
entries: { table: tablesByNamespace[id] ?? {} }
|
|
300
312
|
};
|
|
301
|
-
return [id, createNamespace ? createNamespace(nsInput) : buildSqlNamespace(nsInput)];
|
|
313
|
+
return [id, createNamespace ? createNamespace(nsInput, enumTypes) : buildSqlNamespace(nsInput)];
|
|
302
314
|
})));
|
|
303
315
|
const storageWithoutHash = {
|
|
304
316
|
...Object.keys(documentTypes).length > 0 ? { types: documentTypes } : {},
|
|
305
|
-
namespaces
|
|
317
|
+
namespaces: ensureUnboundNamespaceSlot(namespaces, createNamespace)
|
|
306
318
|
};
|
|
307
319
|
const storageHash = definition.storageHash ? coreHash(definition.storageHash) : computeStorageHash({
|
|
308
320
|
target,
|
|
@@ -354,20 +366,21 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
354
366
|
},
|
|
355
367
|
nullable: f.nullable
|
|
356
368
|
}])) }])) : void 0;
|
|
357
|
-
const defaultNamespaceId = defaultModelNamespaceId(target);
|
|
358
369
|
const domainNamespaceIds = new Set(Object.keys(modelsByNamespace));
|
|
359
370
|
if (domainNamespaceIds.size === 0) domainNamespaceIds.add(defaultNamespaceId);
|
|
360
371
|
if (valueObjects !== void 0) domainNamespaceIds.add(defaultNamespaceId);
|
|
372
|
+
const domainNamespaces = Object.fromEntries([...domainNamespaceIds].sort().map((namespaceId) => {
|
|
373
|
+
const modelsInNs = modelsByNamespace[namespaceId] ?? {};
|
|
374
|
+
return [namespaceId, namespaceId === defaultNamespaceId && valueObjects !== void 0 ? {
|
|
375
|
+
models: modelsInNs,
|
|
376
|
+
valueObjects
|
|
377
|
+
} : { models: modelsInNs }];
|
|
378
|
+
}));
|
|
361
379
|
const contract = {
|
|
362
380
|
target,
|
|
363
381
|
targetFamily,
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return [namespaceId, namespaceId === defaultNamespaceId && valueObjects !== void 0 ? {
|
|
367
|
-
models: modelsInNs,
|
|
368
|
-
valueObjects
|
|
369
|
-
} : { models: modelsInNs }];
|
|
370
|
-
})) },
|
|
382
|
+
...ifDefined("defaultControlPolicy", definition.defaultControlPolicy),
|
|
383
|
+
domain: { namespaces: domainNamespaces },
|
|
371
384
|
roots,
|
|
372
385
|
storage,
|
|
373
386
|
...executionWithHash ? { execution: executionWithHash } : {},
|
|
@@ -382,4 +395,4 @@ function buildSqlContractFromDefinition(definition, codecLookup) {
|
|
|
382
395
|
//#endregion
|
|
383
396
|
export { buildSqlContractFromDefinition as t };
|
|
384
397
|
|
|
385
|
-
//# sourceMappingURL=build-contract-
|
|
398
|
+
//# sourceMappingURL=build-contract-B1odoaHR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-contract-B1odoaHR.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 defaultNamespaceId: string,\n): string {\n if (model.namespaceId !== undefined && model.namespaceId.length > 0) {\n return model.namespaceId;\n }\n return modelNameToNamespaceId.get(model.modelName) ?? defaultNamespaceId;\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(definition.target.defaultNamespaceId);\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\nfunction ensureUnboundNamespaceSlot(\n namespaces: SqlStorageInput['namespaces'],\n createNamespace: ContractDefinition['createNamespace'],\n): SqlStorageInput['namespaces'] {\n if (Object.hasOwn(namespaces, UNBOUND_NAMESPACE_ID)) {\n return namespaces;\n }\n const unboundInput: SqlNamespaceTablesInput = {\n id: UNBOUND_NAMESPACE_ID,\n entries: { table: {} },\n };\n const unbound = createNamespace ? createNamespace(unboundInput) : buildSqlNamespace(unboundInput);\n return blindCast<\n SqlStorageInput['namespaces'],\n 'createNamespace may return a target namespace concretion; the unbound slot matches SqlNamespace at runtime'\n >({\n [UNBOUND_NAMESPACE_ID]: unbound,\n ...namespaces,\n });\n}\n\nconst POSTGRES_ENUM_NAMESPACE_ID = 'public';\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>;\n readonly namespaceEnumTypesById: Record<string, Record<string, PostgresEnumStorageEntry>>;\n} {\n const documentTypes: Record<string, StorageTypeInstance> = {};\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 defaultNamespaceId = definition.target.defaultNamespaceId;\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 : defaultNamespaceId;\n modelNameToNamespaceId.set(semanticModel.modelName, namespaceId);\n // STI variants share the base table; the base model already owns this\n // table name and its root, so the variant contributes neither.\n if (!semanticModel.sharesBaseTable) {\n roots[tableName] = crossRef(semanticModel.modelName, namespaceId);\n }\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 : defaultNamespaceId);\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 // STI variants share the base table: their columns are already\n // materialised onto the base `ModelNode`, so the variant builds a domain\n // model (below) but no storage table of its own.\n if (!semanticModel.sharesBaseTable) {\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 ...ifDefined('control', semanticModel.control),\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\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, defaultNamespaceId),\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 namespaceId,\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 entries: {\n table: tablesByNamespace[id] ?? {},\n },\n };\n return [\n id,\n createNamespace ? createNamespace(nsInput, enumTypes) : buildSqlNamespace(nsInput),\n ];\n }),\n ),\n );\n const storageWithoutHash = {\n ...(Object.keys(documentTypes).length > 0 ? { types: documentTypes } : {}),\n namespaces: ensureUnboundNamespaceSlot(namespaces, createNamespace),\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 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 ...ifDefined('defaultControlPolicy', definition.defaultControlPolicy),\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,14 +1,18 @@
|
|
|
1
|
-
import { Contract } from "@prisma-next/contract/types";
|
|
1
|
+
import { Contract, ControlPolicy } from "@prisma-next/contract/types";
|
|
2
2
|
import { ContractConfig, ContractConfig as ContractConfig$1 } from "@prisma-next/config/config-types";
|
|
3
3
|
import { TargetPackRef } from "@prisma-next/framework-components/components";
|
|
4
4
|
|
|
5
5
|
//#region src/config-types.d.ts
|
|
6
|
+
interface TypeScriptContractSpecifierOptions {
|
|
7
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
8
|
+
}
|
|
6
9
|
declare function emptyContract(options: {
|
|
7
10
|
readonly output?: string;
|
|
8
11
|
readonly target: TargetPackRef<'sql', string>;
|
|
12
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
9
13
|
}): ContractConfig$1;
|
|
10
|
-
declare function typescriptContract(contract: Contract, output?: string): ContractConfig$1;
|
|
11
|
-
declare function typescriptContractFromPath(contractPath: string, output?: string): ContractConfig$1;
|
|
14
|
+
declare function typescriptContract(contract: Contract, output?: string, options?: TypeScriptContractSpecifierOptions): ContractConfig$1;
|
|
15
|
+
declare function typescriptContractFromPath(contractPath: string, output?: string, options?: TypeScriptContractSpecifierOptions): ContractConfig$1;
|
|
12
16
|
//#endregion
|
|
13
17
|
export { type ContractConfig, emptyContract, typescriptContract, typescriptContractFromPath };
|
|
14
18
|
//# 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":";;;;;UAsBiB,kCAAA;EAAA,SACN,oBAAA,GAAuB,aAAa;AAAA;AAAA,iBAG/B,aAAA,CAAc,OAAA;EAAA,SACnB,MAAA;EAAA,SACA,MAAA,EAAQ,aAAA;EAAA,SACR,oBAAA,GAAuB,aAAA;AAAA,IAC9B,gBAAA;AAAA,iBAYY,kBAAA,CACd,QAAA,EAAU,QAAA,EACV,MAAA,WACA,OAAA,GAAU,kCAAA,GACT,gBAAA;AAAA,iBAYa,0BAAA,CACd,YAAA,UACA,MAAA,WACA,OAAA,GAAU,kCAAA,GACT,gBAAc"}
|
package/dist/config-types.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { t as buildSqlContractFromDefinition } from "./build-contract-
|
|
1
|
+
import { t as buildSqlContractFromDefinition } from "./build-contract-B1odoaHR.mjs";
|
|
2
2
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { applySpecifierDefaultControlPolicy } from "@prisma-next/contract/apply-specifier-default-control-policy";
|
|
4
5
|
import { ok } from "@prisma-next/utils/result";
|
|
5
6
|
import { extname } from "pathe";
|
|
6
7
|
//#region src/config-types.ts
|
|
@@ -17,20 +18,22 @@ function defaultOutputFromContractPath(contractPath) {
|
|
|
17
18
|
}
|
|
18
19
|
function emptyContract(options) {
|
|
19
20
|
return {
|
|
20
|
-
source: { load: async () =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
source: { load: async () => {
|
|
22
|
+
return ok(applySpecifierDefaultControlPolicy(buildSqlContractFromDefinition({
|
|
23
|
+
target: options.target,
|
|
24
|
+
models: []
|
|
25
|
+
}), options.defaultControlPolicy));
|
|
26
|
+
} },
|
|
24
27
|
...ifDefined("output", options.output)
|
|
25
28
|
};
|
|
26
29
|
}
|
|
27
|
-
function typescriptContract(contract, output) {
|
|
30
|
+
function typescriptContract(contract, output, options) {
|
|
28
31
|
return {
|
|
29
|
-
source: { load: async () => ok(contract) },
|
|
32
|
+
source: { load: async () => ok(applySpecifierDefaultControlPolicy(contract, options?.defaultControlPolicy)) },
|
|
30
33
|
...ifDefined("output", output)
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
|
-
function typescriptContractFromPath(contractPath, output) {
|
|
36
|
+
function typescriptContractFromPath(contractPath, output, options) {
|
|
34
37
|
return {
|
|
35
38
|
source: {
|
|
36
39
|
inputs: [contractPath],
|
|
@@ -40,7 +43,7 @@ function typescriptContractFromPath(contractPath, output) {
|
|
|
40
43
|
const mod = await import(pathToFileURL(absolutePath).href);
|
|
41
44
|
const contract = mod.default ?? mod.contract;
|
|
42
45
|
if (contract === void 0) throw new Error(`typescriptContractFromPath: module at "${absolutePath}" has no "default" or "contract" export.`);
|
|
43
|
-
return ok(contract);
|
|
46
|
+
return ok(applySpecifierDefaultControlPolicy(contract, options?.defaultControlPolicy));
|
|
44
47
|
}
|
|
45
48
|
},
|
|
46
49
|
output: output ?? defaultOutputFromContractPath(contractPath)
|
|
@@ -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 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 () =>
|
|
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 { applySpecifierDefaultControlPolicy } from '@prisma-next/contract/apply-specifier-default-control-policy';\nimport type { Contract, ControlPolicy } 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 interface TypeScriptContractSpecifierOptions {\n readonly defaultControlPolicy?: ControlPolicy;\n}\n\nexport function emptyContract(options: {\n readonly output?: string;\n readonly target: TargetPackRef<'sql', string>;\n readonly defaultControlPolicy?: ControlPolicy;\n}): ContractConfig {\n return {\n source: {\n load: async () => {\n const built = buildSqlContractFromDefinition({ target: options.target, models: [] });\n return ok(applySpecifierDefaultControlPolicy(built, options.defaultControlPolicy));\n },\n },\n ...ifDefined('output', options.output),\n };\n}\n\nexport function typescriptContract(\n contract: Contract,\n output?: string,\n options?: TypeScriptContractSpecifierOptions,\n): ContractConfig {\n return {\n source: {\n load: async () =>\n ok(applySpecifierDefaultControlPolicy(contract, options?.defaultControlPolicy)),\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(\n contractPath: string,\n output?: string,\n options?: TypeScriptContractSpecifierOptions,\n): 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(applySpecifierDefaultControlPolicy(contract, options?.defaultControlPolicy));\n },\n },\n output: output ?? defaultOutputFromContractPath(contractPath),\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,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;AAMA,SAAgB,cAAc,SAIX;CACjB,OAAO;EACL,QAAQ,EACN,MAAM,YAAY;GAEhB,OAAO,GAAG,mCADI,+BAA+B;IAAE,QAAQ,QAAQ;IAAQ,QAAQ,CAAC;GAAE,CACjC,GAAG,QAAQ,oBAAoB,CAAC;EACnF,EACF;EACA,GAAG,UAAU,UAAU,QAAQ,MAAM;CACvC;AACF;AAEA,SAAgB,mBACd,UACA,QACA,SACgB;CAChB,OAAO;EACL,QAAQ,EACN,MAAM,YACJ,GAAG,mCAAmC,UAAU,SAAS,oBAAoB,CAAC,EAClF;EAGA,GAAG,UAAU,UAAU,MAAM;CAC/B;AACF;AAEA,SAAgB,2BACd,cACA,QACA,SACgB;CAChB,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,mCAAmC,UAAU,SAAS,oBAAoB,CAAC;GACvF;EACF;EACA,QAAQ,UAAU,8BAA8B,YAAY;CAC9D;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ColumnDefault, ColumnDefaultLiteralInputValue, Contract, ContractRelation, ExecutionMutationDefaultPhases, ExecutionMutationDefaultPhases as ExecutionMutationDefaultPhases$1, ExecutionMutationDefaultValue, NamespaceId, StorageHashBase } from "@prisma-next/contract/types";
|
|
1
|
+
import { ColumnDefault, ColumnDefaultLiteralInputValue, Contract, ContractRelation, ControlPolicy, ExecutionMutationDefaultPhases, ExecutionMutationDefaultPhases as ExecutionMutationDefaultPhases$1, ExecutionMutationDefaultValue, NamespaceId, StorageHashBase } from "@prisma-next/contract/types";
|
|
2
2
|
import { EntityHelpersFromNamespace, ExtractAuthoringNamespaceFromPack, ForeignKeyDefaultsState, MergeExtensionAuthoringNamespaces } from "@prisma-next/contract-authoring";
|
|
3
|
-
import { Namespace } from "@prisma-next/framework-components/ir";
|
|
3
|
+
import { Namespace, StorageType } from "@prisma-next/framework-components/ir";
|
|
4
4
|
import { IndexTypeRegistration } from "@prisma-next/sql-contract/index-types";
|
|
5
5
|
import { ContractWithTypeMaps, Index as Index$1, PostgresEnumStorageEntry, ReferentialAction, SqlNamespaceTablesInput, SqlStorage, StorageTypeInstance, TypeMaps } from "@prisma-next/sql-contract/types";
|
|
6
6
|
import { AuthoringArgumentDescriptor, AuthoringFieldPresetDescriptor, AuthoringTypeConstructorDescriptor } from "@prisma-next/framework-components/authoring";
|
|
@@ -227,6 +227,7 @@ type ModelAttributesSpec = {
|
|
|
227
227
|
};
|
|
228
228
|
type SqlStageSpec = {
|
|
229
229
|
readonly table?: string;
|
|
230
|
+
readonly control?: ControlPolicy;
|
|
230
231
|
readonly indexes?: readonly IndexConstraint[];
|
|
231
232
|
readonly foreignKeys?: readonly ForeignKeyConstraint[];
|
|
232
233
|
};
|
|
@@ -318,6 +319,7 @@ type ContractInput<Family extends FamilyPackRef<string> = FamilyPackRef<string>,
|
|
|
318
319
|
readonly naming?: NamingConfig;
|
|
319
320
|
readonly storageHash?: string;
|
|
320
321
|
readonly foreignKeyDefaults?: ForeignKeyDefaultsState;
|
|
322
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
321
323
|
/**
|
|
322
324
|
* Declared namespace coordinates the contract recognises. Per-model
|
|
323
325
|
* `namespace` references must reference an entry in this list (or the
|
|
@@ -513,7 +515,7 @@ type DefinitionNamespaces<Definition> = Definition extends {
|
|
|
513
515
|
} ? string[] extends Names ? never : readonly string[] extends Names ? never : Names[number] : never;
|
|
514
516
|
type DefinitionTypes<Definition> = Definition extends {
|
|
515
517
|
readonly types?: unknown;
|
|
516
|
-
} ? Present<Definition['types']> extends Record<string,
|
|
518
|
+
} ? Present<Definition['types']> extends Record<string, StorageType> ? Present<Definition['types']> : Record<never, never> : Record<never, never>;
|
|
517
519
|
type DefinitionTableNaming<Definition> = Definition extends {
|
|
518
520
|
readonly naming?: {
|
|
519
521
|
readonly tables?: infer Strategy extends string;
|
|
@@ -577,8 +579,8 @@ type DescriptorTypeParams<Descriptor> = Descriptor extends {
|
|
|
577
579
|
type DescriptorTypeRef<Descriptor> = Descriptor extends {
|
|
578
580
|
readonly typeRef: infer TypeRef extends string;
|
|
579
581
|
} ? TypeRef : undefined;
|
|
580
|
-
type LookupNamedStorageTypeKeyByValue<Definition, TypeRef extends
|
|
581
|
-
type ResolveNamedStorageTypeKey<Definition, TypeRef> = TypeRef extends string ? TypeRef : TypeRef extends
|
|
582
|
+
type LookupNamedStorageTypeKeyByValue<Definition, TypeRef extends StorageType> = { [TypeName in keyof DefinitionTypes<Definition> & string]: [TypeRef] extends [DefinitionTypes<Definition>[TypeName]] ? [DefinitionTypes<Definition>[TypeName]] extends [TypeRef] ? TypeName : never : never }[keyof DefinitionTypes<Definition> & string];
|
|
583
|
+
type ResolveNamedStorageTypeKey<Definition, TypeRef> = TypeRef extends string ? TypeRef : TypeRef extends StorageType ? [LookupNamedStorageTypeKeyByValue<Definition, TypeRef>] extends [never] ? string : LookupNamedStorageTypeKeyByValue<Definition, TypeRef> : never;
|
|
582
584
|
type ResolveNamedStorageType<Definition, TypeRef> = ResolveNamedStorageTypeKey<Definition, TypeRef> extends infer TypeName extends string ? TypeName extends keyof DefinitionTypes<Definition> ? DefinitionTypes<Definition>[TypeName] : StorageTypeInstance : StorageTypeInstance;
|
|
583
585
|
type ResolveFieldDescriptor<Definition, FieldState> = [FieldDescriptorOf<FieldState>] extends [never] ? ResolveNamedStorageType<Definition, FieldTypeRefOf<FieldState>> : FieldDescriptorOf<FieldState>;
|
|
584
586
|
type ResolveFieldColumnTypeRef<Definition, FieldState> = [FieldTypeRefOf<FieldState>] extends [never] ? DescriptorTypeRef<FieldDescriptorOf<FieldState>> : ResolveNamedStorageTypeKey<Definition, FieldTypeRefOf<FieldState>>;
|
|
@@ -663,7 +665,7 @@ type BuiltStorageTables<Definition> = { readonly [ModelName in ModelNames<Defini
|
|
|
663
665
|
readonly name?: ModelIdName<Definition, ModelName>;
|
|
664
666
|
};
|
|
665
667
|
} : Record<string, never>) };
|
|
666
|
-
type BuiltDocumentScopedTypes<Definition> = { readonly [K in keyof DefinitionTypes<Definition> as DefinitionTypes<Definition>[K] extends
|
|
668
|
+
type BuiltDocumentScopedTypes<Definition> = { readonly [K in keyof DefinitionTypes<Definition> as DefinitionTypes<Definition>[K] extends StorageTypeInstance ? K : never]: DefinitionTypes<Definition>[K] };
|
|
667
669
|
type BuiltDomain<Definition> = BuiltDocumentScopedTypes<Definition> extends Record<never, never> ? Record<string, never> : {
|
|
668
670
|
readonly __unbound__: {
|
|
669
671
|
readonly types: BuiltDocumentScopedTypes<Definition>;
|
|
@@ -676,13 +678,15 @@ type BuiltStorage<Definition> = {
|
|
|
676
678
|
readonly namespaces: { readonly [K in DefaultStorageNamespaceId<Definition>]: {
|
|
677
679
|
readonly id: K;
|
|
678
680
|
readonly kind: string;
|
|
679
|
-
readonly
|
|
680
|
-
|
|
681
|
+
readonly entries: {
|
|
682
|
+
readonly table: BuiltStorageTables<Definition>;
|
|
683
|
+
};
|
|
681
684
|
} } & { readonly [Ns in Exclude<DefinitionNamespaces<Definition>, DefaultStorageNamespaceId<Definition>>]: {
|
|
682
685
|
readonly id: Ns;
|
|
683
686
|
readonly kind: string;
|
|
684
|
-
readonly
|
|
685
|
-
|
|
687
|
+
readonly entries: {
|
|
688
|
+
readonly table: Record<never, never>;
|
|
689
|
+
};
|
|
686
690
|
} };
|
|
687
691
|
};
|
|
688
692
|
type FieldOutputType<Definition, ModelName extends ModelNames<Definition>, FieldName extends ModelFieldNames<Definition, ModelName>> = ModelStorageColumn<Definition, ModelName, FieldName> extends infer Col ? Col extends {
|
|
@@ -843,9 +847,19 @@ interface ModelNode {
|
|
|
843
847
|
readonly indexes?: readonly IndexNode[];
|
|
844
848
|
readonly foreignKeys?: readonly ForeignKeyNode[];
|
|
845
849
|
readonly relations?: readonly RelationNode[];
|
|
850
|
+
readonly control?: ControlPolicy;
|
|
851
|
+
/**
|
|
852
|
+
* Single-table-inheritance variants share their base model's storage table:
|
|
853
|
+
* the variant's columns are materialised onto the base `ModelNode`, and this
|
|
854
|
+
* model contributes a domain model but no storage table of its own. When set,
|
|
855
|
+
* the assembler builds the domain model but skips creating a (shadow) storage
|
|
856
|
+
* table and a root for this model — the base owns both.
|
|
857
|
+
*/
|
|
858
|
+
readonly sharesBaseTable?: boolean;
|
|
846
859
|
}
|
|
847
860
|
interface ContractDefinition {
|
|
848
861
|
readonly target: TargetPackRef<'sql', string>;
|
|
862
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
849
863
|
readonly extensionPacks?: Record<string, ExtensionPackRef<'sql', string>>;
|
|
850
864
|
readonly storageHash?: string;
|
|
851
865
|
readonly foreignKeyDefaults?: ForeignKeyDefaultsState;
|
|
@@ -853,7 +867,7 @@ interface ContractDefinition {
|
|
|
853
867
|
/**
|
|
854
868
|
* Enum types declared inside a named `namespace { enum … }` block,
|
|
855
869
|
* keyed first by namespace id then by type name. These are routed to
|
|
856
|
-
* `storage.namespaces[nsId].
|
|
870
|
+
* `storage.namespaces[nsId].entries.type` rather than the implicit fallback
|
|
857
871
|
* namespace used for top-level `storageTypes` enums.
|
|
858
872
|
*/
|
|
859
873
|
readonly namespaceTypes?: Readonly<Record<string, Readonly<Record<string, PostgresEnumStorageEntry>>>>;
|
|
@@ -866,8 +880,11 @@ interface ContractDefinition {
|
|
|
866
880
|
* Target-supplied factory that materialises a `Namespace` concretion
|
|
867
881
|
* for a declared namespace coordinate. Mirrors
|
|
868
882
|
* `ContractInput.createNamespace`.
|
|
883
|
+
*
|
|
884
|
+
* The optional second argument carries target-specific enum types for the
|
|
885
|
+
* namespace (e.g. postgres enum registrations keyed by type name).
|
|
869
886
|
*/
|
|
870
|
-
readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
|
|
887
|
+
readonly createNamespace?: (input: SqlNamespaceTablesInput, enumTypes?: Readonly<Record<string, PostgresEnumStorageEntry>>) => Namespace;
|
|
871
888
|
readonly models: readonly ModelNode[];
|
|
872
889
|
readonly valueObjects?: readonly ValueObjectNode[];
|
|
873
890
|
}
|
|
@@ -895,6 +912,7 @@ type ContractDefinition$1<Family extends FamilyPackRef<string>, Target extends T
|
|
|
895
912
|
readonly naming?: Naming;
|
|
896
913
|
readonly storageHash?: StorageHash;
|
|
897
914
|
readonly foreignKeyDefaults?: ForeignKeyDefaults;
|
|
915
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
898
916
|
readonly namespaces?: Namespaces;
|
|
899
917
|
readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
|
|
900
918
|
readonly types?: Types;
|
|
@@ -908,6 +926,7 @@ type ContractScaffold<Family extends FamilyPackRef<string>, Target extends Targe
|
|
|
908
926
|
readonly naming?: Naming;
|
|
909
927
|
readonly storageHash?: StorageHash;
|
|
910
928
|
readonly foreignKeyDefaults?: ForeignKeyDefaults;
|
|
929
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
911
930
|
readonly namespaces?: Namespaces;
|
|
912
931
|
readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
|
|
913
932
|
readonly types?: never;
|
|
@@ -918,8 +937,40 @@ type ContractFactory<Family extends FamilyPackRef<string>, Target extends Target
|
|
|
918
937
|
readonly types?: Types;
|
|
919
938
|
readonly models?: Models;
|
|
920
939
|
};
|
|
940
|
+
type BoundDefinitionInput<Types extends Record<string, StorageTypeInstance | PostgresEnumStorageEntry> = Record<never, never>, Models extends Record<string, ModelLike> = Record<never, never>, ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined = undefined, Naming extends ContractInput['naming'] | undefined = undefined, StorageHash extends string | undefined = undefined, ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined = undefined, Namespaces extends readonly string[] | undefined = undefined> = {
|
|
941
|
+
readonly extensionPacks?: ExtensionPacks;
|
|
942
|
+
readonly naming?: Naming;
|
|
943
|
+
readonly storageHash?: StorageHash;
|
|
944
|
+
readonly foreignKeyDefaults?: ForeignKeyDefaults;
|
|
945
|
+
readonly defaultControlPolicy?: ControlPolicy;
|
|
946
|
+
readonly namespaces?: Namespaces;
|
|
947
|
+
readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
|
|
948
|
+
readonly types?: Types;
|
|
949
|
+
readonly models?: Models;
|
|
950
|
+
readonly codecLookup?: CodecLookup;
|
|
951
|
+
};
|
|
952
|
+
type WithFamilyTarget<Input, F extends FamilyPackRef<string>, T extends TargetPackRef<'sql', string>> = Input & {
|
|
953
|
+
readonly family: F;
|
|
954
|
+
readonly target: T;
|
|
955
|
+
};
|
|
956
|
+
/**
|
|
957
|
+
* Shared builder that assembles a SqlContract with pre-bound family and target.
|
|
958
|
+
* Extension wrappers keep their own public overloads and delegate their impl body here;
|
|
959
|
+
* this is a plain overloaded function (not a factory returning an overloaded function)
|
|
960
|
+
* so no overloaded-function-return cast is needed.
|
|
961
|
+
*
|
|
962
|
+
* Overload 1: definition form (no factory).
|
|
963
|
+
*/
|
|
964
|
+
declare function buildBoundContract<const F extends FamilyPackRef<string>, const T extends TargetPackRef<'sql', string>, const Definition extends BoundDefinitionInput<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>, Record<string, ModelLike>, Record<string, ExtensionPackRef<'sql', string>> | undefined, ContractInput['naming'] | undefined, string | undefined, ForeignKeyDefaultsState | undefined, readonly string[] | undefined>>(family: F, target: T, definition: Definition, factory?: undefined): SqlContractResult<WithFamilyTarget<Definition, F, T>>;
|
|
965
|
+
/**
|
|
966
|
+
* Overload 2: factory form.
|
|
967
|
+
*/
|
|
968
|
+
declare function buildBoundContract<const F extends FamilyPackRef<string>, const T extends TargetPackRef<'sql', string>, const Definition extends BoundDefinitionInput<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>, Record<string, ModelLike>, Record<string, ExtensionPackRef<'sql', string>> | undefined, ContractInput['naming'] | undefined, string | undefined, ForeignKeyDefaultsState | undefined, readonly string[] | undefined>, const Built extends {
|
|
969
|
+
readonly types?: Record<string, StorageTypeInstance | PostgresEnumStorageEntry>;
|
|
970
|
+
readonly models?: Record<string, ModelLike>;
|
|
971
|
+
}>(family: F, target: T, definition: Definition, factory: (helpers: ComposedAuthoringHelpers<F, T, NonNullable<Definition['extensionPacks']>>) => Built): SqlContractResult<WithFamilyTarget<Definition & Built, F, T>>;
|
|
921
972
|
declare function defineContract<const Family extends FamilyPackRef<string>, const Target extends TargetPackRef<'sql', string>, const Types extends Record<string, StorageTypeInstance | PostgresEnumStorageEntry> = Record<never, never>, const Models extends Record<string, ModelLike> = Record<never, never>, const ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined = undefined, const Naming extends ContractInput['naming'] | undefined = undefined, const StorageHash extends string | undefined = undefined, const ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined = undefined, const Namespaces extends readonly string[] | undefined = undefined>(definition: ContractDefinition$1<Family, Target, Types, Models, ExtensionPacks, Naming, StorageHash, ForeignKeyDefaults, Namespaces>): SqlContractResult<ContractDefinition$1<Family, Target, Types, Models, ExtensionPacks, Naming, StorageHash, ForeignKeyDefaults, Namespaces>>;
|
|
922
973
|
declare function defineContract<const Family extends FamilyPackRef<string>, const Target extends TargetPackRef<'sql', string>, const Types extends Record<string, StorageTypeInstance | PostgresEnumStorageEntry> = Record<never, never>, const Models extends Record<string, ModelLike> = Record<never, never>, const ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined = undefined, const Naming extends ContractInput['naming'] | undefined = undefined, const StorageHash extends string | undefined = undefined, const ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined = undefined, const Namespaces extends readonly string[] | undefined = undefined>(definition: ContractScaffold<Family, Target, ExtensionPacks, Naming, StorageHash, ForeignKeyDefaults, Namespaces>, factory: ContractFactory<Family, Target, Types, Models, ExtensionPacks>): SqlContractResult<ContractDefinition$1<Family, Target, Types, Models, ExtensionPacks, Naming, StorageHash, ForeignKeyDefaults, Namespaces>>;
|
|
923
974
|
//#endregion
|
|
924
|
-
export { type ComposedAuthoringHelpers, type ContractDefinition, type ContractInput, type ContractModelBuilder, type FieldNode, type ForeignKeyNode, type IndexNode, type ModelLike, type ModelNode, type PrimaryKeyNode, type RelationNode, type ScalarFieldBuilder, type UniqueConstraintNode, buildSqlContractFromDefinition, defineContract, field, model, rel };
|
|
975
|
+
export { type ComposedAuthoringHelpers, type ContractDefinition, type ContractInput, type ContractModelBuilder, type FieldNode, type ForeignKeyNode, type IndexNode, type ModelLike, type ModelNode, type PrimaryKeyNode, type RelationNode, type ScalarFieldBuilder, type UniqueConstraintNode, buildBoundContract, buildSqlContractFromDefinition, defineContract, field, model, rel };
|
|
925
976
|
//# sourceMappingURL=contract-builder.d.mts.map
|