@prisma-next/sql-contract-ts 0.3.0-pr.99.6 → 0.4.0-dev.1

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.
Files changed (41) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +206 -73
  3. package/dist/config-types.d.mts +8 -0
  4. package/dist/config-types.d.mts.map +1 -0
  5. package/dist/config-types.mjs +14 -0
  6. package/dist/config-types.mjs.map +1 -0
  7. package/dist/contract-builder.d.mts +769 -0
  8. package/dist/contract-builder.d.mts.map +1 -0
  9. package/dist/contract-builder.mjs +1288 -0
  10. package/dist/contract-builder.mjs.map +1 -0
  11. package/package.json +19 -16
  12. package/schemas/data-contract-sql-v1.json +189 -23
  13. package/src/authoring-helper-runtime.ts +139 -0
  14. package/src/authoring-type-utils.ts +168 -0
  15. package/src/build-contract.ts +463 -0
  16. package/src/composed-authoring-helpers.ts +256 -0
  17. package/src/config-types.ts +11 -0
  18. package/src/contract-builder.ts +232 -551
  19. package/src/contract-definition.ts +103 -0
  20. package/src/contract-dsl.ts +1492 -0
  21. package/src/contract-lowering.ts +703 -0
  22. package/src/contract-types.ts +534 -0
  23. package/src/contract-warnings.ts +242 -0
  24. package/src/exports/config-types.ts +2 -0
  25. package/src/exports/contract-builder.ts +23 -2
  26. package/dist/chunk-HTNUNGA2.js +0 -346
  27. package/dist/chunk-HTNUNGA2.js.map +0 -1
  28. package/dist/contract-builder.d.ts +0 -101
  29. package/dist/contract-builder.d.ts.map +0 -1
  30. package/dist/contract.d.ts +0 -50
  31. package/dist/contract.d.ts.map +0 -1
  32. package/dist/exports/contract-builder.d.ts +0 -3
  33. package/dist/exports/contract-builder.d.ts.map +0 -1
  34. package/dist/exports/contract-builder.js +0 -231
  35. package/dist/exports/contract-builder.js.map +0 -1
  36. package/dist/exports/contract.d.ts +0 -2
  37. package/dist/exports/contract.d.ts.map +0 -1
  38. package/dist/exports/contract.js +0 -9
  39. package/dist/exports/contract.js.map +0 -1
  40. package/src/contract.ts +0 -582
  41. package/src/exports/contract.ts +0 -1
@@ -0,0 +1,242 @@
1
+ import type { StorageTypeInstance } from '@prisma-next/sql-contract/types';
2
+ import {
3
+ type ContractModelBuilder,
4
+ type ModelAttributesSpec,
5
+ normalizeRelationFieldNames,
6
+ type RelationBuilder,
7
+ type RelationState,
8
+ type ScalarFieldBuilder,
9
+ type SqlStageSpec,
10
+ } from './contract-dsl';
11
+
12
+ type RuntimeModel = ContractModelBuilder<
13
+ string | undefined,
14
+ Record<string, ScalarFieldBuilder>,
15
+ Record<string, RelationBuilder<RelationState>>,
16
+ ModelAttributesSpec | undefined,
17
+ SqlStageSpec | undefined
18
+ >;
19
+
20
+ type RuntimeModelSpec = {
21
+ readonly modelName: string;
22
+ readonly tableName: string;
23
+ readonly relations: Record<string, RelationBuilder<RelationState>>;
24
+ readonly sqlSpec: SqlStageSpec | undefined;
25
+ };
26
+
27
+ type RuntimeCollection = {
28
+ readonly storageTypes: Record<string, StorageTypeInstance>;
29
+ readonly models: Record<string, RuntimeModel>;
30
+ readonly modelSpecs: ReadonlyMap<string, RuntimeModelSpec>;
31
+ };
32
+
33
+ function hasNamedModelToken(models: Record<string, RuntimeModel>, modelName: string): boolean {
34
+ return models[modelName]?.stageOne.modelName === modelName;
35
+ }
36
+
37
+ function formatFieldSelection(fieldNames: readonly string[]): string {
38
+ if (fieldNames.length === 1) {
39
+ return `'${fieldNames[0]}'`;
40
+ }
41
+
42
+ return `[${fieldNames.map((fieldName) => `'${fieldName}'`).join(', ')}]`;
43
+ }
44
+
45
+ function formatTokenFieldSelection(modelName: string, fieldNames: readonly string[]): string {
46
+ if (fieldNames.length === 1) {
47
+ return `${modelName}.refs.${fieldNames[0]}`;
48
+ }
49
+
50
+ return `[${fieldNames.map((fieldName) => `${modelName}.refs.${fieldName}`).join(', ')}]`;
51
+ }
52
+
53
+ function formatConstraintsRefCall(modelName: string, fieldNames: readonly string[]): string {
54
+ if (fieldNames.length === 1) {
55
+ return `constraints.ref('${modelName}', '${fieldNames[0]}')`;
56
+ }
57
+
58
+ return `[${fieldNames
59
+ .map((fieldName) => `constraints.ref('${modelName}', '${fieldName}')`)
60
+ .join(', ')}]`;
61
+ }
62
+
63
+ function formatRelationModelDisplay(
64
+ relationModel:
65
+ | RelationState['toModel']
66
+ | Extract<RelationState, { kind: 'manyToMany' }>['through'],
67
+ ): string {
68
+ if (relationModel.kind === 'lazyRelationModelName') {
69
+ return `() => ${relationModel.resolve()}`;
70
+ }
71
+
72
+ return relationModel.source === 'string'
73
+ ? `'${relationModel.modelName}'`
74
+ : relationModel.modelName;
75
+ }
76
+
77
+ function formatRelationCall(relation: RelationState, targetModelDisplay: string): string {
78
+ if (relation.kind === 'belongsTo') {
79
+ const from = formatFieldSelection(normalizeRelationFieldNames(relation.from));
80
+ const to = formatFieldSelection(normalizeRelationFieldNames(relation.to));
81
+ return `rel.belongsTo(${targetModelDisplay}, { from: ${from}, to: ${to} })`;
82
+ }
83
+
84
+ if (relation.kind === 'hasMany' || relation.kind === 'hasOne') {
85
+ const by = formatFieldSelection(normalizeRelationFieldNames(relation.by));
86
+ return `rel.${relation.kind}(${targetModelDisplay}, { by: ${by} })`;
87
+ }
88
+
89
+ const throughDisplay = formatRelationModelDisplay(relation.through);
90
+ const from = formatFieldSelection(normalizeRelationFieldNames(relation.from));
91
+ const to = formatFieldSelection(normalizeRelationFieldNames(relation.to));
92
+ return `rel.manyToMany(${targetModelDisplay}, { through: ${throughDisplay}, from: ${from}, to: ${to} })`;
93
+ }
94
+
95
+ function formatManyToManyCallWithThrough(
96
+ relation: Extract<RelationState, { kind: 'manyToMany' }>,
97
+ throughDisplay: string,
98
+ ): string {
99
+ const targetDisplay = formatRelationModelDisplay(relation.toModel);
100
+ const from = formatFieldSelection(normalizeRelationFieldNames(relation.from));
101
+ const to = formatFieldSelection(normalizeRelationFieldNames(relation.to));
102
+ return `rel.manyToMany(${targetDisplay}, { through: ${throughDisplay}, from: ${from}, to: ${to} })`;
103
+ }
104
+
105
+ const WARNING_BATCH_THRESHOLD = 5;
106
+
107
+ function flushWarnings(warnings: readonly string[]): void {
108
+ if (warnings.length === 0) {
109
+ return;
110
+ }
111
+
112
+ if (warnings.length <= WARNING_BATCH_THRESHOLD) {
113
+ for (const message of warnings) {
114
+ process.emitWarning(message, { code: 'PN_CONTRACT_TYPED_FALLBACK_AVAILABLE' });
115
+ }
116
+ return;
117
+ }
118
+
119
+ process.emitWarning(
120
+ `${warnings.length} contract references use string fallbacks where typed alternatives are available. ` +
121
+ 'Use named model tokens and typed storage type refs for autocomplete and type safety.\n' +
122
+ warnings.map((w) => ` - ${w}`).join('\n'),
123
+ { code: 'PN_CONTRACT_TYPED_FALLBACK_AVAILABLE' },
124
+ );
125
+ }
126
+
127
+ function formatFallbackWarning(location: string, current: string, suggested: string): string {
128
+ return (
129
+ `Contract ${location} uses ${current}. ` +
130
+ `Use ${suggested} when the named model token is available in the same contract to keep typed relation targets and model refs.`
131
+ );
132
+ }
133
+
134
+ export function emitTypedNamedTypeFallbackWarnings(
135
+ models: Record<string, RuntimeModel>,
136
+ storageTypes: Record<string, StorageTypeInstance>,
137
+ ): void {
138
+ const warnings: string[] = [];
139
+ const warnedFields = new Set<string>();
140
+
141
+ for (const [modelName, modelDefinition] of Object.entries(models)) {
142
+ for (const [fieldName, fieldBuilder] of Object.entries(modelDefinition.stageOne.fields)) {
143
+ const fieldState = fieldBuilder.build();
144
+ if (typeof fieldState.typeRef !== 'string' || !(fieldState.typeRef in storageTypes)) {
145
+ continue;
146
+ }
147
+
148
+ const warningKey = `${modelName}.${fieldName}`;
149
+ if (warnedFields.has(warningKey)) {
150
+ continue;
151
+ }
152
+ warnedFields.add(warningKey);
153
+
154
+ warnings.push(
155
+ `Contract field "${modelName}.${fieldName}" uses field.namedType('${fieldState.typeRef}'). ` +
156
+ `Use field.namedType(types.${fieldState.typeRef}) when the storage type is declared in the same contract to keep autocomplete and typed local refs.`,
157
+ );
158
+ }
159
+ }
160
+
161
+ flushWarnings(warnings);
162
+ }
163
+
164
+ export function emitTypedCrossModelFallbackWarnings(collection: RuntimeCollection): void {
165
+ const warnings: string[] = [];
166
+ const warnedKeys = new Set<string>();
167
+
168
+ for (const spec of collection.modelSpecs.values()) {
169
+ for (const [relationName, relationBuilder] of Object.entries(spec.relations)) {
170
+ const relation = relationBuilder.build();
171
+
172
+ if (
173
+ relation.toModel.kind === 'relationModelName' &&
174
+ relation.toModel.source === 'string' &&
175
+ hasNamedModelToken(collection.models, relation.toModel.modelName)
176
+ ) {
177
+ const warningKey = `${spec.modelName}.${relationName}.toModel`;
178
+ if (!warnedKeys.has(warningKey)) {
179
+ warnedKeys.add(warningKey);
180
+
181
+ const current = formatRelationCall(relation, `'${relation.toModel.modelName}'`);
182
+ const suggested = formatRelationCall(relation, relation.toModel.modelName);
183
+ warnings.push(
184
+ formatFallbackWarning(
185
+ `relation "${spec.modelName}.${relationName}"`,
186
+ current,
187
+ suggested,
188
+ ),
189
+ );
190
+ }
191
+ }
192
+
193
+ if (
194
+ relation.kind === 'manyToMany' &&
195
+ relation.through.kind === 'relationModelName' &&
196
+ relation.through.source === 'string' &&
197
+ hasNamedModelToken(collection.models, relation.through.modelName)
198
+ ) {
199
+ const warningKey = `${spec.modelName}.${relationName}.through`;
200
+ if (!warnedKeys.has(warningKey)) {
201
+ warnedKeys.add(warningKey);
202
+
203
+ const current = formatManyToManyCallWithThrough(
204
+ relation,
205
+ `'${relation.through.modelName}'`,
206
+ );
207
+ const suggested = formatManyToManyCallWithThrough(relation, relation.through.modelName);
208
+ warnings.push(
209
+ formatFallbackWarning(
210
+ `relation "${spec.modelName}.${relationName}"`,
211
+ current,
212
+ suggested,
213
+ ),
214
+ );
215
+ }
216
+ }
217
+ }
218
+
219
+ for (const [foreignKeyIndex, foreignKey] of (spec.sqlSpec?.foreignKeys ?? []).entries()) {
220
+ if (
221
+ foreignKey.targetSource !== 'string' ||
222
+ !hasNamedModelToken(collection.models, foreignKey.targetModel)
223
+ ) {
224
+ continue;
225
+ }
226
+
227
+ const warningKey = `${spec.modelName}.sql.foreignKeys.${foreignKeyIndex}`;
228
+ if (warnedKeys.has(warningKey)) {
229
+ continue;
230
+ }
231
+ warnedKeys.add(warningKey);
232
+
233
+ const current = formatConstraintsRefCall(foreignKey.targetModel, foreignKey.targetFields);
234
+ const suggested = formatTokenFieldSelection(foreignKey.targetModel, foreignKey.targetFields);
235
+ warnings.push(
236
+ formatFallbackWarning(`model "${spec.modelName}"`, `${current} in .sql(...)`, suggested),
237
+ );
238
+ }
239
+ }
240
+
241
+ flushWarnings(warnings);
242
+ }
@@ -0,0 +1,2 @@
1
+ export type { ContractConfig } from '@prisma-next/config/config-types';
2
+ export { typescriptContract } from '../config-types';
@@ -1,2 +1,23 @@
1
- export type { ColumnBuilder } from '../contract-builder';
2
- export { defineContract } from '../contract-builder';
1
+ export type {
2
+ ComposedAuthoringHelpers,
3
+ ContractInput,
4
+ ContractModelBuilder,
5
+ ScalarFieldBuilder,
6
+ } from '../contract-builder';
7
+ export {
8
+ buildSqlContractFromDefinition,
9
+ defineContract,
10
+ field,
11
+ model,
12
+ rel,
13
+ } from '../contract-builder';
14
+ export type {
15
+ ContractDefinition,
16
+ FieldNode,
17
+ ForeignKeyNode,
18
+ IndexNode,
19
+ ModelNode,
20
+ PrimaryKeyNode,
21
+ RelationNode,
22
+ UniqueConstraintNode,
23
+ } from '../contract-definition';
@@ -1,346 +0,0 @@
1
- // src/contract.ts
2
- import { type } from "arktype";
3
- var StorageColumnSchema = type.declare().type({
4
- nativeType: "string",
5
- codecId: "string",
6
- nullable: "boolean",
7
- "typeParams?": "Record<string, unknown>",
8
- "typeRef?": "string"
9
- });
10
- var StorageTypeInstanceSchema = type.declare().type({
11
- codecId: "string",
12
- nativeType: "string",
13
- typeParams: "Record<string, unknown>"
14
- });
15
- var PrimaryKeySchema = type.declare().type({
16
- columns: type.string.array().readonly(),
17
- "name?": "string"
18
- });
19
- var UniqueConstraintSchema = type.declare().type({
20
- columns: type.string.array().readonly(),
21
- "name?": "string"
22
- });
23
- var IndexSchema = type.declare().type({
24
- columns: type.string.array().readonly(),
25
- "name?": "string"
26
- });
27
- var ForeignKeyReferencesSchema = type.declare().type({
28
- table: "string",
29
- columns: type.string.array().readonly()
30
- });
31
- var ForeignKeySchema = type.declare().type({
32
- columns: type.string.array().readonly(),
33
- references: ForeignKeyReferencesSchema,
34
- "name?": "string"
35
- });
36
- var StorageTableSchema = type.declare().type({
37
- columns: type({ "[string]": StorageColumnSchema }),
38
- "primaryKey?": PrimaryKeySchema,
39
- uniques: UniqueConstraintSchema.array().readonly(),
40
- indexes: IndexSchema.array().readonly(),
41
- foreignKeys: ForeignKeySchema.array().readonly()
42
- });
43
- var StorageSchema = type.declare().type({
44
- tables: type({ "[string]": StorageTableSchema }),
45
- "types?": type({ "[string]": StorageTypeInstanceSchema })
46
- });
47
- var ModelFieldSchema = type.declare().type({
48
- column: "string"
49
- });
50
- var ModelStorageSchema = type.declare().type({
51
- table: "string"
52
- });
53
- var ModelSchema = type.declare().type({
54
- storage: ModelStorageSchema,
55
- fields: type({ "[string]": ModelFieldSchema }),
56
- relations: type({ "[string]": "unknown" })
57
- });
58
- var SqlContractSchema = type({
59
- "schemaVersion?": "'1'",
60
- target: "string",
61
- targetFamily: "'sql'",
62
- coreHash: "string",
63
- "profileHash?": "string",
64
- "capabilities?": "Record<string, Record<string, boolean>>",
65
- "extensionPacks?": "Record<string, unknown>",
66
- "meta?": "Record<string, unknown>",
67
- "sources?": "Record<string, unknown>",
68
- models: type({ "[string]": ModelSchema }),
69
- storage: StorageSchema
70
- });
71
- function validateContractStructure(value) {
72
- const rawValue = value;
73
- if (rawValue.targetFamily !== void 0 && rawValue.targetFamily !== "sql") {
74
- throw new Error(`Unsupported target family: ${rawValue.targetFamily}`);
75
- }
76
- const contractResult = SqlContractSchema(value);
77
- if (contractResult instanceof type.errors) {
78
- const messages = contractResult.map((p) => p.message).join("; ");
79
- throw new Error(`Contract structural validation failed: ${messages}`);
80
- }
81
- return contractResult;
82
- }
83
- function computeMappings(models, _storage, existingMappings) {
84
- const modelToTable = {};
85
- const tableToModel = {};
86
- const fieldToColumn = {};
87
- const columnToField = {};
88
- for (const [modelName, model] of Object.entries(models)) {
89
- const tableName = model.storage.table;
90
- modelToTable[modelName] = tableName;
91
- tableToModel[tableName] = modelName;
92
- const modelFieldToColumn = {};
93
- for (const [fieldName, field] of Object.entries(model.fields)) {
94
- const columnName = field.column;
95
- modelFieldToColumn[fieldName] = columnName;
96
- if (!columnToField[tableName]) {
97
- columnToField[tableName] = {};
98
- }
99
- columnToField[tableName][columnName] = fieldName;
100
- }
101
- fieldToColumn[modelName] = modelFieldToColumn;
102
- }
103
- return {
104
- modelToTable: existingMappings?.modelToTable ?? modelToTable,
105
- tableToModel: existingMappings?.tableToModel ?? tableToModel,
106
- fieldToColumn: existingMappings?.fieldToColumn ?? fieldToColumn,
107
- columnToField: existingMappings?.columnToField ?? columnToField,
108
- codecTypes: existingMappings?.codecTypes ?? {},
109
- operationTypes: existingMappings?.operationTypes ?? {}
110
- };
111
- }
112
- function validateContractLogic(structurallyValidatedContract) {
113
- const { storage, models } = structurallyValidatedContract;
114
- const tableNames = new Set(Object.keys(storage.tables));
115
- const typeInstanceNames = new Set(Object.keys(storage.types ?? {}));
116
- if (storage.types) {
117
- for (const [typeName, typeInstance] of Object.entries(storage.types)) {
118
- if (Array.isArray(typeInstance.typeParams)) {
119
- throw new Error(
120
- `Type instance "${typeName}" has invalid typeParams: must be a plain object, not an array`
121
- );
122
- }
123
- }
124
- }
125
- for (const [tableName, table] of Object.entries(storage.tables)) {
126
- for (const [columnName, column] of Object.entries(table.columns)) {
127
- if (column.typeParams !== void 0 && column.typeRef !== void 0) {
128
- throw new Error(
129
- `Column "${columnName}" in table "${tableName}" has both typeParams and typeRef; these are mutually exclusive`
130
- );
131
- }
132
- if (column.typeParams !== void 0 && Array.isArray(column.typeParams)) {
133
- throw new Error(
134
- `Column "${columnName}" in table "${tableName}" has invalid typeParams: must be a plain object, not an array`
135
- );
136
- }
137
- if (column.typeRef !== void 0 && !typeInstanceNames.has(column.typeRef)) {
138
- throw new Error(
139
- `Column "${columnName}" in table "${tableName}" references non-existent type instance "${column.typeRef}" (not found in storage.types)`
140
- );
141
- }
142
- }
143
- }
144
- for (const [modelName, modelUnknown] of Object.entries(models)) {
145
- const model = modelUnknown;
146
- if (!model.storage?.table) {
147
- throw new Error(`Model "${modelName}" is missing storage.table`);
148
- }
149
- const tableName = model.storage.table;
150
- if (!tableNames.has(tableName)) {
151
- throw new Error(`Model "${modelName}" references non-existent table "${tableName}"`);
152
- }
153
- const table = storage.tables[tableName];
154
- if (!table) {
155
- throw new Error(`Model "${modelName}" references non-existent table "${tableName}"`);
156
- }
157
- if (!table.primaryKey) {
158
- throw new Error(`Model "${modelName}" table "${tableName}" is missing a primary key`);
159
- }
160
- const columnNames = new Set(Object.keys(table.columns));
161
- if (!model.fields) {
162
- throw new Error(`Model "${modelName}" is missing fields`);
163
- }
164
- for (const [fieldName, fieldUnknown] of Object.entries(model.fields)) {
165
- const field = fieldUnknown;
166
- if (!field.column) {
167
- throw new Error(`Model "${modelName}" field "${fieldName}" is missing column property`);
168
- }
169
- if (!columnNames.has(field.column)) {
170
- throw new Error(
171
- `Model "${modelName}" field "${fieldName}" references non-existent column "${field.column}" in table "${tableName}"`
172
- );
173
- }
174
- }
175
- if (model.relations) {
176
- for (const [relationName, relation] of Object.entries(model.relations)) {
177
- if (typeof relation === "object" && relation !== null && "on" in relation && "to" in relation) {
178
- const on = relation.on;
179
- const cardinality = relation.cardinality;
180
- if (on.parentCols && on.childCols) {
181
- if (cardinality === "1:N") {
182
- continue;
183
- }
184
- const hasMatchingFk = table.foreignKeys?.some((fk) => {
185
- return fk.columns.length === on.childCols?.length && fk.columns.every((col, i) => col === on.childCols?.[i]) && fk.references.table && fk.references.columns.length === on.parentCols?.length && fk.references.columns.every((col, i) => col === on.parentCols?.[i]);
186
- });
187
- if (!hasMatchingFk) {
188
- throw new Error(
189
- `Model "${modelName}" relation "${relationName}" does not have a corresponding foreign key in table "${tableName}"`
190
- );
191
- }
192
- }
193
- }
194
- }
195
- }
196
- }
197
- for (const [tableName, table] of Object.entries(storage.tables)) {
198
- const columnNames = new Set(Object.keys(table.columns));
199
- if (table.primaryKey) {
200
- for (const colName of table.primaryKey.columns) {
201
- if (!columnNames.has(colName)) {
202
- throw new Error(
203
- `Table "${tableName}" primaryKey references non-existent column "${colName}"`
204
- );
205
- }
206
- }
207
- }
208
- for (const unique of table.uniques) {
209
- for (const colName of unique.columns) {
210
- if (!columnNames.has(colName)) {
211
- throw new Error(
212
- `Table "${tableName}" unique constraint references non-existent column "${colName}"`
213
- );
214
- }
215
- }
216
- }
217
- for (const index of table.indexes) {
218
- for (const colName of index.columns) {
219
- if (!columnNames.has(colName)) {
220
- throw new Error(`Table "${tableName}" index references non-existent column "${colName}"`);
221
- }
222
- }
223
- }
224
- for (const fk of table.foreignKeys) {
225
- for (const colName of fk.columns) {
226
- if (!columnNames.has(colName)) {
227
- throw new Error(
228
- `Table "${tableName}" foreignKey references non-existent column "${colName}"`
229
- );
230
- }
231
- }
232
- if (!tableNames.has(fk.references.table)) {
233
- throw new Error(
234
- `Table "${tableName}" foreignKey references non-existent table "${fk.references.table}"`
235
- );
236
- }
237
- const referencedTable = storage.tables[fk.references.table];
238
- if (!referencedTable) {
239
- throw new Error(
240
- `Table "${tableName}" foreignKey references non-existent table "${fk.references.table}"`
241
- );
242
- }
243
- const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
244
- for (const colName of fk.references.columns) {
245
- if (!referencedColumnNames.has(colName)) {
246
- throw new Error(
247
- `Table "${tableName}" foreignKey references non-existent column "${colName}" in table "${fk.references.table}"`
248
- );
249
- }
250
- }
251
- if (fk.columns.length !== fk.references.columns.length) {
252
- throw new Error(
253
- `Table "${tableName}" foreignKey column count (${fk.columns.length}) does not match referenced column count (${fk.references.columns.length})`
254
- );
255
- }
256
- }
257
- }
258
- }
259
- function normalizeContract(contract) {
260
- const contractObj = contract;
261
- let normalizedStorage = contractObj["storage"];
262
- if (normalizedStorage && typeof normalizedStorage === "object" && normalizedStorage !== null) {
263
- const storage = normalizedStorage;
264
- const tables = storage["tables"];
265
- if (tables) {
266
- const normalizedTables = {};
267
- for (const [tableName, table] of Object.entries(tables)) {
268
- const tableObj = table;
269
- const columns = tableObj["columns"];
270
- if (columns) {
271
- const normalizedColumns = {};
272
- for (const [columnName, column] of Object.entries(columns)) {
273
- const columnObj = column;
274
- const normalizedColumn = {
275
- ...columnObj,
276
- nullable: columnObj["nullable"] ?? false
277
- };
278
- normalizedColumns[columnName] = normalizedColumn;
279
- }
280
- normalizedTables[tableName] = {
281
- ...tableObj,
282
- columns: normalizedColumns,
283
- uniques: tableObj["uniques"] ?? [],
284
- indexes: tableObj["indexes"] ?? [],
285
- foreignKeys: tableObj["foreignKeys"] ?? []
286
- };
287
- } else {
288
- normalizedTables[tableName] = tableObj;
289
- }
290
- }
291
- normalizedStorage = {
292
- ...storage,
293
- tables: normalizedTables
294
- };
295
- }
296
- }
297
- let normalizedModels = contractObj["models"];
298
- if (normalizedModels && typeof normalizedModels === "object" && normalizedModels !== null) {
299
- const models = normalizedModels;
300
- const normalizedModelsObj = {};
301
- for (const [modelName, model] of Object.entries(models)) {
302
- const modelObj = model;
303
- normalizedModelsObj[modelName] = {
304
- ...modelObj,
305
- relations: modelObj["relations"] ?? {}
306
- };
307
- }
308
- normalizedModels = normalizedModelsObj;
309
- }
310
- return {
311
- ...contractObj,
312
- models: normalizedModels,
313
- relations: contractObj["relations"] ?? {},
314
- storage: normalizedStorage,
315
- extensionPacks: contractObj["extensionPacks"] ?? {},
316
- capabilities: contractObj["capabilities"] ?? {},
317
- meta: contractObj["meta"] ?? {},
318
- sources: contractObj["sources"] ?? {}
319
- };
320
- }
321
- function validateContract(value) {
322
- const normalized = normalizeContract(value);
323
- const structurallyValid = validateContractStructure(normalized);
324
- const contractForValidation = structurallyValid;
325
- validateContractLogic(contractForValidation);
326
- const existingMappings = contractForValidation.mappings;
327
- const mappings = computeMappings(
328
- contractForValidation.models,
329
- contractForValidation.storage,
330
- existingMappings
331
- );
332
- const contractWithMappings = {
333
- ...structurallyValid,
334
- models: contractForValidation.models,
335
- relations: contractForValidation.relations,
336
- storage: contractForValidation.storage,
337
- mappings
338
- };
339
- return contractWithMappings;
340
- }
341
-
342
- export {
343
- computeMappings,
344
- validateContract
345
- };
346
- //# sourceMappingURL=chunk-HTNUNGA2.js.map