@prisma-next/sql-contract-emitter 0.3.0-dev.15 → 0.3.0-dev.162

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/src/index.ts CHANGED
@@ -1,23 +1,38 @@
1
- import type { ContractIR } from '@prisma-next/contract/ir';
2
- import type { TypesImportSpec, ValidationContext } from '@prisma-next/contract/types';
1
+ import type { Contract, ContractModel } from '@prisma-next/contract/types';
2
+ import {
3
+ generateCodecTypeIntersection,
4
+ serializeObjectKey,
5
+ serializeValue,
6
+ } from '@prisma-next/emitter/domain-type-generation';
3
7
  import type {
4
- ModelDefinition,
5
- ModelField,
6
- SqlStorage,
7
- StorageTable,
8
- } from '@prisma-next/sql-contract/types';
9
-
10
- export const sqlTargetFamilyHook = {
8
+ GenerateContractTypesOptions,
9
+ ValidationContext,
10
+ } from '@prisma-next/framework-components/emission';
11
+ import type { SqlModelStorage, SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';
12
+ import { assertDefined } from '@prisma-next/utils/assertions';
13
+
14
+ function serializeTypeParamsLiteral(params: Record<string, unknown> | undefined): string {
15
+ if (!params || Object.keys(params).length === 0) {
16
+ return 'Record<string, never>';
17
+ }
18
+
19
+ const entries: string[] = [];
20
+ for (const [key, value] of Object.entries(params)) {
21
+ entries.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);
22
+ }
23
+
24
+ return `{ ${entries.join('; ')} }`;
25
+ }
26
+
27
+ export const sqlEmission = {
11
28
  id: 'sql',
12
29
 
13
- validateTypes(ir: ContractIR, _ctx: ValidationContext): void {
14
- const storage = ir.storage as SqlStorage | undefined;
30
+ validateTypes(contract: Contract, _ctx: ValidationContext): void {
31
+ const storage = contract.storage as unknown as SqlStorage | undefined;
15
32
  if (!storage || !storage.tables) {
16
33
  return;
17
34
  }
18
35
 
19
- // Validate codec ID format (ns/name@version). Adapter-provided codecs are available regardless of contract.extensionPacks (which is for framework extensions); TypeScript prevents invalid usage and runtime validates availability.
20
-
21
36
  const typeIdRegex = /^([^/]+)\/([^@]+)@(\d+)$/;
22
37
 
23
38
  for (const [tableName, tableUnknown] of Object.entries(storage.tables)) {
@@ -39,22 +54,21 @@ export const sqlTargetFamilyHook = {
39
54
  }
40
55
  },
41
56
 
42
- validateStructure(ir: ContractIR): void {
43
- if (ir.targetFamily !== 'sql') {
44
- throw new Error(`Expected targetFamily "sql", got "${ir.targetFamily}"`);
57
+ validateStructure(contract: Contract): void {
58
+ if (contract.targetFamily !== 'sql') {
59
+ throw new Error(`Expected targetFamily "sql", got "${contract.targetFamily}"`);
45
60
  }
46
61
 
47
- const storage = ir.storage as SqlStorage | undefined;
62
+ const storage = contract.storage as unknown as SqlStorage | undefined;
48
63
  if (!storage || !storage.tables) {
49
64
  throw new Error('SQL contract must have storage.tables');
50
65
  }
51
66
 
52
- const models = ir.models as Record<string, ModelDefinition> | undefined;
67
+ const models = contract.models as Record<string, ContractModel<SqlModelStorage>>;
53
68
  const tableNames = new Set(Object.keys(storage.tables));
54
69
 
55
70
  if (models) {
56
- for (const [modelName, modelUnknown] of Object.entries(models)) {
57
- const model = modelUnknown as ModelDefinition;
71
+ for (const [modelName, model] of Object.entries(models)) {
58
72
  if (!model.storage?.table) {
59
73
  throw new Error(`Model "${modelName}" is missing storage.table`);
60
74
  }
@@ -64,22 +78,20 @@ export const sqlTargetFamilyHook = {
64
78
  throw new Error(`Model "${modelName}" references non-existent table "${tableName}"`);
65
79
  }
66
80
 
67
- const table = storage.tables[tableName];
68
- if (!table) {
69
- throw new Error(`Model "${modelName}" references non-existent table "${tableName}"`);
70
- }
81
+ const table: StorageTable | undefined = storage.tables[tableName];
82
+ assertDefined(table, `Model "${modelName}" references non-existent table "${tableName}"`);
71
83
 
72
84
  if (!table.primaryKey) {
73
85
  throw new Error(`Model "${modelName}" table "${tableName}" is missing a primary key`);
74
86
  }
75
87
 
76
88
  const columnNames = new Set(Object.keys(table.columns));
77
- if (!model.fields || Object.keys(model.fields).length === 0) {
78
- throw new Error(`Model "${modelName}" is missing fields`);
89
+ const storageFields = model.storage.fields;
90
+ if (!storageFields || Object.keys(storageFields).length === 0) {
91
+ throw new Error(`Model "${modelName}" is missing storage.fields`);
79
92
  }
80
93
 
81
- for (const [fieldName, fieldUnknown] of Object.entries(model.fields)) {
82
- const field = fieldUnknown as ModelField;
94
+ for (const [fieldName, field] of Object.entries(storageFields)) {
83
95
  if (!field.column) {
84
96
  throw new Error(`Model "${modelName}" field "${fieldName}" is missing column property`);
85
97
  }
@@ -103,10 +115,6 @@ export const sqlTargetFamilyHook = {
103
115
  const table = tableUnknown as StorageTable;
104
116
  const columnNames = new Set(Object.keys(table.columns));
105
117
 
106
- // Column structure (nullable, nativeType, codecId) and table arrays (uniques, indexes, foreignKeys)
107
- // are validated by Arktype schema validation - no need to re-check here.
108
- // We only validate logical consistency (foreign key references, model references, etc.)
109
-
110
118
  if (!Array.isArray(table.uniques)) {
111
119
  throw new Error(
112
120
  `Table "${tableName}" is missing required field "uniques" (must be an array)`,
@@ -168,12 +176,11 @@ export const sqlTargetFamilyHook = {
168
176
  );
169
177
  }
170
178
 
171
- const referencedTable = storage.tables[fk.references.table];
172
- if (!referencedTable) {
173
- throw new Error(
174
- `Table "${tableName}" foreignKey references non-existent table "${fk.references.table}"`,
175
- );
176
- }
179
+ const referencedTable: StorageTable | undefined = storage.tables[fk.references.table];
180
+ assertDefined(
181
+ referencedTable,
182
+ `Table "${tableName}" foreignKey references non-existent table "${fk.references.table}"`,
183
+ );
177
184
 
178
185
  const referencedColumnNames = new Set(Object.keys(referencedTable.columns));
179
186
  for (const colName of fk.references.columns) {
@@ -193,76 +200,50 @@ export const sqlTargetFamilyHook = {
193
200
  }
194
201
  },
195
202
 
196
- generateContractTypes(
197
- ir: ContractIR,
198
- codecTypeImports: ReadonlyArray<TypesImportSpec>,
199
- operationTypeImports: ReadonlyArray<TypesImportSpec>,
200
- ): string {
201
- const allImports = [...codecTypeImports, ...operationTypeImports];
202
- const importLines = allImports.map(
203
- (imp) => `import type { ${imp.named} as ${imp.alias} } from '${imp.package}';`,
204
- );
205
-
206
- const codecTypes = codecTypeImports.map((imp) => imp.alias).join(' & ');
207
- const operationTypes = operationTypeImports.map((imp) => imp.alias).join(' & ');
208
-
209
- const storage = ir.storage as SqlStorage;
210
- const models = ir.models as Record<string, ModelDefinition>;
211
-
212
- const storageType = this.generateStorageType(storage);
213
- const modelsType = this.generateModelsType(models, storage);
214
- const relationsType = this.generateRelationsType(ir.relations);
215
- const mappingsType = this.generateMappingsType(models, storage, codecTypes, operationTypes);
216
-
217
- return `// ⚠️ GENERATED FILE - DO NOT EDIT
218
- // This file is automatically generated by 'prisma-next contract emit'.
219
- // To regenerate, run: prisma-next contract emit
220
- ${importLines.join('\n')}
221
-
222
- import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';
223
-
224
- export type CodecTypes = ${codecTypes || 'Record<string, never>'};
225
- export type LaneCodecTypes = CodecTypes;
226
- export type OperationTypes = ${operationTypes || 'Record<string, never>'};
227
-
228
- export type Contract = SqlContract<
229
- ${storageType},
230
- ${modelsType},
231
- ${relationsType},
232
- ${mappingsType}
233
- >;
234
-
235
- export type Tables = Contract['storage']['tables'];
236
- export type Models = Contract['models'];
237
- export type Relations = Contract['relations'];
238
- `;
239
- },
240
-
241
- generateStorageType(storage: SqlStorage): string {
203
+ generateStorageType(contract: Contract, storageHashTypeName: string): string {
204
+ const storage = contract.storage as unknown as SqlStorage;
242
205
  const tables: string[] = [];
243
- for (const [tableName, table] of Object.entries(storage.tables)) {
206
+ for (const [tableName, table] of Object.entries(storage.tables).sort(([a], [b]) =>
207
+ a.localeCompare(b),
208
+ )) {
244
209
  const columns: string[] = [];
245
210
  for (const [colName, col] of Object.entries(table.columns)) {
246
211
  const nullable = col.nullable ? 'true' : 'false';
247
- const nativeType = `'${col.nativeType}'`;
248
- const codecId = `'${col.codecId}'`;
212
+ const nativeType = serializeValue(col.nativeType);
213
+ const codecId = serializeValue(col.codecId);
214
+ const defaultSpec = col.default
215
+ ? col.default.kind === 'literal'
216
+ ? `; readonly default: { readonly kind: 'literal'; readonly value: DefaultLiteralValue<${codecId}, ${serializeValue(
217
+ col.default.value,
218
+ )}> }`
219
+ : `; readonly default: { readonly kind: 'function'; readonly expression: ${serializeValue(
220
+ col.default.expression,
221
+ )} }`
222
+ : '';
223
+ const typeParamsSpec =
224
+ col.typeParams && Object.keys(col.typeParams).length > 0
225
+ ? `; readonly typeParams: ${serializeTypeParamsLiteral(col.typeParams)}`
226
+ : '';
227
+ const typeRefSpec = col.typeRef ? `; readonly typeRef: ${serializeValue(col.typeRef)}` : '';
249
228
  columns.push(
250
- `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable} }`,
229
+ `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable}${defaultSpec}${typeParamsSpec}${typeRefSpec} }`,
251
230
  );
252
231
  }
253
232
 
254
233
  const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];
255
234
 
256
235
  if (table.primaryKey) {
257
- const pkCols = table.primaryKey.columns.map((c) => `'${c}'`).join(', ');
258
- const pkName = table.primaryKey.name ? `; readonly name: '${table.primaryKey.name}'` : '';
236
+ const pkCols = table.primaryKey.columns.map((c) => serializeValue(c)).join(', ');
237
+ const pkName = table.primaryKey.name
238
+ ? `; readonly name: ${serializeValue(table.primaryKey.name)}`
239
+ : '';
259
240
  tableParts.push(`primaryKey: { readonly columns: readonly [${pkCols}]${pkName} }`);
260
241
  }
261
242
 
262
243
  const uniques = table.uniques
263
244
  .map((u) => {
264
- const cols = u.columns.map((c: string) => `'${c}'`).join(', ');
265
- const name = u.name ? `; readonly name: '${u.name}'` : '';
245
+ const cols = u.columns.map((c: string) => serializeValue(c)).join(', ');
246
+ const name = u.name ? `; readonly name: ${serializeValue(u.name)}` : '';
266
247
  return `{ readonly columns: readonly [${cols}]${name} }`;
267
248
  })
268
249
  .join(', ');
@@ -270,19 +251,22 @@ export type Relations = Contract['relations'];
270
251
 
271
252
  const indexes = table.indexes
272
253
  .map((i) => {
273
- const cols = i.columns.map((c: string) => `'${c}'`).join(', ');
274
- const name = i.name ? `; readonly name: '${i.name}'` : '';
275
- return `{ readonly columns: readonly [${cols}]${name} }`;
254
+ const cols = i.columns.map((c: string) => serializeValue(c)).join(', ');
255
+ const name = i.name ? `; readonly name: ${serializeValue(i.name)}` : '';
256
+ const using = i.using !== undefined ? `; readonly using: ${serializeValue(i.using)}` : '';
257
+ const config =
258
+ i.config !== undefined ? `; readonly config: ${serializeValue(i.config)}` : '';
259
+ return `{ readonly columns: readonly [${cols}]${name}${using}${config} }`;
276
260
  })
277
261
  .join(', ');
278
262
  tableParts.push(`indexes: readonly [${indexes}]`);
279
263
 
280
264
  const fks = table.foreignKeys
281
265
  .map((fk) => {
282
- const cols = fk.columns.map((c: string) => `'${c}'`).join(', ');
283
- const refCols = fk.references.columns.map((c: string) => `'${c}'`).join(', ');
284
- const name = fk.name ? `; readonly name: '${fk.name}'` : '';
285
- return `{ readonly columns: readonly [${cols}]; readonly references: { readonly table: '${fk.references.table}'; readonly columns: readonly [${refCols}] }${name} }`;
266
+ const cols = fk.columns.map((c: string) => serializeValue(c)).join(', ');
267
+ const refCols = fk.references.columns.map((c: string) => serializeValue(c)).join(', ');
268
+ const name = fk.name ? `; readonly name: ${serializeValue(fk.name)}` : '';
269
+ return `{ readonly columns: readonly [${cols}]; readonly references: { readonly table: ${serializeValue(fk.references.table)}; readonly columns: readonly [${refCols}] }${name}; readonly constraint: ${fk.constraint}; readonly index: ${fk.index} }`;
286
270
  })
287
271
  .join(', ');
288
272
  tableParts.push(`foreignKeys: readonly [${fks}]`);
@@ -290,196 +274,84 @@ export type Relations = Contract['relations'];
290
274
  tables.push(`readonly ${tableName}: { ${tableParts.join('; ')} }`);
291
275
  }
292
276
 
293
- return `{ readonly tables: { ${tables.join('; ')} } }`;
294
- },
295
-
296
- generateModelsType(
297
- models: Record<string, ModelDefinition> | undefined,
298
- storage: SqlStorage,
299
- ): string {
300
- if (!models) {
301
- return 'Record<string, never>';
302
- }
303
-
304
- const modelTypes: string[] = [];
305
- for (const [modelName, model] of Object.entries(models)) {
306
- const fields: string[] = [];
307
- const tableName = model.storage.table;
308
- const table = storage.tables[tableName];
309
-
310
- if (table) {
311
- for (const [fieldName, field] of Object.entries(model.fields)) {
312
- const column = table.columns[field.column];
313
- if (!column) {
314
- fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);
315
- continue;
316
- }
317
-
318
- const typeId = column.codecId;
319
- const nullable = column.nullable ?? false;
320
- const jsType = nullable
321
- ? `CodecTypes['${typeId}']['output'] | null`
322
- : `CodecTypes['${typeId}']['output']`;
323
-
324
- fields.push(`readonly ${fieldName}: ${jsType}`);
325
- }
326
- } else {
327
- for (const [fieldName, field] of Object.entries(model.fields)) {
328
- fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);
329
- }
330
- }
331
-
332
- const relations: string[] = [];
333
- for (const [relName, rel] of Object.entries(model.relations)) {
334
- if (typeof rel === 'object' && rel !== null && 'on' in rel) {
335
- const on = rel.on as { parentCols?: string[]; childCols?: string[] };
336
- if (on.parentCols && on.childCols) {
337
- const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');
338
- const childCols = on.childCols.map((c) => `'${c}'`).join(', ');
339
- relations.push(
340
- `readonly ${relName}: { readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] } }`,
341
- );
342
- }
343
- }
344
- }
345
-
346
- const modelParts: string[] = [
347
- `storage: { readonly table: '${tableName}' }`,
348
- `fields: { ${fields.join('; ')} }`,
349
- ];
277
+ const typesType = generateStorageTypesType(storage.types);
350
278
 
351
- if (relations.length > 0) {
352
- modelParts.push(`relations: { ${relations.join('; ')} }`);
353
- }
354
-
355
- modelTypes.push(`readonly ${modelName}: { ${modelParts.join('; ')} }`);
356
- }
357
-
358
- return `{ ${modelTypes.join('; ')} }`;
279
+ return `{ readonly tables: { ${tables.join('; ')} }; readonly types: ${typesType}; readonly storageHash: ${storageHashTypeName} }`;
359
280
  },
360
281
 
361
- generateRelationsType(relations: Record<string, unknown> | undefined): string {
362
- if (!relations || Object.keys(relations).length === 0) {
363
- return 'Record<string, never>';
364
- }
365
-
366
- const tableEntries: string[] = [];
367
- for (const [tableName, relsValue] of Object.entries(relations)) {
368
- if (typeof relsValue !== 'object' || relsValue === null) {
369
- continue;
370
- }
371
- const rels = relsValue as Record<string, unknown>;
372
- const relationEntries: string[] = [];
373
- for (const [relName, relValue] of Object.entries(rels)) {
374
- if (typeof relValue !== 'object' || relValue === null) {
375
- relationEntries.push(`readonly ${relName}: unknown`);
376
- continue;
377
- }
378
- const { to, cardinality, on, through } = relValue as {
379
- readonly to?: string;
380
- readonly cardinality?: string;
381
- readonly on?: {
382
- readonly parentCols?: readonly string[];
383
- readonly childCols?: readonly string[];
384
- };
385
- readonly through?: {
386
- readonly table: string;
387
- readonly parentCols: readonly string[];
388
- readonly childCols: readonly string[];
389
- };
390
- };
391
-
392
- const parts: string[] = [];
393
- if (to) {
394
- parts.push(`readonly to: '${to}'`);
395
- }
396
- if (cardinality) {
397
- parts.push(`readonly cardinality: '${cardinality}'`);
398
- }
399
- if (on?.parentCols && on.childCols) {
400
- const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');
401
- const childCols = on.childCols.map((c) => `'${c}'`).join(', ');
402
- parts.push(
403
- `readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,
404
- );
405
- }
406
- if (through) {
407
- const parentCols = through.parentCols.map((c) => `'${c}'`).join(', ');
408
- const childCols = through.childCols.map((c) => `'${c}'`).join(', ');
409
- parts.push(
410
- `readonly through: { readonly table: '${through.table}'; readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,
411
- );
412
- }
413
-
414
- relationEntries.push(
415
- parts.length > 0
416
- ? `readonly ${relName}: { ${parts.join('; ')} }`
417
- : `readonly ${relName}: unknown`,
282
+ generateModelStorageType(_modelName: string, model: ContractModel): string {
283
+ const sqlModel = model as ContractModel<SqlModelStorage>;
284
+ const tableName = sqlModel.storage.table;
285
+ const storageFields = sqlModel.storage.fields;
286
+
287
+ const storageParts = [`readonly table: ${serializeValue(tableName)}`];
288
+ if (Object.keys(storageFields).length > 0) {
289
+ const fieldParts: string[] = [];
290
+ for (const [fieldName, field] of Object.entries(storageFields)) {
291
+ fieldParts.push(
292
+ `readonly ${serializeObjectKey(fieldName)}: { readonly column: ${serializeValue(field.column)} }`,
418
293
  );
419
294
  }
420
- tableEntries.push(`readonly ${tableName}: { ${relationEntries.join('; ')} }`);
295
+ storageParts.push(`readonly fields: { ${fieldParts.join('; ')} }`);
421
296
  }
422
297
 
423
- return `{ ${tableEntries.join('; ')} }`;
298
+ return `{ ${storageParts.join('; ')} }`;
424
299
  },
425
300
 
426
- generateMappingsType(
427
- models: Record<string, ModelDefinition> | undefined,
428
- storage: SqlStorage,
429
- codecTypes: string,
430
- operationTypes: string,
431
- ): string {
432
- if (!models) {
433
- return `SqlMappings & { readonly codecTypes: ${codecTypes || 'Record<string, never>'}; readonly operationTypes: ${operationTypes || 'Record<string, never>'}; }`;
434
- }
435
-
436
- const modelToTable: string[] = [];
437
- const tableToModel: string[] = [];
438
- const fieldToColumn: string[] = [];
439
- const columnToField: string[] = [];
440
-
441
- for (const [modelName, model] of Object.entries(models)) {
442
- const tableName = model.storage.table;
443
- modelToTable.push(`readonly ${modelName}: '${tableName}'`);
444
- tableToModel.push(`readonly ${tableName}: '${modelName}'`);
445
-
446
- const fieldMap: string[] = [];
447
- for (const [fieldName, field] of Object.entries(model.fields)) {
448
- fieldMap.push(`readonly ${fieldName}: '${field.column}'`);
449
- }
450
-
451
- if (fieldMap.length > 0) {
452
- fieldToColumn.push(`readonly ${modelName}: { ${fieldMap.join('; ')} }`);
453
- }
301
+ getFamilyImports(): string[] {
302
+ return [
303
+ 'import type {',
304
+ ' ContractWithTypeMaps,',
305
+ ' TypeMaps as TypeMapsType,',
306
+ "} from '@prisma-next/sql-contract/types';",
307
+ ];
308
+ },
454
309
 
455
- if (storage.tables[tableName]) {
456
- const colMap: string[] = [];
457
- for (const [fieldName, field] of Object.entries(model.fields)) {
458
- colMap.push(`readonly ${field.column}: '${fieldName}'`);
459
- }
310
+ getFamilyTypeAliases(options?: GenerateContractTypesOptions): string {
311
+ const queryOperationTypeImports = options?.queryOperationTypeImports ?? [];
312
+ const queryOperationTypes = generateCodecTypeIntersection(
313
+ queryOperationTypeImports,
314
+ 'QueryOperationTypes',
315
+ );
460
316
 
461
- if (colMap.length > 0) {
462
- columnToField.push(`readonly ${tableName}: { ${colMap.join('; ')} }`);
463
- }
464
- }
465
- }
317
+ return [
318
+ 'export type LaneCodecTypes = CodecTypes;',
319
+ `export type QueryOperationTypes = ${queryOperationTypes};`,
320
+ 'type DefaultLiteralValue<CodecId extends string, _Encoded> =',
321
+ ' CodecId extends keyof CodecTypes',
322
+ " ? CodecTypes[CodecId]['output']",
323
+ ' : _Encoded;',
324
+ ].join('\n');
325
+ },
466
326
 
467
- const parts: string[] = [];
468
- if (modelToTable.length > 0) {
469
- parts.push(`modelToTable: { ${modelToTable.join('; ')} }`);
470
- }
471
- if (tableToModel.length > 0) {
472
- parts.push(`tableToModel: { ${tableToModel.join('; ')} }`);
473
- }
474
- if (fieldToColumn.length > 0) {
475
- parts.push(`fieldToColumn: { ${fieldToColumn.join('; ')} }`);
476
- }
477
- if (columnToField.length > 0) {
478
- parts.push(`columnToField: { ${columnToField.join('; ')} }`);
479
- }
480
- parts.push(`codecTypes: ${codecTypes || 'Record<string, never>'}`);
481
- parts.push(`operationTypes: ${operationTypes || 'Record<string, never>'}`);
327
+ getTypeMapsExpression(): string {
328
+ return 'TypeMapsType<CodecTypes, OperationTypes, QueryOperationTypes, FieldOutputTypes, FieldInputTypes>';
329
+ },
482
330
 
483
- return `{ ${parts.join('; ')} }`;
331
+ getContractWrapper(contractBaseName: string, typeMapsName: string): string {
332
+ return [
333
+ `export type Contract = ContractWithTypeMaps<${contractBaseName}, ${typeMapsName}>;`,
334
+ '',
335
+ "export type Tables = Contract['storage']['tables'];",
336
+ "export type Models = Contract['models'];",
337
+ ].join('\n');
484
338
  },
485
339
  } as const;
340
+
341
+ function generateStorageTypesType(types: SqlStorage['types']): string {
342
+ if (!types || Object.keys(types).length === 0) {
343
+ return 'Record<string, never>';
344
+ }
345
+
346
+ const typeEntries: string[] = [];
347
+ for (const [typeName, typeInstance] of Object.entries(types)) {
348
+ const codecId = serializeValue(typeInstance.codecId);
349
+ const nativeType = serializeValue(typeInstance.nativeType);
350
+ const typeParamsStr = serializeTypeParamsLiteral(typeInstance.typeParams);
351
+ typeEntries.push(
352
+ `readonly ${typeName}: { readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,
353
+ );
354
+ }
355
+
356
+ return `{ ${typeEntries.join('; ')} }`;
357
+ }
package/dist/index.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { ContractIR } from '@prisma-next/contract/ir';
2
- import type { TypesImportSpec, ValidationContext } from '@prisma-next/contract/types';
3
- import type { ModelDefinition, SqlStorage } from '@prisma-next/sql-contract/types';
4
- export declare const sqlTargetFamilyHook: {
5
- readonly id: "sql";
6
- readonly validateTypes: (ir: ContractIR, _ctx: ValidationContext) => void;
7
- readonly validateStructure: (ir: ContractIR) => void;
8
- readonly generateContractTypes: (ir: ContractIR, codecTypeImports: ReadonlyArray<TypesImportSpec>, operationTypeImports: ReadonlyArray<TypesImportSpec>) => string;
9
- readonly generateStorageType: (storage: SqlStorage) => string;
10
- readonly generateModelsType: (models: Record<string, ModelDefinition> | undefined, storage: SqlStorage) => string;
11
- readonly generateRelationsType: (relations: Record<string, unknown> | undefined) => string;
12
- readonly generateMappingsType: (models: Record<string, ModelDefinition> | undefined, storage: SqlStorage, codecTypes: string, operationTypes: string) => string;
13
- };
14
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EACV,eAAe,EAEf,UAAU,EAEX,MAAM,iCAAiC,CAAC;AAEzC,eAAO,MAAM,mBAAmB;;iCAGZ,UAAU,QAAQ,iBAAiB,KAAG,IAAI;qCA6BtC,UAAU,KAAG,IAAI;yCA2JjC,UAAU,oBACI,aAAa,CAAC,eAAe,CAAC,wBAC1B,aAAa,CAAC,eAAe,CAAC,KACnD,MAAM;4CAyCoB,UAAU,KAAG,MAAM;0CAwDtC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,KAClB,MAAM;gDA8DwB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAG,MAAM;4CAkEnE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,cACP,MAAM,kBACF,MAAM,KACrB,MAAM;CAsDD,CAAC"}