@prisma-next/sql-contract 0.3.0-dev.131 → 0.3.0-dev.132

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/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@prisma-next/sql-contract",
3
- "version": "0.3.0-dev.131",
3
+ "version": "0.3.0-dev.132",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "SQL contract types, validators, and IR factories for Prisma Next",
7
7
  "dependencies": {
8
8
  "arktype": "^2.1.25",
9
- "@prisma-next/contract": "0.3.0-dev.131"
9
+ "@prisma-next/contract": "0.3.0-dev.132"
10
10
  },
11
11
  "devDependencies": {
12
12
  "tsdown": "0.18.4",
13
13
  "typescript": "5.9.3",
14
14
  "vitest": "4.0.17",
15
+ "@prisma-next/test-utils": "0.0.1",
15
16
  "@prisma-next/tsconfig": "0.0.0",
16
- "@prisma-next/tsdown": "0.0.0",
17
- "@prisma-next/test-utils": "0.0.1"
17
+ "@prisma-next/tsdown": "0.0.0"
18
18
  },
19
19
  "files": [
20
20
  "dist",
package/src/construct.ts CHANGED
@@ -1,158 +1,4 @@
1
- import type { ModelDefinition, SqlContract, SqlMappings, SqlStorage } from './types';
2
-
3
- type ResolvedMappings = {
4
- modelToTable: Record<string, string>;
5
- tableToModel: Record<string, string>;
6
- fieldToColumn: Record<string, Record<string, string>>;
7
- columnToField: Record<string, Record<string, string>>;
8
- };
9
-
10
- function computeDefaultMappings(models: Record<string, ModelDefinition>): ResolvedMappings {
11
- const modelToTable: Record<string, string> = {};
12
- const tableToModel: Record<string, string> = {};
13
- const fieldToColumn: Record<string, Record<string, string>> = {};
14
- const columnToField: Record<string, Record<string, string>> = {};
15
-
16
- for (const [modelName, model] of Object.entries(models)) {
17
- const tableName = model.storage.table;
18
- modelToTable[modelName] = tableName;
19
- tableToModel[tableName] = modelName;
20
-
21
- const modelFieldToColumn: Record<string, string> = {};
22
- for (const [fieldName, field] of Object.entries(model.fields)) {
23
- const columnName = field.column;
24
- modelFieldToColumn[fieldName] = columnName;
25
- if (!columnToField[tableName]) {
26
- columnToField[tableName] = {};
27
- }
28
- columnToField[tableName][columnName] = fieldName;
29
- }
30
-
31
- fieldToColumn[modelName] = modelFieldToColumn;
32
- }
33
-
34
- return {
35
- modelToTable,
36
- tableToModel,
37
- fieldToColumn,
38
- columnToField,
39
- };
40
- }
41
-
42
- function assertInverseModelMappings(
43
- modelToTable: Record<string, string>,
44
- tableToModel: Record<string, string>,
45
- ): void {
46
- for (const [model, table] of Object.entries(modelToTable)) {
47
- if (tableToModel[table] !== model) {
48
- throw new Error(
49
- `Mappings override mismatch: modelToTable.${model}="${table}" is not mirrored in tableToModel`,
50
- );
51
- }
52
- }
53
- for (const [table, model] of Object.entries(tableToModel)) {
54
- if (modelToTable[model] !== table) {
55
- throw new Error(
56
- `Mappings override mismatch: tableToModel.${table}="${model}" is not mirrored in modelToTable`,
57
- );
58
- }
59
- }
60
- }
61
-
62
- function assertInverseFieldMappings(
63
- fieldToColumn: Record<string, Record<string, string>>,
64
- columnToField: Record<string, Record<string, string>>,
65
- modelToTable: Record<string, string>,
66
- tableToModel: Record<string, string>,
67
- ): void {
68
- for (const [model, fields] of Object.entries(fieldToColumn)) {
69
- const table = modelToTable[model];
70
- if (!table) {
71
- throw new Error(
72
- `Mappings override mismatch: fieldToColumn references unknown model "${model}"`,
73
- );
74
- }
75
- const reverseFields = columnToField[table];
76
- if (!reverseFields) {
77
- throw new Error(
78
- `Mappings override mismatch: columnToField is missing table "${table}" for model "${model}"`,
79
- );
80
- }
81
- for (const [field, column] of Object.entries(fields)) {
82
- if (reverseFields[column] !== field) {
83
- throw new Error(
84
- `Mappings override mismatch: fieldToColumn.${model}.${field}="${column}" is not mirrored in columnToField.${table}`,
85
- );
86
- }
87
- }
88
- }
89
-
90
- for (const [table, columns] of Object.entries(columnToField)) {
91
- const model = tableToModel[table];
92
- if (!model) {
93
- throw new Error(
94
- `Mappings override mismatch: columnToField references unknown table "${table}"`,
95
- );
96
- }
97
- const forwardFields = fieldToColumn[model];
98
- if (!forwardFields) {
99
- throw new Error(
100
- `Mappings override mismatch: fieldToColumn is missing model "${model}" for table "${table}"`,
101
- );
102
- }
103
- for (const [column, field] of Object.entries(columns)) {
104
- if (forwardFields[field] !== column) {
105
- throw new Error(
106
- `Mappings override mismatch: columnToField.${table}.${column}="${field}" is not mirrored in fieldToColumn.${model}`,
107
- );
108
- }
109
- }
110
- }
111
- }
112
-
113
- function mergeMappings(
114
- defaults: ResolvedMappings,
115
- existingMappings?: Partial<SqlMappings>,
116
- ): ResolvedMappings {
117
- const hasModelToTable = existingMappings?.modelToTable !== undefined;
118
- const hasTableToModel = existingMappings?.tableToModel !== undefined;
119
- if (hasModelToTable !== hasTableToModel) {
120
- throw new Error(
121
- 'Mappings override mismatch: modelToTable and tableToModel must be provided together',
122
- );
123
- }
124
-
125
- const hasFieldToColumn = existingMappings?.fieldToColumn !== undefined;
126
- const hasColumnToField = existingMappings?.columnToField !== undefined;
127
- if (hasFieldToColumn !== hasColumnToField) {
128
- throw new Error(
129
- 'Mappings override mismatch: fieldToColumn and columnToField must be provided together',
130
- );
131
- }
132
-
133
- const modelToTable: Record<string, string> = hasModelToTable
134
- ? (existingMappings?.modelToTable ?? {})
135
- : defaults.modelToTable;
136
- const tableToModel: Record<string, string> = hasTableToModel
137
- ? (existingMappings?.tableToModel ?? {})
138
- : defaults.tableToModel;
139
- assertInverseModelMappings(modelToTable, tableToModel);
140
-
141
- const fieldToColumn: Record<string, Record<string, string>> = hasFieldToColumn
142
- ? (existingMappings?.fieldToColumn ?? {})
143
- : defaults.fieldToColumn;
144
- const columnToField: Record<string, Record<string, string>> = hasColumnToField
145
- ? (existingMappings?.columnToField ?? {})
146
- : defaults.columnToField;
147
- assertInverseFieldMappings(fieldToColumn, columnToField, modelToTable, tableToModel);
148
-
149
- return {
150
- modelToTable,
151
- tableToModel,
152
- fieldToColumn,
153
- columnToField,
154
- };
155
- }
1
+ import type { SqlContract, SqlStorage } from './types';
156
2
 
157
3
  type ValidatedContractInput = SqlContract<SqlStorage> & { _generated?: unknown };
158
4
 
@@ -165,17 +11,6 @@ function stripGenerated(obj: ValidatedContractInput): Omit<ValidatedContractInpu
165
11
  export function constructContract<TContract extends SqlContract<SqlStorage>>(
166
12
  input: ValidatedContractInput,
167
13
  ): TContract {
168
- const existingMappings = (input as { mappings?: Partial<SqlMappings> }).mappings;
169
- const defaultMappings = computeDefaultMappings(input.models as Record<string, ModelDefinition>);
170
- const mappings = mergeMappings(defaultMappings, existingMappings);
171
-
172
14
  const stripped = stripGenerated(input);
173
-
174
- const contractWithMappings = {
175
- ...stripped,
176
- mappings,
177
- roots: stripped.roots,
178
- };
179
-
180
- return contractWithMappings as TContract;
15
+ return stripped as TContract;
181
16
  }
@@ -9,9 +9,6 @@ export type {
9
9
  ForeignKeyOptions,
10
10
  ForeignKeyReferences,
11
11
  Index,
12
- ModelDefinition,
13
- ModelField,
14
- ModelStorage,
15
12
  OperationTypesOf,
16
13
  PrimaryKey,
17
14
  QueryOperationTypeEntry,
@@ -21,7 +18,6 @@ export type {
21
18
  ResolveCodecTypes,
22
19
  ResolveOperationTypes,
23
20
  SqlContract,
24
- SqlMappings,
25
21
  SqlModelFieldStorage,
26
22
  SqlModelStorage,
27
23
  SqlQueryOperationTypes,
package/src/factories.ts CHANGED
@@ -8,12 +8,10 @@ import type {
8
8
  ForeignKeyOptions,
9
9
  ForeignKeyReferences,
10
10
  Index,
11
- ModelDefinition,
12
- ModelField,
13
- ModelStorage,
14
11
  PrimaryKey,
15
12
  SqlContract,
16
- SqlMappings,
13
+ SqlModelFieldStorage,
14
+ SqlModelStorage,
17
15
  SqlStorage,
18
16
  StorageColumn,
19
17
  StorageTable,
@@ -21,14 +19,6 @@ import type {
21
19
  } from './types';
22
20
  import { applyFkDefaults } from './types';
23
21
 
24
- /**
25
- * Creates a StorageColumn with nativeType and codecId.
26
- *
27
- * @param nativeType - Native database type identifier (e.g., 'int4', 'text', 'vector')
28
- * @param codecId - Codec identifier (e.g., 'pg/int4@1', 'pg/text@1')
29
- * @param nullable - Whether the column is nullable (default: false)
30
- * @returns StorageColumn with nativeType and codecId
31
- */
32
22
  export function col(nativeType: string, codecId: string, nullable = false): StorageColumn {
33
23
  return {
34
24
  nativeType,
@@ -95,14 +85,27 @@ export function table(
95
85
  }
96
86
 
97
87
  export function model(
98
- table: string,
99
- fields: Record<string, ModelField>,
88
+ tableName: string,
89
+ fields: Record<string, SqlModelFieldStorage>,
100
90
  relations: Record<string, unknown> = {},
101
- ): ModelDefinition {
102
- const storage: ModelStorage = { table };
91
+ ): {
92
+ storage: SqlModelStorage;
93
+ fields: Record<string, { nullable: boolean; codecId?: string }>;
94
+ relations: Record<string, unknown>;
95
+ } {
96
+ const storage: SqlModelStorage = { table: tableName, fields };
97
+ const domainFields = Object.fromEntries(
98
+ Object.entries(fields).map(([name, field]) => [
99
+ name,
100
+ {
101
+ nullable: field.nullable ?? false,
102
+ ...(field.codecId !== undefined ? { codecId: field.codecId } : {}),
103
+ },
104
+ ]),
105
+ ) as Record<string, { nullable: boolean; codecId?: string }>;
103
106
  return {
104
107
  storage,
105
- fields,
108
+ fields: domainFields,
106
109
  relations,
107
110
  };
108
111
  }
@@ -120,9 +123,7 @@ export function contract<
120
123
  storageHash: TStorageHash;
121
124
  executionHash?: TExecutionHash;
122
125
  storage: SqlStorage;
123
- models?: Record<string, ModelDefinition>;
124
- relations?: Record<string, unknown>;
125
- mappings?: Partial<SqlMappings>;
126
+ models?: Record<string, unknown>;
126
127
  schemaVersion?: '1';
127
128
  targetFamily?: 'sql';
128
129
  profileHash?: TProfileHash;
@@ -130,15 +131,7 @@ export function contract<
130
131
  extensionPacks?: Record<string, unknown>;
131
132
  meta?: Record<string, unknown>;
132
133
  sources?: Record<string, unknown>;
133
- }): SqlContract<
134
- SqlStorage,
135
- Record<string, unknown>,
136
- Record<string, unknown>,
137
- SqlMappings,
138
- TStorageHash,
139
- TExecutionHash,
140
- TProfileHash
141
- > {
134
+ }): SqlContract<SqlStorage, Record<string, unknown>, TStorageHash, TExecutionHash, TProfileHash> {
142
135
  return {
143
136
  schemaVersion: opts.schemaVersion ?? '1',
144
137
  target: opts.target,
@@ -147,20 +140,11 @@ export function contract<
147
140
  ...(opts.executionHash !== undefined && { executionHash: opts.executionHash }),
148
141
  storage: opts.storage,
149
142
  models: opts.models ?? {},
150
- relations: opts.relations ?? {},
151
- mappings: (opts.mappings ?? {}) as SqlMappings,
143
+ roots: {},
152
144
  ...(opts.profileHash !== undefined && { profileHash: opts.profileHash }),
153
145
  ...(opts.capabilities !== undefined && { capabilities: opts.capabilities }),
154
146
  ...(opts.extensionPacks !== undefined && { extensionPacks: opts.extensionPacks }),
155
147
  ...(opts.meta !== undefined && { meta: opts.meta }),
156
148
  ...(opts.sources !== undefined && { sources: opts.sources as Record<string, unknown> }),
157
- } as SqlContract<
158
- SqlStorage,
159
- Record<string, unknown>,
160
- Record<string, unknown>,
161
- SqlMappings,
162
- TStorageHash,
163
- TExecutionHash,
164
- TProfileHash
165
- >;
149
+ } as SqlContract<SqlStorage, Record<string, unknown>, TStorageHash, TExecutionHash, TProfileHash>;
166
150
  }
package/src/types.ts CHANGED
@@ -120,21 +120,6 @@ export type SqlStorage = {
120
120
  readonly types?: Record<string, StorageTypeInstance>;
121
121
  };
122
122
 
123
- export type ModelField = {
124
- readonly column: string;
125
- };
126
-
127
- export type ModelStorage = {
128
- readonly table: string;
129
- };
130
-
131
- export type ModelDefinition = {
132
- readonly storage: ModelStorage;
133
- readonly fields: Record<string, ModelField>;
134
- readonly relations: Record<string, unknown>;
135
- readonly owner?: string;
136
- };
137
-
138
123
  export type SqlModelFieldStorage = {
139
124
  readonly column: string;
140
125
  readonly codecId?: string;
@@ -152,13 +137,6 @@ export type SqlRelation = {
152
137
  readonly on: DomainRelationOn;
153
138
  };
154
139
 
155
- export type SqlMappings = {
156
- readonly modelToTable?: Record<string, string>;
157
- readonly tableToModel?: Record<string, string>;
158
- readonly fieldToColumn?: Record<string, Record<string, string>>;
159
- readonly columnToField?: Record<string, Record<string, string>>;
160
- };
161
-
162
140
  export const DEFAULT_FK_CONSTRAINT = true;
163
141
  export const DEFAULT_FK_INDEX = true;
164
142
 
@@ -223,17 +201,14 @@ export type ContractWithTypeMaps<TContract, TTypeMaps> = TContract & {
223
201
 
224
202
  export type SqlContract<
225
203
  S extends SqlStorage = SqlStorage,
226
- M extends Record<string, unknown> = Record<string, unknown>,
227
- R extends Record<string, unknown> = Record<string, unknown>,
228
- Map extends SqlMappings = SqlMappings,
204
+ TModels extends Record<string, unknown> = Record<string, unknown>,
229
205
  TStorageHash extends StorageHashBase<string> = StorageHashBase<string>,
230
206
  TExecutionHash extends ExecutionHashBase<string> = ExecutionHashBase<string>,
231
207
  TProfileHash extends ProfileHashBase<string> = ProfileHashBase<string>,
232
- > = ContractBase<TStorageHash, TExecutionHash, TProfileHash, M> & {
208
+ > = Omit<ContractBase<TStorageHash, TExecutionHash, TProfileHash>, 'models'> & {
233
209
  readonly targetFamily: string;
234
210
  readonly storage: S;
235
- readonly relations: R;
236
- readonly mappings: Map;
211
+ readonly models: TModels;
237
212
  readonly execution?: ExecutionSection;
238
213
  };
239
214