@prisma-next/sql-contract-ts 0.12.0 → 0.13.0-dev.2

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 +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 () => ok(buildSqlContractFromDefinition({ target: options.target, models: [] })),\n },\n ...ifDefined('output', options.output),\n };\n}\n\nexport function typescriptContract(contract: Contract, output?: string): ContractConfig {\n return {\n source: {\n load: async () => ok(contract),\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(contractPath: string, output?: string): 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(contract);\n },\n },\n output: output ?? defaultOutputFromContractPath(contractPath),\n };\n}\n"],"mappings":";;;;;;;;;;;;AAeA,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;AAEA,SAAgB,cAAc,SAGX;CACjB,OAAO;EACL,QAAQ,EACN,MAAM,YAAY,GAAG,+BAA+B;GAAE,QAAQ,QAAQ;GAAQ,QAAQ,CAAC;EAAE,CAAC,CAAC,EAC7F;EACA,GAAG,UAAU,UAAU,QAAQ,MAAM;CACvC;AACF;AAEA,SAAgB,mBAAmB,UAAoB,QAAiC;CACtF,OAAO;EACL,QAAQ,EACN,MAAM,YAAY,GAAG,QAAQ,EAC/B;EAGA,GAAG,UAAU,UAAU,MAAM;CAC/B;AACF;AAEA,SAAgB,2BAA2B,cAAsB,QAAiC;CAChG,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,QAAQ;GACpB;EACF;EACA,QAAQ,UAAU,8BAA8B,YAAY;CAC9D;AACF"}
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,CAAC,CAAC;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,19 +1,117 @@
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";
7
7
  import { ExtensionPackRef, FamilyPackRef, TargetPackRef } from "@prisma-next/framework-components/components";
8
8
  import { CodecLookup, ColumnTypeDescriptor } from "@prisma-next/framework-components/codec";
9
9
 
10
+ //#region src/enum-type.d.ts
11
+ /**
12
+ * A single enum member produced by `member()`. The `Name` and `Value` generics
13
+ * are preserved as literal types so `enumType()` can carry the ordered value
14
+ * tuple in its return type.
15
+ */
16
+ interface EnumMember<Name extends string, Value extends string> {
17
+ readonly name: Name;
18
+ readonly value: Value;
19
+ }
20
+ /**
21
+ * Declare an enum member. The `value` defaults to `name` when omitted.
22
+ * Both generics are preserved as literals so downstream `enumType` can
23
+ * carry the ordered value tuple in its type.
24
+ */
25
+ declare function member<const Name extends string>(name: Name): EnumMember<Name, Name>;
26
+ declare function member<const Name extends string, const Value extends string>(name: Name, value: Value): EnumMember<Name, Value>;
27
+ type MembersToValues<Members extends readonly EnumMember<string, string>[]> = { readonly [K in keyof Members]: Members[K] extends EnumMember<string, infer V> ? V : never };
28
+ type MembersToNames<Members extends readonly EnumMember<string, string>[]> = { readonly [K in keyof Members]: Members[K] extends EnumMember<infer N, string> ? N : never };
29
+ type MembersAccessorMap<Members extends readonly EnumMember<string, string>[]> = { readonly [M in Members[number] as M['name']]: M['value'] };
30
+ /**
31
+ * Internal brand that identifies an EnumTypeHandle in the lowering pipeline.
32
+ * Not exported — callers only interact with `EnumTypeHandle`.
33
+ */
34
+ declare const ENUM_TYPE_HANDLE_BRAND: unique symbol;
35
+ /**
36
+ * Authoring handle returned by `enumType()`. Carries:
37
+ *
38
+ * - The ordered literal value tuple (`.values`) and name tuple (`.names`)
39
+ * so downstream type-tests can assert literal preservation.
40
+ * - A namespaced member accessor map (`.members`) to avoid collisions with
41
+ * `.values` / `.has` / `.nameOf` / `.ordinalOf`.
42
+ * - Runtime helpers `.has()`, `.nameOf()`, `.ordinalOf()`.
43
+ * - Internal metadata (`enumName`, `codecId`, `nativeType`,
44
+ * `enumMembers`) for the lowering pipeline.
45
+ *
46
+ * The type is generic over the ordered value tuple so callers that assign
47
+ * `const Role = enumType(...)` retain the literal tuple on `.values`.
48
+ */
49
+ interface EnumTypeHandle<Name extends string = string, Values extends readonly string[] = readonly string[], Names extends readonly string[] = readonly string[], MembersMap extends Record<string, string> = Record<string, string>> {
50
+ /** Internal brand for lowering-pipeline detection. */
51
+ readonly [ENUM_TYPE_HANDLE_BRAND]: true;
52
+ /** The enum's declared name (used as the key in domain `enum` / storage `valueSet`). */
53
+ readonly enumName: Name;
54
+ /** codecId from the codec passed to `enumType`. */
55
+ readonly codecId: string;
56
+ /** nativeType from the codec passed to `enumType`. */
57
+ readonly nativeType: string;
58
+ /** Ordered member list for lowering (name + value pairs). */
59
+ readonly enumMembers: readonly {
60
+ readonly name: string;
61
+ readonly value: string;
62
+ }[];
63
+ /** Ordered literal value tuple. Declaration order is preserved. */
64
+ readonly values: Values;
65
+ /** Ordered literal name tuple. Declaration order is preserved. */
66
+ readonly names: Names;
67
+ /**
68
+ * Namespaced accessor map: `Role.members.User === 'user'`.
69
+ * Namespaced under `.members` to avoid collisions with `.values` / `.has`.
70
+ */
71
+ readonly members: MembersMap;
72
+ /** Returns `true` if `v` is a declared member value. */
73
+ has(v: string): boolean;
74
+ /** Returns the member name for a value, or `undefined` if not found. */
75
+ nameOf(v: string): string | undefined;
76
+ /** Returns the zero-based declaration index of a value, or `-1` if not found. */
77
+ ordinalOf(v: string): number;
78
+ }
79
+ /**
80
+ * Declare a domain enum for use in TS-authoring contracts.
81
+ *
82
+ * - The codec is an explicit required argument — the `codecId` and
83
+ * `nativeType` are taken from the passed `ColumnTypeDescriptor` (e.g.
84
+ * `{ codecId: 'pg/text@1', nativeType: 'text' }` from a field preset
85
+ * output or a direct inline object).
86
+ * - `const` generics on the members spread preserve the ordered literal
87
+ * value tuple so `Role.values` is `readonly ['user','admin']`, not
88
+ * `string[]`.
89
+ * - Well-formedness assertions at construction: non-empty member list;
90
+ * unique names; unique values.
91
+ *
92
+ * The returned handle wires into `field.namedType(handle)` to set
93
+ * `valueSet` refs on both the domain field and the storage column.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * const Role = enumType('Role', { codecId: 'pg/text@1', nativeType: 'text' },
98
+ * member('User', 'user'),
99
+ * member('Admin', 'admin'),
100
+ * );
101
+ * // Role.values → readonly ['user', 'admin']
102
+ * // Role.members.User → 'user'
103
+ * ```
104
+ */
105
+ declare function enumType<const Name extends string, const Codec extends Pick<ColumnTypeDescriptor, 'codecId' | 'nativeType'>, const Members extends readonly [EnumMember<string, string>, ...EnumMember<string, string>[]]>(name: Name, codec: Codec, ...members: Members): EnumTypeHandle<Name, MembersToValues<[...Members]>, MembersToNames<[...Members]>, MembersAccessorMap<[...Members]>>;
106
+ declare function enumType(name: string, codec: Pick<ColumnTypeDescriptor, 'codecId' | 'nativeType'>, ...members: EnumMember<string, string>[]): EnumTypeHandle;
107
+ //#endregion
10
108
  //#region src/contract-dsl.d.ts
11
109
  type NamingStrategy = 'identity' | 'snake_case';
12
110
  type NamingConfig = {
13
111
  readonly tables?: NamingStrategy;
14
112
  readonly columns?: NamingStrategy;
15
113
  };
16
- type NamedStorageTypeRef = string | StorageTypeInstance | PostgresEnumStorageEntry;
114
+ type NamedStorageTypeRef = string | StorageTypeInstance | PostgresEnumStorageEntry | EnumTypeHandle;
17
115
  type NamedConstraintNameSpec<Name extends string = string> = {
18
116
  readonly name: Name;
19
117
  };
@@ -78,6 +176,13 @@ declare class ScalarFieldBuilder<State extends AnyScalarFieldState = AnyScalarFi
78
176
  private readonly state;
79
177
  readonly __state: State;
80
178
  constructor(state: State);
179
+ /**
180
+ * Returns the physical column name when `.column(name)` was called, or
181
+ * `undefined` when the field uses the default (logical field name) mapping.
182
+ * Used by cross-space FK lowering to stamp the physical column name onto
183
+ * `TargetFieldRef.columnName` so FK target columns are resolved correctly.
184
+ */
185
+ get physicalColumnName(): string | undefined;
81
186
  optional(): ScalarFieldBuilder<State extends ScalarFieldState<infer CodecId, infer TypeRef, boolean, infer ColumnName, infer IdSpec, infer UniqueSpec> ? ScalarFieldState<CodecId, TypeRef, true, ColumnName, IdSpec, UniqueSpec> : never>;
82
187
  column<ColumnName extends string>(name: ColumnName): ScalarFieldBuilder<State extends ScalarFieldState<infer CodecId, infer TypeRef, infer Nullable, string | undefined, infer IdSpec, infer UniqueSpec> ? ScalarFieldState<CodecId, TypeRef, Nullable, ColumnName, IdSpec, UniqueSpec> : never>;
83
188
  default(value: ColumnDefaultLiteralInputValue | ColumnDefault): ScalarFieldBuilder<State>;
@@ -94,6 +199,7 @@ declare function generatedField<Descriptor extends ColumnTypeDescriptor>(spec: G
94
199
  declare function namedTypeField<TypeRef extends string>(typeRef: TypeRef): ScalarFieldBuilder<ScalarFieldState<string, TypeRef, false, undefined>>;
95
200
  declare function namedTypeField<TypeRef extends StorageTypeInstance>(typeRef: TypeRef): ScalarFieldBuilder<ScalarFieldState<TypeRef['codecId'], TypeRef, false, undefined>>;
96
201
  declare function namedTypeField<TypeRef extends PostgresEnumStorageEntry>(typeRef: TypeRef): ScalarFieldBuilder<ScalarFieldState<string, TypeRef, false, undefined>>;
202
+ declare function namedTypeField<Handle extends EnumTypeHandle>(typeRef: Handle): ScalarFieldBuilder<ScalarFieldState<Handle['codecId'], Handle, false, undefined>>;
97
203
  type RelationModelRefSource = 'string' | 'token' | 'lazyToken';
98
204
  type TargetFieldRefSource = 'string' | 'token';
99
205
  type EagerRelationModelName<ModelName extends string = string, Source extends Exclude<RelationModelRefSource, 'lazyToken'> = Exclude<RelationModelRefSource, 'lazyToken'>> = {
@@ -113,6 +219,22 @@ type BelongsToRelation<ToModel extends string = string, FromField extends string
113
219
  readonly from: FromField;
114
220
  readonly to: ToField;
115
221
  readonly sql?: SqlSpec;
222
+ /**
223
+ * Contract-space identity of the target model. Populated when
224
+ * `belongsTo` receives a cross-space branded handle. Absent for
225
+ * local (same-space) relations.
226
+ */
227
+ readonly spaceId?: string;
228
+ /**
229
+ * Physical table name of the cross-space target model. Only set
230
+ * when `spaceId` is present; read from the handle's `tableName`.
231
+ */
232
+ readonly tableName?: string;
233
+ /**
234
+ * Namespace coordinate of the cross-space target model.
235
+ * Only set when `spaceId` is present.
236
+ */
237
+ readonly namespaceId?: string;
116
238
  };
117
239
  type HasManyRelation<ToModel extends string = string, ByField extends string | readonly string[] = string | readonly string[]> = {
118
240
  readonly kind: 'hasMany';
@@ -142,17 +264,58 @@ declare class RelationBuilder<State extends RelationState = AnyRelationState> {
142
264
  sql<const SqlSpec extends BelongsToRelationSqlSpec>(this: State extends BelongsToRelation<string, string | readonly string[], string | readonly string[], BelongsToRelationSqlSpec | undefined> ? RelationBuilder<State> : never, spec: SqlSpec): RelationBuilder<ApplyBelongsToRelationSqlSpec<State, SqlSpec>>;
143
265
  build(): State;
144
266
  }
267
+ /**
268
+ * Reference to a column on the current (local) model.
269
+ *
270
+ * Source columns are always local to the contract being authored. The
271
+ * cross-space brand lives on `TargetFieldRef` (the target side of a foreign
272
+ * key), not here.
273
+ */
145
274
  type ColumnRef<FieldName extends string = string> = {
146
275
  readonly kind: 'columnRef';
147
276
  readonly fieldName: FieldName;
148
277
  };
149
- type TargetFieldRef<ModelName extends string = string, FieldName extends string = string, Source extends TargetFieldRefSource = TargetFieldRefSource> = {
278
+ /**
279
+ * Reference to a field on a target model, produced by model `.refs` and
280
+ * `constraints.ref(modelName, fieldName)`.
281
+ *
282
+ * The `TSpaceId` phantom parameter carries the contract-space identity of the
283
+ * target model. Local model handles produce `TSpaceId = '<self>'`; extension
284
+ * handles carry the extension's `spaceId`. The brand is propagated from the
285
+ * parent `ContractModelBuilder` via the `spaceId?` property: absent means local
286
+ * (`'<self>'`), present means cross-space.
287
+ */
288
+ type TargetFieldRef<ModelName extends string = string, FieldName extends string = string, TSpaceId extends string = string> = {
150
289
  readonly kind: 'targetFieldRef';
151
- readonly source: Source;
290
+ readonly source: TargetFieldRefSource;
152
291
  readonly modelName: ModelName;
153
292
  readonly fieldName: FieldName;
293
+ /**
294
+ * Cross-space discriminator. When present, the referenced model lives in a
295
+ * different contract space identified by this value. Absent for local refs.
296
+ */
297
+ readonly spaceId?: TSpaceId extends '<self>' ? never : TSpaceId;
298
+ /**
299
+ * Namespace id of the cross-space target model (e.g. `'auth'` for
300
+ * `supabase` `auth.User`). Only present for cross-space refs.
301
+ */
302
+ readonly namespaceId?: string;
303
+ /**
304
+ * Physical table name of the cross-space target model. Only present for
305
+ * cross-space refs; allows the lowering path to bypass the local model
306
+ * registry.
307
+ */
308
+ readonly tableName?: string;
309
+ /**
310
+ * Physical column name of the target field. Populated for cross-space refs
311
+ * when the extension handle's field used `.column(name)` to rename the
312
+ * physical column. When absent the logical `fieldName` is used as the column
313
+ * name. Only relevant for cross-space FK lowering — local FKs resolve column
314
+ * names via the local `fieldToColumn` map.
315
+ */
316
+ readonly columnName?: string;
154
317
  };
155
- type ModelTokenRefs<ModelName extends string, Fields extends Record<string, ScalarFieldBuilder>> = { readonly [K in keyof Fields]: TargetFieldRef<ModelName, K & string> };
318
+ type ModelTokenRefs<ModelName extends string, Fields extends Record<string, ScalarFieldBuilder>, TSpaceId extends string = '<self>'> = { readonly [K in keyof Fields]: TargetFieldRef<ModelName, K & string, TSpaceId> };
156
319
  type ConstraintOptions<Name extends string | undefined = string | undefined> = {
157
320
  readonly name?: Name;
158
321
  };
@@ -198,6 +361,22 @@ type ForeignKeyConstraint<SourceFieldNames extends readonly string[] = readonly
198
361
  readonly targetModel: TargetModelName;
199
362
  readonly targetFields: TargetFieldNames;
200
363
  readonly targetSource?: TargetFieldRefSource;
364
+ /**
365
+ * Cross-space discriminator. When present, the FK target lives in a
366
+ * different contract space identified by this value. Absent for local FKs.
367
+ */
368
+ readonly targetSpaceId?: string;
369
+ /**
370
+ * Namespace coordinate of the cross-space target model. Populated when
371
+ * the target model handle carries a `namespace` (e.g. `auth` for supabase
372
+ * `auth.User`). Absent for local FKs.
373
+ */
374
+ readonly targetNamespaceId?: string;
375
+ /**
376
+ * Table name of the cross-space target. Populated for cross-space FKs
377
+ * so the lowering path doesn't need a local model lookup.
378
+ */
379
+ readonly targetTableName?: string;
201
380
  readonly name?: Name;
202
381
  readonly onDelete?: 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';
203
382
  readonly onUpdate?: 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';
@@ -227,6 +406,7 @@ type ModelAttributesSpec = {
227
406
  };
228
407
  type SqlStageSpec = {
229
408
  readonly table?: string;
409
+ readonly control?: ControlPolicy;
230
410
  readonly indexes?: readonly IndexConstraint[];
231
411
  readonly foreignKeys?: readonly ForeignKeyConstraint[];
232
412
  };
@@ -271,7 +451,7 @@ type SqlForeignKeys<SqlSpec extends SqlStageSpec> = SqlSpec extends {
271
451
  type SqlNamedObjects<SqlSpec extends SqlStageSpec> = [...SqlIndexes<SqlSpec>, ...SqlForeignKeys<SqlSpec>];
272
452
  type ValidateSqlStageSpec<Fields extends Record<string, ScalarFieldBuilder>, AttributesSpec extends ModelAttributesSpec | undefined, SqlSpec extends SqlStageSpec> = [DuplicateLiteralNames<SqlNamedObjects<SqlSpec>>] extends [never] ? [Extract<ModelIdLiteralName<Fields, AttributesSpec>, NamedConstraintLiteralName<SqlNamedObjects<SqlSpec>[number]>>] extends [never] ? SqlSpec : never : never;
273
453
  type ValidateAttributesStageSpec<Fields extends Record<string, ScalarFieldBuilder>, SqlSpec extends SqlStageSpec | undefined, AttributesSpec extends ModelAttributesSpec> = SqlSpec extends SqlStageSpec ? [Extract<ModelIdLiteralName<Fields, AttributesSpec>, NamedConstraintLiteralName<SqlNamedObjects<SqlSpec>[number]>>] extends [never] ? AttributesSpec : never : AttributesSpec;
274
- declare class ContractModelBuilder<ModelName extends string | undefined, Fields extends Record<string, ScalarFieldBuilder>, Relations extends Record<string, AnyRelationBuilder> = Record<never, never>, AttributesSpec extends ModelAttributesSpec | undefined = undefined, SqlSpec extends SqlStageSpec | undefined = undefined, IndexTypes extends IndexTypeMap = Record<never, never>> {
454
+ declare class ContractModelBuilder<ModelName extends string | undefined, Fields extends Record<string, ScalarFieldBuilder>, Relations extends Record<string, AnyRelationBuilder> = Record<never, never>, AttributesSpec extends ModelAttributesSpec | undefined = undefined, SqlSpec extends SqlStageSpec | undefined = undefined, IndexTypes extends IndexTypeMap = Record<never, never>, TSpaceId extends string = '<self>'> {
275
455
  readonly stageOne: {
276
456
  readonly modelName?: ModelName;
277
457
  readonly namespace?: string;
@@ -280,23 +460,26 @@ declare class ContractModelBuilder<ModelName extends string | undefined, Fields
280
460
  };
281
461
  readonly attributesFactory?: StageInput<AttributeContext<Fields>, AttributesSpec> | undefined;
282
462
  readonly sqlFactory?: StageInput<SqlContext<Fields, IndexTypes>, SqlSpec> | undefined;
463
+ readonly spaceId?: TSpaceId | undefined;
464
+ readonly tableName?: string | undefined;
283
465
  readonly __name: ModelName;
284
466
  readonly __fields: Fields;
285
467
  readonly __relations: Relations;
286
468
  readonly __attributes: AttributesSpec;
287
469
  readonly __sql: SqlSpec;
288
470
  readonly __indexTypes: IndexTypes;
289
- readonly refs: ModelName extends string ? ModelTokenRefs<ModelName, Fields> : never;
471
+ readonly __spaceId: TSpaceId;
472
+ readonly refs: ModelName extends string ? ModelTokenRefs<ModelName, Fields, TSpaceId> : never;
290
473
  constructor(stageOne: {
291
474
  readonly modelName?: ModelName;
292
475
  readonly namespace?: string;
293
476
  readonly fields: Fields;
294
477
  readonly relations: Relations;
295
- }, attributesFactory?: StageInput<AttributeContext<Fields>, AttributesSpec> | undefined, sqlFactory?: StageInput<SqlContext<Fields, IndexTypes>, SqlSpec> | undefined);
478
+ }, attributesFactory?: StageInput<AttributeContext<Fields>, AttributesSpec> | undefined, sqlFactory?: StageInput<SqlContext<Fields, IndexTypes>, SqlSpec> | undefined, spaceId?: TSpaceId | undefined, tableName?: string | undefined);
296
479
  ref<FieldName extends keyof Fields & string>(this: ModelName extends string ? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, SqlSpec, IndexTypes> : never, fieldName: FieldName): TargetFieldRef<ModelName & string, FieldName>;
297
- relations<const NextRelations extends Record<string, AnyRelationBuilder>>(relations: NextRelations): ContractModelBuilder<ModelName, Fields, Relations & NextRelations, AttributesSpec, SqlSpec, IndexTypes>;
298
- attributes<const NextAttributesSpec extends ModelAttributesSpec>(specOrFactory: StageInput<AttributeContext<Fields>, ValidateAttributesStageSpec<Fields, SqlSpec, NextAttributesSpec>>): ContractModelBuilder<ModelName, Fields, Relations, NextAttributesSpec, SqlSpec, IndexTypes>;
299
- sql<const NextSqlSpec extends SqlStageSpec>(specOrFactory: StageInput<SqlContext<Fields, IndexTypes>, NextSqlSpec>): [ValidateSqlStageSpec<Fields, AttributesSpec, NextSqlSpec>] extends [never] ? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, never, IndexTypes> : ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, NextSqlSpec, IndexTypes>;
480
+ relations<const NextRelations extends Record<string, AnyRelationBuilder>>(relations: NextRelations): ContractModelBuilder<ModelName, Fields, Relations & NextRelations, AttributesSpec, SqlSpec, IndexTypes, TSpaceId>;
481
+ attributes<const NextAttributesSpec extends ModelAttributesSpec>(specOrFactory: StageInput<AttributeContext<Fields>, ValidateAttributesStageSpec<Fields, SqlSpec, NextAttributesSpec>>): ContractModelBuilder<ModelName, Fields, Relations, NextAttributesSpec, SqlSpec, IndexTypes, TSpaceId>;
482
+ sql<const NextSqlSpec extends SqlStageSpec>(specOrFactory: StageInput<SqlContext<Fields, IndexTypes>, NextSqlSpec>): [ValidateSqlStageSpec<Fields, AttributesSpec, NextSqlSpec>] extends [never] ? ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, never, IndexTypes, TSpaceId> : ContractModelBuilder<ModelName, Fields, Relations, AttributesSpec, NextSqlSpec, IndexTypes, TSpaceId>;
300
483
  buildAttributesSpec(): AttributesSpec;
301
484
  buildSqlSpec(): SqlSpec;
302
485
  }
@@ -318,6 +501,7 @@ type ContractInput<Family extends FamilyPackRef<string> = FamilyPackRef<string>,
318
501
  readonly naming?: NamingConfig;
319
502
  readonly storageHash?: string;
320
503
  readonly foreignKeyDefaults?: ForeignKeyDefaultsState;
504
+ readonly defaultControlPolicy?: ControlPolicy;
321
505
  /**
322
506
  * Declared namespace coordinates the contract recognises. Per-model
323
507
  * `namespace` references must reference an entry in this list (or the
@@ -366,6 +550,12 @@ type ContractInput<Family extends FamilyPackRef<string> = FamilyPackRef<string>,
366
550
  readonly types?: Types;
367
551
  readonly models?: Models;
368
552
  readonly codecLookup?: CodecLookup;
553
+ /**
554
+ * Domain enum handles authored via `enumType()`. Each handle lowers to a
555
+ * domain `enum` entry and a storage `valueSet` entry in the target's
556
+ * default namespace. Fields reference the enum via `field.namedType(handle)`.
557
+ */
558
+ readonly enums?: Record<string, EnumTypeHandle>;
369
559
  };
370
560
  declare function model<const ModelName extends string, Fields extends Record<string, ScalarFieldBuilder>, Relations extends Record<string, AnyRelationBuilder> = Record<never, never>>(modelName: ModelName, input: {
371
561
  readonly fields: Fields;
@@ -377,6 +567,26 @@ declare function model<Fields extends Record<string, ScalarFieldBuilder>, Relati
377
567
  readonly relations?: Relations;
378
568
  readonly namespace?: string;
379
569
  }): ContractModelBuilder<undefined, Fields, Relations>;
570
+ /**
571
+ * Factory for building a standalone branded extension model handle.
572
+ *
573
+ * Use this instead of `new ContractModelBuilder(…)` when constructing handles
574
+ * for models that live in a foreign contract space (e.g. a Supabase extension
575
+ * model referenced by a user's contract). The `spaceId` brands the returned
576
+ * handle so `refs.<field>.spaceId` carries the foreign space identifier.
577
+ *
578
+ * @param name - The domain model name as declared in the foreign contract
579
+ * (e.g. `'AuthUser'`, not a bare table alias like `'User'`).
580
+ * @param input.namespace - The namespace within the foreign space (e.g. `'auth'`).
581
+ * @param input.fields - Field definitions (use `field.column(…)`).
582
+ * @param input.table - The physical table name in the foreign schema.
583
+ * @param spaceId - The extension space identifier (e.g. `'supabase'`).
584
+ */
585
+ declare function extensionModel<const ModelName extends string, Fields extends Record<string, ScalarFieldBuilder>, const TSpaceId extends string>(name: ModelName, input: {
586
+ readonly namespace: string;
587
+ readonly fields: Fields;
588
+ readonly table: string;
589
+ }, spaceId: TSpaceId): ContractModelBuilder<ModelName, Fields, Record<never, never>, undefined, undefined, Record<never, never>, TSpaceId>;
380
590
  declare function belongsTo<Token extends AnyNamedModelToken, FromField extends string | readonly string[], ToField extends RelationFieldSelection<RelationModelFieldNames<Token>>>(toModel: Token | LazyNamedModelToken<Token>, options: {
381
591
  readonly from: FromField;
382
592
  readonly to: ToField;
@@ -513,7 +723,7 @@ type DefinitionNamespaces<Definition> = Definition extends {
513
723
  } ? string[] extends Names ? never : readonly string[] extends Names ? never : Names[number] : never;
514
724
  type DefinitionTypes<Definition> = Definition extends {
515
725
  readonly types?: unknown;
516
- } ? Present<Definition['types']> extends Record<string, StorageTypeInstance | PostgresEnumStorageEntry> ? Present<Definition['types']> : Record<never, never> : Record<never, never>;
726
+ } ? Present<Definition['types']> extends Record<string, StorageType> ? Present<Definition['types']> : Record<never, never> : Record<never, never>;
517
727
  type DefinitionTableNaming<Definition> = Definition extends {
518
728
  readonly naming?: {
519
729
  readonly tables?: infer Strategy extends string;
@@ -577,8 +787,8 @@ type DescriptorTypeParams<Descriptor> = Descriptor extends {
577
787
  type DescriptorTypeRef<Descriptor> = Descriptor extends {
578
788
  readonly typeRef: infer TypeRef extends string;
579
789
  } ? TypeRef : undefined;
580
- type LookupNamedStorageTypeKeyByValue<Definition, TypeRef extends StorageTypeInstance | PostgresEnumStorageEntry> = { [TypeName in keyof DefinitionTypes<Definition> & string]: [TypeRef] extends [DefinitionTypes<Definition>[TypeName]] ? [DefinitionTypes<Definition>[TypeName]] extends [TypeRef] ? TypeName : never : never }[keyof DefinitionTypes<Definition> & string];
581
- type ResolveNamedStorageTypeKey<Definition, TypeRef> = TypeRef extends string ? TypeRef : TypeRef extends StorageTypeInstance | PostgresEnumStorageEntry ? [LookupNamedStorageTypeKeyByValue<Definition, TypeRef>] extends [never] ? string : LookupNamedStorageTypeKeyByValue<Definition, TypeRef> : never;
790
+ 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];
791
+ type ResolveNamedStorageTypeKey<Definition, TypeRef> = TypeRef extends string ? TypeRef : TypeRef extends StorageType ? [LookupNamedStorageTypeKeyByValue<Definition, TypeRef>] extends [never] ? string : LookupNamedStorageTypeKeyByValue<Definition, TypeRef> : never;
582
792
  type ResolveNamedStorageType<Definition, TypeRef> = ResolveNamedStorageTypeKey<Definition, TypeRef> extends infer TypeName extends string ? TypeName extends keyof DefinitionTypes<Definition> ? DefinitionTypes<Definition>[TypeName] : StorageTypeInstance : StorageTypeInstance;
583
793
  type ResolveFieldDescriptor<Definition, FieldState> = [FieldDescriptorOf<FieldState>] extends [never] ? ResolveNamedStorageType<Definition, FieldTypeRefOf<FieldState>> : FieldDescriptorOf<FieldState>;
584
794
  type ResolveFieldColumnTypeRef<Definition, FieldState> = [FieldTypeRefOf<FieldState>] extends [never] ? DescriptorTypeRef<FieldDescriptorOf<FieldState>> : ResolveNamedStorageTypeKey<Definition, FieldTypeRefOf<FieldState>>;
@@ -648,6 +858,7 @@ type BuiltStorageTables<Definition> = { readonly [ModelName in ModelNames<Defini
648
858
  };
649
859
  readonly target: {
650
860
  readonly namespaceId: NamespaceId;
861
+ readonly spaceId?: string;
651
862
  readonly tableName: string;
652
863
  readonly columns: readonly string[];
653
864
  };
@@ -663,7 +874,7 @@ type BuiltStorageTables<Definition> = { readonly [ModelName in ModelNames<Defini
663
874
  readonly name?: ModelIdName<Definition, ModelName>;
664
875
  };
665
876
  } : Record<string, never>) };
666
- type BuiltDocumentScopedTypes<Definition> = { readonly [K in keyof DefinitionTypes<Definition> as DefinitionTypes<Definition>[K] extends PostgresEnumStorageEntry ? never : K]: DefinitionTypes<Definition>[K] };
877
+ type BuiltDocumentScopedTypes<Definition> = { readonly [K in keyof DefinitionTypes<Definition> as DefinitionTypes<Definition>[K] extends StorageTypeInstance ? K : never]: DefinitionTypes<Definition>[K] };
667
878
  type BuiltDomain<Definition> = BuiltDocumentScopedTypes<Definition> extends Record<never, never> ? Record<string, never> : {
668
879
  readonly __unbound__: {
669
880
  readonly types: BuiltDocumentScopedTypes<Definition>;
@@ -676,13 +887,15 @@ type BuiltStorage<Definition> = {
676
887
  readonly namespaces: { readonly [K in DefaultStorageNamespaceId<Definition>]: {
677
888
  readonly id: K;
678
889
  readonly kind: string;
679
- readonly tables: BuiltStorageTables<Definition>;
680
- readonly enum?: Readonly<Record<string, PostgresEnumStorageEntry>>;
890
+ readonly entries: {
891
+ readonly table: BuiltStorageTables<Definition>;
892
+ };
681
893
  } } & { readonly [Ns in Exclude<DefinitionNamespaces<Definition>, DefaultStorageNamespaceId<Definition>>]: {
682
894
  readonly id: Ns;
683
895
  readonly kind: string;
684
- readonly tables: Record<never, never>;
685
- readonly enum?: Readonly<Record<string, PostgresEnumStorageEntry>>;
896
+ readonly entries: {
897
+ readonly table: Record<never, never>;
898
+ };
686
899
  } };
687
900
  };
688
901
  type FieldOutputType<Definition, ModelName extends ModelNames<Definition>, FieldName extends ModelFieldNames<Definition, ModelName>> = ModelStorageColumn<Definition, ModelName, FieldName> extends infer Col ? Col extends {
@@ -758,6 +971,8 @@ interface FieldNode {
758
971
  readonly default?: ColumnDefault;
759
972
  readonly executionDefaults?: ExecutionMutationDefaultPhases$1;
760
973
  readonly many?: boolean;
974
+ /** Present when the field was authored with `field.namedType(enumHandle)`. */
975
+ readonly enumTypeHandle?: EnumTypeHandle;
761
976
  }
762
977
  interface PrimaryKeyNode {
763
978
  readonly columns: readonly string[];
@@ -786,6 +1001,12 @@ interface ForeignKeyNode {
786
1001
  * know the target namespace can stamp it explicitly.
787
1002
  */
788
1003
  readonly namespaceId?: string;
1004
+ /**
1005
+ * Contract-space identity of the referenced table. When present, the
1006
+ * table lives in a different contract space (identified by this value)
1007
+ * rather than the current contract. Absent for local FKs.
1008
+ */
1009
+ readonly spaceId?: string;
789
1010
  };
790
1011
  readonly name?: string;
791
1012
  readonly onDelete?: ReferentialAction;
@@ -797,7 +1018,26 @@ interface RelationNode {
797
1018
  readonly fieldName: string;
798
1019
  readonly toModel: string;
799
1020
  readonly toTable: string;
1021
+ /**
1022
+ * Namespace coordinate of the related model. When omitted the assembler
1023
+ * resolves the coordinate from the referenced model node's own
1024
+ * `namespaceId`; the field exists so authoring paths that already know the
1025
+ * target namespace can stamp it explicitly — required to disambiguate a
1026
+ * relation to a model whose bare name also exists in another namespace.
1027
+ */
1028
+ readonly toNamespaceId?: string;
800
1029
  readonly cardinality: '1:1' | '1:N' | 'N:1' | 'N:M';
1030
+ /**
1031
+ * Contract-space identity of the related model. When present, the
1032
+ * related model lives in a different contract space. Absent for local
1033
+ * (same-space) relations.
1034
+ */
1035
+ readonly spaceId?: string;
1036
+ /**
1037
+ * Namespace coordinate of the related model in the foreign space.
1038
+ * Only set when `spaceId` is present.
1039
+ */
1040
+ readonly namespaceId?: string;
801
1041
  readonly on: {
802
1042
  readonly parentTable: string;
803
1043
  readonly parentColumns: readonly string[];
@@ -843,9 +1083,19 @@ interface ModelNode {
843
1083
  readonly indexes?: readonly IndexNode[];
844
1084
  readonly foreignKeys?: readonly ForeignKeyNode[];
845
1085
  readonly relations?: readonly RelationNode[];
1086
+ readonly control?: ControlPolicy;
1087
+ /**
1088
+ * Single-table-inheritance variants share their base model's storage table:
1089
+ * the variant's columns are materialised onto the base `ModelNode`, and this
1090
+ * model contributes a domain model but no storage table of its own. When set,
1091
+ * the assembler builds the domain model but skips creating a (shadow) storage
1092
+ * table and a root for this model — the base owns both.
1093
+ */
1094
+ readonly sharesBaseTable?: boolean;
846
1095
  }
847
1096
  interface ContractDefinition {
848
1097
  readonly target: TargetPackRef<'sql', string>;
1098
+ readonly defaultControlPolicy?: ControlPolicy;
849
1099
  readonly extensionPacks?: Record<string, ExtensionPackRef<'sql', string>>;
850
1100
  readonly storageHash?: string;
851
1101
  readonly foreignKeyDefaults?: ForeignKeyDefaultsState;
@@ -853,7 +1103,7 @@ interface ContractDefinition {
853
1103
  /**
854
1104
  * Enum types declared inside a named `namespace { enum … }` block,
855
1105
  * keyed first by namespace id then by type name. These are routed to
856
- * `storage.namespaces[nsId].enum` rather than the implicit fallback
1106
+ * `storage.namespaces[nsId].entries.type` rather than the implicit fallback
857
1107
  * namespace used for top-level `storageTypes` enums.
858
1108
  */
859
1109
  readonly namespaceTypes?: Readonly<Record<string, Readonly<Record<string, PostgresEnumStorageEntry>>>>;
@@ -866,10 +1116,19 @@ interface ContractDefinition {
866
1116
  * Target-supplied factory that materialises a `Namespace` concretion
867
1117
  * for a declared namespace coordinate. Mirrors
868
1118
  * `ContractInput.createNamespace`.
1119
+ *
1120
+ * The optional second argument carries target-specific enum types for the
1121
+ * namespace (e.g. postgres enum registrations keyed by type name).
869
1122
  */
870
- readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
1123
+ readonly createNamespace?: (input: SqlNamespaceTablesInput, enumTypes?: Readonly<Record<string, PostgresEnumStorageEntry>>) => Namespace;
871
1124
  readonly models: readonly ModelNode[];
872
1125
  readonly valueObjects?: readonly ValueObjectNode[];
1126
+ /**
1127
+ * Domain enum handles authored via `enumType()`. Each entry lowers to a
1128
+ * domain `enum` entry and a storage `valueSet` entry in the contract's
1129
+ * default namespace.
1130
+ */
1131
+ readonly enums?: Record<string, EnumTypeHandle>;
873
1132
  }
874
1133
  //#endregion
875
1134
  //#region src/build-contract.d.ts
@@ -895,11 +1154,13 @@ type ContractDefinition$1<Family extends FamilyPackRef<string>, Target extends T
895
1154
  readonly naming?: Naming;
896
1155
  readonly storageHash?: StorageHash;
897
1156
  readonly foreignKeyDefaults?: ForeignKeyDefaults;
1157
+ readonly defaultControlPolicy?: ControlPolicy;
898
1158
  readonly namespaces?: Namespaces;
899
1159
  readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
900
1160
  readonly types?: Types;
901
1161
  readonly models?: Models;
902
1162
  readonly codecLookup?: CodecLookup;
1163
+ readonly enums?: Record<string, EnumTypeHandle>;
903
1164
  };
904
1165
  type ContractScaffold<Family extends FamilyPackRef<string>, Target extends TargetPackRef<'sql', string>, ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined, Naming extends ContractInput['naming'] | undefined, StorageHash extends string | undefined, ForeignKeyDefaults extends ForeignKeyDefaultsState | undefined, Namespaces extends readonly string[] | undefined = undefined> = {
905
1166
  readonly family: Family;
@@ -908,18 +1169,53 @@ type ContractScaffold<Family extends FamilyPackRef<string>, Target extends Targe
908
1169
  readonly naming?: Naming;
909
1170
  readonly storageHash?: StorageHash;
910
1171
  readonly foreignKeyDefaults?: ForeignKeyDefaults;
1172
+ readonly defaultControlPolicy?: ControlPolicy;
911
1173
  readonly namespaces?: Namespaces;
912
1174
  readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
913
1175
  readonly types?: never;
914
1176
  readonly models?: never;
915
1177
  readonly codecLookup?: CodecLookup;
1178
+ readonly enums?: Record<string, EnumTypeHandle>;
916
1179
  };
917
1180
  type ContractFactory<Family extends FamilyPackRef<string>, Target extends TargetPackRef<'sql', string>, Types extends Record<string, StorageTypeInstance | PostgresEnumStorageEntry>, Models extends Record<string, ModelLike>, ExtensionPacks extends Record<string, ExtensionPackRef<'sql', string>> | undefined> = (helpers: ComposedAuthoringHelpers<Family, Target, ExtensionPacks>) => {
918
1181
  readonly types?: Types;
919
1182
  readonly models?: Models;
920
1183
  };
1184
+ 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> = {
1185
+ readonly extensionPacks?: ExtensionPacks;
1186
+ readonly naming?: Naming;
1187
+ readonly storageHash?: StorageHash;
1188
+ readonly foreignKeyDefaults?: ForeignKeyDefaults;
1189
+ readonly defaultControlPolicy?: ControlPolicy;
1190
+ readonly namespaces?: Namespaces;
1191
+ readonly createNamespace?: (input: SqlNamespaceTablesInput) => Namespace;
1192
+ readonly types?: Types;
1193
+ readonly models?: Models;
1194
+ readonly codecLookup?: CodecLookup;
1195
+ readonly enums?: Record<string, EnumTypeHandle>;
1196
+ };
1197
+ type WithFamilyTarget<Input, F extends FamilyPackRef<string>, T extends TargetPackRef<'sql', string>> = Input & {
1198
+ readonly family: F;
1199
+ readonly target: T;
1200
+ };
1201
+ /**
1202
+ * Shared builder that assembles a SqlContract with pre-bound family and target.
1203
+ * Extension wrappers keep their own public overloads and delegate their impl body here;
1204
+ * this is a plain overloaded function (not a factory returning an overloaded function)
1205
+ * so no overloaded-function-return cast is needed.
1206
+ *
1207
+ * Overload 1: definition form (no factory).
1208
+ */
1209
+ 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>>;
1210
+ /**
1211
+ * Overload 2: factory form.
1212
+ */
1213
+ 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 {
1214
+ readonly types?: Record<string, StorageTypeInstance | PostgresEnumStorageEntry>;
1215
+ readonly models?: Record<string, ModelLike>;
1216
+ }>(family: F, target: T, definition: Definition, factory: (helpers: ComposedAuthoringHelpers<F, T, NonNullable<Definition['extensionPacks']>>) => Built): SqlContractResult<WithFamilyTarget<Definition & Built, F, T>>;
921
1217
  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
1218
  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
1219
  //#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 };
1220
+ export { type ComposedAuthoringHelpers, type ContractDefinition, type ContractInput, type ContractModelBuilder, type EnumMember, type EnumTypeHandle, type FieldNode, type ForeignKeyNode, type IndexNode, type ModelLike, type ModelNode, type PrimaryKeyNode, type RelationNode, type ScalarFieldBuilder, type TargetFieldRef, type UniqueConstraintNode, buildBoundContract, buildSqlContractFromDefinition, defineContract, enumType, extensionModel, field, member, model, rel };
925
1221
  //# sourceMappingURL=contract-builder.d.mts.map