@prisma-next/sql-contract-ts 0.3.0-dev.133 → 0.3.0-dev.135

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,9 @@
1
- import type { ExtensionPackRef, TargetPackRef } from '@prisma-next/contract/framework-components';
2
1
  import type {
3
- ColumnDefault,
4
- ColumnDefaultLiteralInputValue,
5
- ColumnDefaultLiteralValue,
6
- ExecutionMutationDefault,
7
- ExecutionMutationDefaultValue,
8
- TaggedRaw,
9
- } from '@prisma-next/contract/types';
2
+ ExtensionPackRef,
3
+ FamilyPackRef,
4
+ TargetPackRef,
5
+ } from '@prisma-next/contract/framework-components';
6
+ import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';
10
7
  import type {
11
8
  ColumnBuilderState,
12
9
  ColumnTypeDescriptor,
@@ -24,19 +21,48 @@ import {
24
21
  type ExtractColumns,
25
22
  type ExtractPrimaryKey,
26
23
  ModelBuilder,
27
- type Mutable,
28
24
  TableBuilder,
29
25
  } from '@prisma-next/contract-authoring';
30
- import {
31
- applyFkDefaults,
32
- type ContractWithTypeMaps,
33
- type Index,
34
- type ReferentialAction,
35
- type SqlContract,
36
- type StorageTypeInstance,
37
- type TypeMaps,
26
+ import type {
27
+ ContractWithTypeMaps,
28
+ Index,
29
+ ReferentialAction,
30
+ SqlContract,
31
+ StorageTypeInstance,
32
+ TypeMaps,
38
33
  } from '@prisma-next/sql-contract/types';
39
- import { ifDefined } from '@prisma-next/utils/defined';
34
+ import {
35
+ type ComposedAuthoringHelpers,
36
+ createComposedAuthoringHelpers,
37
+ } from './composed-authoring-helpers';
38
+ import {
39
+ buildContractIR,
40
+ buildSqlContractFromSemanticDefinition,
41
+ type RuntimeBuilderState,
42
+ } from './contract-ir-builder';
43
+
44
+ export { buildSqlContractFromSemanticDefinition } from './contract-ir-builder';
45
+
46
+ import {
47
+ field,
48
+ isStagedContractInput,
49
+ type ModelAttributesSpec,
50
+ model,
51
+ type RelationBuilder,
52
+ rel,
53
+ type ScalarFieldBuilder,
54
+ type SqlStageSpec,
55
+ type StagedContractInput,
56
+ type StagedModelBuilder,
57
+ type RelationState as StagedRelationState,
58
+ } from './staged-contract-dsl';
59
+ import { buildStagedSemanticContractDefinition } from './staged-contract-lowering';
60
+ import type {
61
+ ExtractCodecTypesFromPack,
62
+ MergeExtensionCodecTypes,
63
+ MergeExtensionPackRefs,
64
+ SqlContractResult,
65
+ } from './staged-contract-types';
40
66
 
41
67
  type ColumnDefaultForCodec<
42
68
  CodecTypes extends Record<string, { output: unknown }>,
@@ -126,24 +152,6 @@ export interface SqlTableBuilder<
126
152
  >;
127
153
  }
128
154
 
129
- type ExtractCodecTypesFromPack<P> = P extends { __codecTypes?: infer C }
130
- ? C extends Record<string, { output: unknown }>
131
- ? C
132
- : Record<string, never>
133
- : Record<string, never>;
134
-
135
- type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
136
- k: infer I,
137
- ) => void
138
- ? I
139
- : never;
140
-
141
- type MergeExtensionCodecTypes<Packs extends Record<string, unknown>> = UnionToIntersection<
142
- {
143
- [K in keyof Packs]: ExtractCodecTypesFromPack<Packs[K]>;
144
- }[keyof Packs]
145
- >;
146
-
147
155
  type BuildStorageTable<
148
156
  _TableName extends string,
149
157
  Columns extends Record<string, ColumnBuilderState<string, boolean, string>>,
@@ -194,73 +202,30 @@ type BuildStorage<
194
202
  readonly types: Types;
195
203
  };
196
204
 
197
- type BuildStorageTables<
198
- Tables extends Record<
199
- string,
200
- TableBuilderState<
201
- string,
202
- Record<string, ColumnBuilderState<string, boolean, string>>,
203
- readonly string[] | undefined
204
- >
205
- >,
206
- > = {
207
- readonly [K in keyof Tables]: BuildStorageTable<
208
- K & string,
209
- ExtractColumns<Tables[K]>,
210
- ExtractPrimaryKey<Tables[K]>
211
- >;
212
- };
213
-
214
205
  export interface ColumnBuilder<Name extends string, Nullable extends boolean, Type extends string> {
215
206
  nullable<Value extends boolean>(value?: Value): ColumnBuilder<Name, Value, Type>;
216
207
  type<Id extends string>(id: Id): ColumnBuilder<Name, Nullable, Id>;
217
208
  build(): ColumnBuilderState<Name, Nullable, Type>;
218
209
  }
219
210
 
220
- function isPlainObject(value: unknown): value is Record<string, unknown> {
221
- if (typeof value !== 'object' || value === null) return false;
222
- const proto = Object.getPrototypeOf(value);
223
- return proto === Object.prototype || proto === null;
224
- }
225
-
226
- function isJsonValue(value: unknown): value is ColumnDefaultLiteralValue {
227
- if (value === null) return true;
228
- const valueType = typeof value;
229
- if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') return true;
230
- if (Array.isArray(value)) {
231
- return value.every((item) => isJsonValue(item));
232
- }
233
- if (isPlainObject(value)) {
234
- return Object.values(value).every((item) => isJsonValue(item));
235
- }
236
- return false;
237
- }
238
-
239
- function encodeDefaultLiteralValue(
240
- value: ColumnDefaultLiteralInputValue,
241
- ): ColumnDefaultLiteralValue {
242
- if (typeof value === 'bigint') {
243
- return { $type: 'bigint', value: value.toString() };
244
- }
245
- if (value instanceof Date) {
246
- return value.toISOString();
247
- }
248
- if (isJsonValue(value)) {
249
- if (isPlainObject(value) && '$type' in value) {
250
- return { $type: 'raw', value } satisfies TaggedRaw;
251
- }
252
- return value;
253
- }
254
- throw new Error(
255
- 'Unsupported column default literal value: expected JSON-safe value, bigint, or Date.',
256
- );
257
- }
211
+ type StagedModelLike = {
212
+ readonly stageOne: {
213
+ readonly modelName?: string;
214
+ readonly fields: Record<string, ScalarFieldBuilder>;
215
+ readonly relations: Record<string, RelationBuilder<StagedRelationState>>;
216
+ };
217
+ readonly __attributes: ModelAttributesSpec | undefined;
218
+ readonly __sql: SqlStageSpec | undefined;
219
+ buildAttributesSpec(): ModelAttributesSpec | undefined;
220
+ buildSqlSpec(): SqlStageSpec | undefined;
221
+ };
258
222
 
259
- function encodeColumnDefault(defaultInput: ColumnDefault): ColumnDefault {
260
- if (defaultInput.kind === 'function') {
261
- return { kind: 'function', expression: defaultInput.expression };
262
- }
263
- return { kind: 'literal', value: encodeDefaultLiteralValue(defaultInput.value) };
223
+ function buildStagedContract<Definition extends StagedContractInput>(
224
+ definition: Definition,
225
+ ): SqlContractResult<Definition> {
226
+ return buildSqlContractFromSemanticDefinition(
227
+ buildStagedSemanticContractDefinition(definition),
228
+ ) as SqlContractResult<Definition>;
264
229
  }
265
230
 
266
231
  class SqlContractBuilder<
@@ -327,241 +292,7 @@ class SqlContractBuilder<
327
292
  TypeMaps<CodecTypes, Record<string, never>>
328
293
  >
329
294
  : never {
330
- type BuiltContract = Target extends string
331
- ? ContractWithTypeMaps<
332
- SqlContract<BuildStorage<Tables, Types>, BuildModels<Models>> & {
333
- readonly schemaVersion: '1';
334
- readonly target: Target;
335
- readonly targetFamily: 'sql';
336
- readonly storageHash: StorageHash extends string ? StorageHash : string;
337
- } & (ExtensionPacks extends Record<string, unknown>
338
- ? { readonly extensionPacks: ExtensionPacks }
339
- : Record<string, never>) &
340
- (Capabilities extends Record<string, Record<string, boolean>>
341
- ? { readonly capabilities: Capabilities }
342
- : Record<string, never>),
343
- TypeMaps<CodecTypes, Record<string, never>>
344
- >
345
- : never;
346
- if (!this.state.target) {
347
- throw new Error('target is required. Call .target() before .build()');
348
- }
349
-
350
- const target = this.state.target as Target & string;
351
-
352
- const storageTables = {} as Partial<Mutable<BuildStorageTables<Tables>>>;
353
- const executionDefaults: ExecutionMutationDefault[] = [];
354
-
355
- for (const tableName of Object.keys(this.state.tables) as Array<keyof Tables & string>) {
356
- const tableState = this.state.tables[tableName];
357
- if (!tableState) continue;
358
-
359
- type TableKey = typeof tableName;
360
- type ColumnDefs = ExtractColumns<Tables[TableKey]>;
361
- type PrimaryKey = ExtractPrimaryKey<Tables[TableKey]>;
362
-
363
- const columns = {} as Partial<{
364
- [K in keyof ColumnDefs]: BuildStorageColumn<
365
- ColumnDefs[K]['nullable'] & boolean,
366
- ColumnDefs[K]['type']
367
- >;
368
- }>;
369
-
370
- for (const columnName in tableState.columns) {
371
- const columnState = tableState.columns[columnName];
372
- if (!columnState) continue;
373
- const codecId = columnState.type;
374
- const nativeType = columnState.nativeType;
375
- const typeRef = columnState.typeRef;
376
-
377
- const encodedDefault =
378
- columnState.default !== undefined
379
- ? encodeColumnDefault(columnState.default as ColumnDefault)
380
- : undefined;
381
-
382
- columns[columnName as keyof ColumnDefs] = {
383
- nativeType,
384
- codecId,
385
- nullable: (columnState.nullable ?? false) as ColumnDefs[keyof ColumnDefs]['nullable'] &
386
- boolean,
387
- ...ifDefined('typeParams', columnState.typeParams),
388
- ...ifDefined('default', encodedDefault),
389
- ...ifDefined('typeRef', typeRef),
390
- } as BuildStorageColumn<
391
- ColumnDefs[keyof ColumnDefs]['nullable'] & boolean,
392
- ColumnDefs[keyof ColumnDefs]['type']
393
- >;
394
-
395
- if ('executionDefault' in columnState && columnState.executionDefault) {
396
- executionDefaults.push({
397
- ref: { table: tableName, column: columnName },
398
- onCreate: columnState.executionDefault,
399
- });
400
- }
401
- }
402
-
403
- // Build uniques from table state
404
- const uniques = (tableState.uniques ?? []).map((u) => ({
405
- columns: u.columns,
406
- ...(u.name ? { name: u.name } : {}),
407
- }));
408
-
409
- // Build indexes from table state
410
- const indexes = (tableState.indexes ?? []).map((i) => ({
411
- columns: i.columns,
412
- ...(i.name ? { name: i.name } : {}),
413
- ...(i.using ? { using: i.using } : {}),
414
- ...(i.config ? { config: i.config } : {}),
415
- }));
416
-
417
- // Build foreign keys from table state, materializing defaults
418
- const foreignKeys = (tableState.foreignKeys ?? []).map((fk) => ({
419
- columns: fk.columns,
420
- references: fk.references,
421
- ...applyFkDefaults(fk, this.state.foreignKeyDefaults),
422
- ...(fk.name ? { name: fk.name } : {}),
423
- ...(fk.onDelete !== undefined ? { onDelete: fk.onDelete } : {}),
424
- ...(fk.onUpdate !== undefined ? { onUpdate: fk.onUpdate } : {}),
425
- }));
426
-
427
- const table = {
428
- columns: columns as {
429
- [K in keyof ColumnDefs]: BuildStorageColumn<
430
- ColumnDefs[K]['nullable'] & boolean,
431
- ColumnDefs[K]['type']
432
- >;
433
- },
434
- uniques,
435
- indexes,
436
- foreignKeys,
437
- ...(tableState.primaryKey
438
- ? {
439
- primaryKey: {
440
- columns: tableState.primaryKey,
441
- ...(tableState.primaryKeyName ? { name: tableState.primaryKeyName } : {}),
442
- },
443
- }
444
- : {}),
445
- } as unknown as BuildStorageTable<TableKey & string, ColumnDefs, PrimaryKey>;
446
-
447
- (storageTables as Mutable<BuildStorageTables<Tables>>)[tableName] = table;
448
- }
449
-
450
- const storageTypes = (this.state.storageTypes ?? {}) as Types;
451
- const storage: BuildStorage<Tables, Types> = {
452
- tables: storageTables as BuildStorageTables<Tables>,
453
- types: storageTypes,
454
- };
455
-
456
- const execution =
457
- executionDefaults.length > 0
458
- ? {
459
- mutations: {
460
- defaults: executionDefaults.sort((a, b) => {
461
- const tableCompare = a.ref.table.localeCompare(b.ref.table);
462
- if (tableCompare !== 0) {
463
- return tableCompare;
464
- }
465
- return a.ref.column.localeCompare(b.ref.column);
466
- }),
467
- },
468
- }
469
- : undefined;
470
-
471
- // Build models - construct as partial first, then assert full type
472
- const modelsPartial: Partial<BuildModels<Models>> = {};
473
-
474
- for (const modelName in this.state.models) {
475
- const modelState = this.state.models[modelName];
476
- if (!modelState) continue;
477
-
478
- const modelStateTyped = modelState as unknown as {
479
- name: string;
480
- table: string;
481
- fields: Record<string, string>;
482
- relations: Record<string, RelationDefinition>;
483
- };
484
-
485
- const tableName = modelStateTyped.table;
486
- const tableState = this.state.tables[tableName as keyof Tables];
487
- const tableColumns = tableState
488
- ? (
489
- tableState as unknown as {
490
- columns: Record<string, { type: string; nullable?: boolean }>;
491
- }
492
- ).columns
493
- : {};
494
-
495
- const storageFields: Record<string, { readonly column: string }> = {};
496
- const domainFields: Record<string, Record<string, unknown>> = {};
497
-
498
- for (const fieldName in modelStateTyped.fields) {
499
- const columnName = modelStateTyped.fields[fieldName];
500
- if (!columnName) continue;
501
-
502
- storageFields[fieldName] = { column: columnName };
503
-
504
- const column = tableColumns[columnName];
505
- if (column) {
506
- domainFields[fieldName] = {
507
- codecId: column.type,
508
- nullable: column.nullable ?? false,
509
- };
510
- }
511
- }
512
-
513
- const modelRelations: Record<string, Record<string, unknown>> = {};
514
- if (modelStateTyped.relations) {
515
- for (const relName in modelStateTyped.relations) {
516
- const rel = modelStateTyped.relations[relName];
517
- if (!rel) continue;
518
- modelRelations[relName] = {
519
- to: rel.to,
520
- cardinality: rel.cardinality,
521
- on: {
522
- localFields: rel.on.parentCols,
523
- targetFields: rel.on.childCols,
524
- },
525
- };
526
- }
527
- }
528
-
529
- (modelsPartial as unknown as Record<string, Record<string, unknown>>)[modelName] = {
530
- storage: {
531
- table: tableName,
532
- fields: storageFields,
533
- },
534
- fields: domainFields,
535
- relations: modelRelations,
536
- };
537
- }
538
-
539
- const models = modelsPartial as unknown as BuildModels<Models>;
540
-
541
- const extensionNamespaces = this.state.extensionNamespaces ?? [];
542
- const extensionPacks: Record<string, unknown> = { ...(this.state.extensionPacks || {}) };
543
- for (const namespace of extensionNamespaces) {
544
- if (!Object.hasOwn(extensionPacks, namespace)) {
545
- extensionPacks[namespace] = {};
546
- }
547
- }
548
-
549
- const contract = {
550
- schemaVersion: '1' as const,
551
- target,
552
- targetFamily: 'sql' as const,
553
- storageHash: this.state.storageHash || 'sha256:ts-builder-placeholder',
554
- models,
555
- roots: {},
556
- storage,
557
- ...(execution ? { execution } : {}),
558
- extensionPacks,
559
- capabilities: this.state.capabilities || {},
560
- meta: {},
561
- sources: {},
562
- } as unknown as BuiltContract;
563
-
564
- return contract as unknown as ReturnType<
295
+ return buildContractIR(this.state as unknown as RuntimeBuilderState) as unknown as ReturnType<
565
296
  SqlContractBuilder<
566
297
  CodecTypes,
567
298
  Target,
@@ -629,7 +360,7 @@ class SqlContractBuilder<
629
360
  Models,
630
361
  Types,
631
362
  StorageHash,
632
- ExtensionPacks,
363
+ MergeExtensionPackRefs<ExtensionPacks, Packs>,
633
364
  Capabilities
634
365
  > {
635
366
  if (!this.state.target) {
@@ -637,8 +368,13 @@ class SqlContractBuilder<
637
368
  }
638
369
 
639
370
  const namespaces = new Set(this.state.extensionNamespaces ?? []);
371
+ const nextExtensionPacks = {
372
+ ...(this.state.extensionPacks ?? {}),
373
+ } as Record<string, unknown>;
640
374
 
641
- for (const packRef of Object.values(packs) as ExtensionPackRef<'sql', string>[]) {
375
+ for (const [name, packRef] of Object.entries(packs) as Array<
376
+ [keyof Packs & string, ExtensionPackRef<'sql', string>]
377
+ >) {
642
378
  if (!packRef) continue;
643
379
 
644
380
  if (packRef.kind !== 'extension') {
@@ -660,6 +396,7 @@ class SqlContractBuilder<
660
396
  }
661
397
 
662
398
  namespaces.add(packRef.id);
399
+ nextExtensionPacks[name] = packRef;
663
400
  }
664
401
 
665
402
  return new SqlContractBuilder<
@@ -669,10 +406,11 @@ class SqlContractBuilder<
669
406
  Models,
670
407
  Types,
671
408
  StorageHash,
672
- ExtensionPacks,
409
+ MergeExtensionPackRefs<ExtensionPacks, Packs>,
673
410
  Capabilities
674
411
  >({
675
412
  ...this.state,
413
+ extensionPacks: nextExtensionPacks as MergeExtensionPackRefs<ExtensionPacks, Packs>,
676
414
  extensionNamespaces: [...namespaces],
677
415
  });
678
416
  }
@@ -743,6 +481,9 @@ class SqlContractBuilder<
743
481
  Capabilities
744
482
  > {
745
483
  const tableBuilder = createTable(name);
484
+ // Double cast: createTable returns an unparameterized builder; we first narrow
485
+ // to SqlTableBuilder with the caller's generic params, then to the public
486
+ // TableBuilder facade that the callback expects.
746
487
  const result = callback(
747
488
  tableBuilder as unknown as SqlTableBuilder<
748
489
  TableName,
@@ -873,8 +614,168 @@ class SqlContractBuilder<
873
614
  }
874
615
  }
875
616
 
617
+ type StagedContractDefinition<
618
+ Family extends FamilyPackRef<string>,
619
+ Target extends TargetPackRef<'sql', string>,
620
+ Types extends Record<string, StorageTypeInstance>,
621
+ Models extends Record<string, StagedModelLike>,
622
+ ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined,
623
+ Capabilities extends Record<string, Record<string, boolean>> | undefined,
624
+ Naming extends StagedContractInput['naming'] | undefined,
625
+ StorageHash extends string | undefined,
626
+ ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined,
627
+ > = {
628
+ readonly family: Family;
629
+ readonly target: Target;
630
+ readonly extensionPacks?: ExtensionPacks;
631
+ readonly naming?: Naming;
632
+ readonly storageHash?: StorageHash;
633
+ readonly foreignKeyDefaults?: ForeignKeyDefaults;
634
+ readonly capabilities?: Capabilities;
635
+ readonly types?: Types;
636
+ readonly models?: Models;
637
+ };
638
+
639
+ type StagedContractScaffold<
640
+ Family extends FamilyPackRef<string>,
641
+ Target extends TargetPackRef<'sql', string>,
642
+ ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined,
643
+ Capabilities extends Record<string, Record<string, boolean>> | undefined,
644
+ Naming extends StagedContractInput['naming'] | undefined,
645
+ StorageHash extends string | undefined,
646
+ ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined,
647
+ > = {
648
+ readonly family: Family;
649
+ readonly target: Target;
650
+ readonly extensionPacks?: ExtensionPacks;
651
+ readonly naming?: Naming;
652
+ readonly storageHash?: StorageHash;
653
+ readonly foreignKeyDefaults?: ForeignKeyDefaults;
654
+ readonly capabilities?: Capabilities;
655
+ };
656
+
657
+ type StagedContractFactory<
658
+ Family extends FamilyPackRef<string>,
659
+ Target extends TargetPackRef<'sql', string>,
660
+ Types extends Record<string, StorageTypeInstance>,
661
+ Models extends Record<string, StagedModelLike>,
662
+ ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined,
663
+ > = (helpers: ComposedAuthoringHelpers<Family, Target, ExtensionPacks>) => {
664
+ readonly types?: Types;
665
+ readonly models?: Models;
666
+ };
667
+
668
+ export function defineContract<
669
+ CodecTypes extends Record<string, { output: unknown }> = Record<string, never>,
670
+ >(): SqlContractBuilder<CodecTypes>;
671
+ export function defineContract<
672
+ const Family extends FamilyPackRef<string>,
673
+ const Target extends TargetPackRef<'sql', string>,
674
+ const Types extends Record<string, StorageTypeInstance> = Record<never, never>,
675
+ const Models extends Record<string, StagedModelLike> = Record<never, never>,
676
+ const ExtensionPacks extends
677
+ | Record<string, ExtensionPackRef<'sql', string>>
678
+ | undefined = undefined,
679
+ const Capabilities extends Record<string, Record<string, boolean>> | undefined = undefined,
680
+ const Naming extends StagedContractInput['naming'] | undefined = undefined,
681
+ const StorageHash extends string | undefined = undefined,
682
+ const ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined = undefined,
683
+ >(
684
+ definition: StagedContractDefinition<
685
+ Family,
686
+ Target,
687
+ Types,
688
+ Models,
689
+ ExtensionPacks,
690
+ Capabilities,
691
+ Naming,
692
+ StorageHash,
693
+ ForeignKeyDefaults
694
+ >,
695
+ ): SqlContractResult<
696
+ StagedContractDefinition<
697
+ Family,
698
+ Target,
699
+ Types,
700
+ Models,
701
+ ExtensionPacks,
702
+ Capabilities,
703
+ Naming,
704
+ StorageHash,
705
+ ForeignKeyDefaults
706
+ >
707
+ >;
708
+ export function defineContract<
709
+ const Family extends FamilyPackRef<string>,
710
+ const Target extends TargetPackRef<'sql', string>,
711
+ const Types extends Record<string, StorageTypeInstance> = Record<never, never>,
712
+ const Models extends Record<string, StagedModelLike> = Record<never, never>,
713
+ const ExtensionPacks extends
714
+ | Record<string, ExtensionPackRef<'sql', string>>
715
+ | undefined = undefined,
716
+ const Capabilities extends Record<string, Record<string, boolean>> | undefined = undefined,
717
+ const Naming extends StagedContractInput['naming'] | undefined = undefined,
718
+ const StorageHash extends string | undefined = undefined,
719
+ const ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined = undefined,
720
+ >(
721
+ definition: StagedContractScaffold<
722
+ Family,
723
+ Target,
724
+ ExtensionPacks,
725
+ Capabilities,
726
+ Naming,
727
+ StorageHash,
728
+ ForeignKeyDefaults
729
+ >,
730
+ factory: StagedContractFactory<Family, Target, Types, Models, ExtensionPacks>,
731
+ ): SqlContractResult<
732
+ StagedContractDefinition<
733
+ Family,
734
+ Target,
735
+ Types,
736
+ Models,
737
+ ExtensionPacks,
738
+ Capabilities,
739
+ Naming,
740
+ StorageHash,
741
+ ForeignKeyDefaults
742
+ >
743
+ >;
876
744
  export function defineContract<
877
745
  CodecTypes extends Record<string, { output: unknown }> = Record<string, never>,
878
- >(): SqlContractBuilder<CodecTypes> {
746
+ >(
747
+ definition?: StagedContractInput,
748
+ factory?: StagedContractFactory<
749
+ FamilyPackRef<string>,
750
+ TargetPackRef<'sql', string>,
751
+ Record<string, StorageTypeInstance>,
752
+ Record<string, StagedModelLike>,
753
+ Record<string, ExtensionPackRef<'sql', string>> | undefined
754
+ >,
755
+ ): SqlContractBuilder<CodecTypes> | SqlContractResult<StagedContractInput> {
756
+ if (definition && isStagedContractInput(definition)) {
757
+ if (factory) {
758
+ const builtDefinition = {
759
+ ...definition,
760
+ ...factory(
761
+ createComposedAuthoringHelpers({
762
+ family: definition.family,
763
+ target: definition.target,
764
+ extensionPacks: definition.extensionPacks,
765
+ }),
766
+ ),
767
+ };
768
+ return buildStagedContract(builtDefinition);
769
+ }
770
+ return buildStagedContract(definition);
771
+ }
879
772
  return new SqlContractBuilder<CodecTypes>();
880
773
  }
774
+
775
+ export { field, model, rel };
776
+ export type {
777
+ ComposedAuthoringHelpers,
778
+ StagedContractInput,
779
+ StagedModelBuilder,
780
+ ScalarFieldBuilder,
781
+ };