effect-qb 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +8065 -0
  3. package/dist/mysql.js +3053 -2505
  4. package/dist/postgres/metadata.js +1366 -1250
  5. package/dist/postgres.js +2020 -2719
  6. package/dist/sqlite.js +3226 -2732
  7. package/dist/standard.js +8019 -0
  8. package/package.json +10 -3
  9. package/src/casing.ts +71 -0
  10. package/src/index.ts +2 -0
  11. package/src/internal/casing.ts +89 -0
  12. package/src/internal/column-state.ts +11 -6
  13. package/src/internal/column.ts +44 -7
  14. package/src/internal/datatypes/define.ts +2 -1
  15. package/src/internal/datatypes/enrich.ts +23 -0
  16. package/src/internal/datatypes/lookup.ts +14 -7
  17. package/src/internal/derived-table.ts +4 -36
  18. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +548 -359
  19. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +654 -399
  20. package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +501 -345
  21. package/src/internal/dialect.ts +35 -0
  22. package/src/internal/dsl-mutation-runtime.ts +12 -162
  23. package/src/internal/dsl-plan-runtime.ts +10 -138
  24. package/src/internal/dsl-query-runtime.ts +5 -79
  25. package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
  26. package/src/internal/executor.ts +10 -6
  27. package/src/internal/grouping-key.ts +87 -20
  28. package/src/internal/implication-runtime.ts +1 -1
  29. package/src/internal/predicate/runtime.ts +3 -0
  30. package/src/internal/query.d.ts +38 -11
  31. package/src/internal/query.ts +64 -25
  32. package/src/internal/renderer.ts +26 -14
  33. package/src/internal/runtime/normalize.ts +12 -5
  34. package/src/internal/scalar.ts +6 -1
  35. package/src/internal/schema-derivation.d.ts +12 -61
  36. package/src/internal/schema-derivation.ts +90 -38
  37. package/src/internal/schema-expression.ts +2 -2
  38. package/src/internal/sql-expression-renderer.ts +19 -0
  39. package/src/internal/standard-dsl.ts +6885 -0
  40. package/src/internal/table-options.ts +126 -66
  41. package/src/internal/table.d.ts +33 -32
  42. package/src/internal/table.ts +406 -155
  43. package/src/mysql/column-extension.ts +3 -0
  44. package/src/mysql/column.ts +10 -11
  45. package/src/mysql/datatypes/index.ts +3 -2
  46. package/src/mysql/executor.ts +7 -5
  47. package/src/mysql/internal/dialect.ts +9 -4
  48. package/src/mysql/internal/dsl.ts +219 -155
  49. package/src/mysql/internal/renderer.ts +6 -2
  50. package/src/mysql/json.ts +37 -0
  51. package/src/mysql/query-extension.ts +16 -0
  52. package/src/mysql/renderer.ts +31 -4
  53. package/src/mysql.ts +4 -12
  54. package/src/postgres/column-extension.ts +28 -0
  55. package/src/postgres/column.ts +5 -11
  56. package/src/postgres/datatypes/index.d.ts +2 -1
  57. package/src/postgres/datatypes/index.ts +3 -2
  58. package/src/postgres/executor.ts +7 -5
  59. package/src/postgres/function/core.ts +1 -3
  60. package/src/postgres/function/index.ts +1 -17
  61. package/src/postgres/internal/dialect.ts +9 -4
  62. package/src/postgres/internal/dsl.ts +208 -160
  63. package/src/postgres/internal/renderer.ts +6 -2
  64. package/src/postgres/internal/schema-ddl.ts +22 -10
  65. package/src/postgres/internal/schema-model.ts +238 -7
  66. package/src/postgres/json.ts +43 -7
  67. package/src/postgres/jsonb.ts +38 -0
  68. package/src/postgres/query-extension.ts +2 -0
  69. package/src/postgres/renderer.ts +31 -4
  70. package/src/postgres/schema-management.ts +17 -12
  71. package/src/postgres/schema.ts +98 -15
  72. package/src/postgres/table.ts +193 -524
  73. package/src/postgres/type.ts +8 -7
  74. package/src/postgres.ts +9 -11
  75. package/src/sqlite/column-extension.ts +3 -0
  76. package/src/sqlite/column.ts +10 -11
  77. package/src/sqlite/datatypes/index.ts +3 -2
  78. package/src/sqlite/executor.ts +7 -5
  79. package/src/sqlite/internal/dialect.ts +9 -4
  80. package/src/sqlite/internal/dsl.ts +208 -155
  81. package/src/sqlite/internal/renderer.ts +6 -2
  82. package/src/sqlite/json.ts +37 -0
  83. package/src/sqlite/query-extension.ts +2 -0
  84. package/src/sqlite/renderer.ts +31 -4
  85. package/src/sqlite.ts +4 -12
  86. package/src/standard/column.ts +163 -0
  87. package/src/standard/datatypes/index.ts +83 -0
  88. package/src/standard/datatypes/spec.ts +98 -0
  89. package/src/standard/dialect.ts +40 -0
  90. package/src/standard/function/aggregate.ts +2 -0
  91. package/src/standard/function/core.ts +2 -0
  92. package/src/standard/function/index.ts +18 -0
  93. package/src/standard/function/string.ts +2 -0
  94. package/src/standard/function/temporal.ts +78 -0
  95. package/src/standard/function/window.ts +2 -0
  96. package/src/standard/internal/renderer.ts +45 -0
  97. package/src/standard/query.ts +152 -0
  98. package/src/standard/renderer.ts +21 -0
  99. package/src/standard/table.ts +147 -0
  100. package/src/standard.ts +18 -0
  101. package/src/internal/aggregation-validation.ts +0 -57
  102. package/src/mysql/table.ts +0 -183
  103. package/src/sqlite/table.ts +0 -183
@@ -12,8 +12,10 @@ import {
12
12
  resolvePrimaryKeyColumns,
13
13
  type DdlExpressionLike,
14
14
  type IndexKeySpec,
15
+ type LiteralStringInput,
15
16
  type MatchingColumnArityInput,
16
17
  type NonEmptyColumnInput,
18
+ type NonEmptyStringInput,
17
19
  type NormalizeColumns,
18
20
  type ReferentialAction,
19
21
  type TableOptionSpec,
@@ -24,12 +26,16 @@ import {
24
26
  validateOptions
25
27
  } from "./table-options.js"
26
28
  import {
27
- deriveSchemas,
29
+ deriveInsertSchema,
30
+ deriveSelectSchema,
31
+ deriveUpdateSchema,
28
32
  type InsertRow,
29
33
  type SelectRow,
30
34
  type TableFieldMap,
35
+ type TableSchemaVariant,
31
36
  type UpdateRow
32
37
  } from "./schema-derivation.js"
38
+ import * as Casing from "./casing.js"
33
39
 
34
40
  /** Symbol used to attach table-definition metadata. */
35
41
  export const TypeId: unique symbol = Symbol.for("effect-qb/Table")
@@ -39,15 +45,22 @@ export const OptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/normaliz
39
45
  export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOptions")
40
46
 
41
47
  const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
48
+ const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
42
49
  const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
43
50
 
44
51
  type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
45
52
  [K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never
46
53
  }[keyof Fields], string>
47
54
 
48
- type TableDialect<Fields extends TableFieldMap> = Fields[keyof Fields][typeof import("./column-state.js").ColumnTypeId]["dbType"]["dialect"]
55
+ type FieldDialects<Fields extends TableFieldMap> = Fields[keyof Fields][typeof import("./column-state.js").ColumnTypeId]["dbType"]["dialect"]
56
+ type ConcreteFieldDialects<Fields extends TableFieldMap> = Exclude<FieldDialects<Fields>, "standard">
57
+ type TableDialect<Fields extends TableFieldMap> = [ConcreteFieldDialects<Fields>] extends [never]
58
+ ? "standard"
59
+ : ConcreteFieldDialects<Fields>
49
60
  type TableKind = "schema" | "alias"
50
61
  type DefaultSchemaName = "public"
62
+ type NonEmptyFieldMap<Fields extends TableFieldMap> =
63
+ string extends keyof Fields ? Fields : "" extends keyof Fields ? never : Fields
51
64
  type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
52
65
  type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
53
66
  type FieldIndexKeySpec<Fields extends TableFieldMap> =
@@ -74,43 +87,79 @@ interface TableOptionBuilderLike<
74
87
 
75
88
  type ClassTableOption<Fields extends TableFieldMap> = TableOptionBuilderLike<ClassOptionSpec<Fields>>
76
89
  type ClassDeclaredTableOptions<Fields extends TableFieldMap> = readonly ClassTableOption<Fields>[]
90
+ type TableNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
91
+ Table extends TableDefinition<infer Name, any, any, "schema", any> ? Name : never
92
+ type TableFieldsOf<Table extends TableDefinition<any, any, any, "schema", any>> =
93
+ Table extends TableDefinition<any, infer Fields, any, "schema", any> ? Fields : never
94
+ type TablePrimaryKeyOf<Table extends TableDefinition<any, any, any, "schema", any>> =
95
+ Table extends TableDefinition<any, any, infer PrimaryKeyColumns, "schema", any> ? PrimaryKeyColumns : never
96
+ type TableSchemaNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
97
+ Table extends TableDefinition<any, any, any, "schema", infer SchemaName> ? SchemaName : never
77
98
 
78
99
  type BuildPrimaryKey<
79
100
  Table extends TableDefinition<any, any, any, "schema", any>,
80
101
  Spec extends TableOptionSpec
81
102
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
82
- ? Columns[number] & keyof Table[typeof TypeId]["fields"] & string
83
- : Table[typeof TypeId]["primaryKey"][number]
103
+ ? Columns[number] & keyof TableFieldsOf<Table> & string
104
+ : TablePrimaryKeyOf<Table>
84
105
 
85
- type OptionInputTable<
106
+ type OptionInputConstraint<
86
107
  Table extends TableDefinition<any, any, any, "schema", any>,
87
108
  Spec extends TableOptionSpec
88
109
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
89
- ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
110
+ ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
90
111
  : Spec extends { readonly kind: "index" }
91
- ? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
112
+ ? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
92
113
  : Spec extends { readonly kind: "foreignKey" }
93
- ? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
114
+ ? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
94
115
  : Spec extends { readonly columns: infer Columns extends readonly string[] }
95
- ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
96
- : Table
116
+ ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
117
+ : unknown
118
+
119
+ type OptionInputTable<
120
+ Table extends TableDefinition<any, any, any, "schema", any>,
121
+ Spec extends TableOptionSpec
122
+ > = Table & OptionInputConstraint<Table, Spec>
123
+
124
+ type OptionValidationArgs<
125
+ Table extends TableDefinition<any, any, any, "schema", any>,
126
+ Spec extends TableOptionSpec
127
+ > = OptionInputConstraint<Table, Spec> extends never ? [never] : []
97
128
 
98
129
  type ApplyOption<
99
130
  Table extends TableDefinition<any, any, any, "schema", any>,
100
131
  Spec extends TableOptionSpec
101
132
  > = Spec extends { readonly kind: "primaryKey" }
102
133
  ? TableDefinition<
103
- Table[typeof TypeId]["name"],
104
- Table[typeof TypeId]["fields"],
134
+ TableNameOf<Table>,
135
+ TableFieldsOf<Table>,
105
136
  BuildPrimaryKey<Table, Spec>,
106
- "schema"
107
- >
108
- : TableDefinition<
109
- Table[typeof TypeId]["name"],
110
- Table[typeof TypeId]["fields"],
111
- Table[typeof TypeId]["primaryKey"][number],
112
- "schema"
137
+ "schema",
138
+ TableSchemaNameOf<Table>
113
139
  >
140
+ : Table
141
+
142
+ type ApplyTableOption<
143
+ Table extends TableDefinition<any, any, any, "schema", any>,
144
+ Spec extends TableOptionSpec
145
+ > = Spec extends { readonly kind: "primaryKey" }
146
+ ? ApplyOption<Table, Spec>
147
+ : Table
148
+
149
+ type TableOptionPipe<
150
+ Name extends string,
151
+ Fields extends TableFieldMap,
152
+ PrimaryKeyColumns extends keyof Fields & string,
153
+ Kind extends TableKind,
154
+ SchemaName extends string | undefined
155
+ > = Kind extends "schema"
156
+ ? {
157
+ pipe<Spec extends TableOptionSpec>(
158
+ option: TableOption<Spec>,
159
+ ...validation: OptionValidationArgs<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Spec>
160
+ ): ApplyTableOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Spec>
161
+ }
162
+ : {}
114
163
 
115
164
  export type ValidateDeclaredOptions<
116
165
  Table extends TableDefinition<any, any, any, "schema", any>,
@@ -153,6 +202,20 @@ export interface TableSchemas<
153
202
  readonly update: Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
154
203
  }
155
204
 
205
+ type AnyTableSchemas = {
206
+ readonly select: Schema.Schema<any>
207
+ readonly insert: Schema.Schema<any>
208
+ readonly update: Schema.Schema<any>
209
+ }
210
+
211
+ type TableSchemaCache<
212
+ Name extends string,
213
+ Fields extends TableFieldMap,
214
+ PrimaryKeyColumns extends keyof Fields & string
215
+ > = Partial<TableSchemas<Name, Fields, PrimaryKeyColumns>> & {
216
+ schemas?: TableSchemas<Name, Fields, PrimaryKeyColumns>
217
+ }
218
+
156
219
  interface TableState<
157
220
  Name extends string,
158
221
  Fields extends TableFieldMap,
@@ -166,25 +229,14 @@ interface TableState<
166
229
  readonly fields: Fields
167
230
  readonly primaryKey: readonly PrimaryKeyColumns[]
168
231
  readonly kind: Kind
169
- }
170
-
171
- /** Namespace-scoped table builder. */
172
- export interface TableSchemaNamespace<SchemaName extends string> {
173
- readonly schemaName: SchemaName
174
- readonly table: <
175
- Name extends string,
176
- Fields extends TableFieldMap,
177
- const Options extends DeclaredTableOptions,
178
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
179
- >(
180
- name: Name,
181
- fields: Fields,
182
- ...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
183
- ) => ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
232
+ readonly casing?: Casing.Options
184
233
  }
185
234
 
186
235
  export type DeclaredTableOptions = readonly TableOptionBuilderLike[]
187
- export type { DdlExpressionLike, IndexKeySpec, MatchingColumnArityInput, NonEmptyColumnInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
236
+ export type { DdlExpressionLike, IndexKeySpec, LiteralStringInput, MatchingColumnArityInput, NonEmptyColumnInput, NonEmptyStringInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
237
+ export type { NonEmptyFieldMap }
238
+ export type NonEmptySchemaNameInput<Value extends string | undefined> =
239
+ Value extends string ? NonEmptyStringInput<Value> : Value
188
240
 
189
241
  export type TableDefinition<
190
242
  Name extends string,
@@ -192,10 +244,10 @@ export type TableDefinition<
192
244
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
193
245
  Kind extends TableKind = "schema",
194
246
  SchemaName extends string | undefined = DefaultSchemaName
195
- > = Pipeable & {
247
+ > = TableOptionPipe<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> & Pipeable & {
196
248
  readonly name: Name
197
249
  readonly columns: BoundColumns<Name, Fields>
198
- readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
250
+ readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns> & AnyTableSchemas
199
251
  readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName>
200
252
  readonly [Plan.TypeId]: Plan.State<
201
253
  BoundColumns<Name, Fields>,
@@ -245,32 +297,37 @@ export type TableClassStatic<
245
297
  >
246
298
 
247
299
  /** Minimal structural table-like contract used across helper APIs. */
248
- export type AnyTable = TableDefinition<any, any, any, any, any> | TableClassStatic<any, any, any, any>
300
+ export type AnyTable<Dialect extends string = string> = {
301
+ readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>
302
+ readonly [OptionsSymbol]: readonly TableOptionSpec[]
303
+ } & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>
249
304
 
250
- type FieldsOfAnyTable<Table extends AnyTable> = Table extends TableDefinition<any, infer Fields extends TableFieldMap, any, any, any>
251
- ? Fields
252
- : Table extends TableClassStatic<any, infer Fields extends TableFieldMap, any, any>
253
- ? Fields
254
- : never
305
+ type FieldsOfAnyTable<Table extends AnyTable> = Table[typeof TypeId]["fields"]
255
306
 
256
307
  type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
257
308
 
258
309
  /** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
259
310
  export type TableOption<
260
311
  Spec extends TableOptionSpec = TableOptionSpec
261
- > = {
262
- <
263
- Name extends string,
264
- Fields extends TableFieldMap,
265
- PrimaryKeyColumns extends keyof Fields & string
266
- >(
267
- table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
268
- ): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
312
+ > = Pipeable & {
313
+ readonly pipe: Pipeable["pipe"]
269
314
  readonly option: Spec
270
- }
315
+ } & (Spec extends { readonly kind: "primaryKey" }
316
+ ? {
317
+ <Table extends TableDefinition<any, any, any, "schema", any>>(
318
+ table: Table,
319
+ ...validation: OptionValidationArgs<Table, Spec>
320
+ ): ApplyOption<Table, Spec>
321
+ }
322
+ : {
323
+ <Table extends TableDefinition<any, any, any, "schema", any>>(
324
+ table: Table,
325
+ ...validation: OptionValidationArgs<Table, Spec>
326
+ ): Table
327
+ })
271
328
 
272
329
  const TableProto = {
273
- pipe(this: unknown) {
330
+ pipe(this: Pipeable) {
274
331
  return pipeArguments(this, arguments)
275
332
  }
276
333
  }
@@ -279,7 +336,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
279
336
  Object.defineProperty(value, "pipe", {
280
337
  configurable: true,
281
338
  writable: true,
282
- value: function(this: unknown) {
339
+ value: function(this: Value) {
283
340
  return pipeArguments(value, arguments)
284
341
  }
285
342
  })
@@ -292,7 +349,6 @@ type BuildArtifacts<
292
349
  PrimaryKeyColumns extends keyof Fields & string
293
350
  > = {
294
351
  readonly columns: BoundColumns<Name, Fields>
295
- readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
296
352
  readonly normalizedOptions: readonly TableOptionSpec[]
297
353
  readonly primaryKey: readonly PrimaryKeyColumns[]
298
354
  }
@@ -305,24 +361,159 @@ const buildArtifacts = <
305
361
  name: Name,
306
362
  fields: Fields,
307
363
  declaredOptions: readonly TableOptionSpec[],
308
- schemaName: SchemaName
364
+ schemaName: SchemaName,
365
+ casing?: Casing.Options
309
366
  ): BuildArtifacts<Name, Fields, keyof Fields & string> => {
310
367
  const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions]
311
368
  validateFieldDialects(name, fields)
312
369
  validateOptions(name, fields, declaredOptions)
313
370
  const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions) as readonly (keyof Fields & string)[]
314
371
  const columns = Object.fromEntries(
315
- Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)])
372
+ Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName, casing)])
316
373
  ) as BoundColumns<Name, Fields>
317
- const schemas = deriveSchemas(name, fields, primaryKey)
318
374
  return {
319
375
  columns,
320
- schemas,
321
376
  normalizedOptions,
322
377
  primaryKey
323
378
  }
324
379
  }
325
380
 
381
+ const getSchemaCache = <
382
+ Name extends string,
383
+ Fields extends TableFieldMap,
384
+ PrimaryKeyColumns extends keyof Fields & string
385
+ >(
386
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
387
+ ): TableSchemaCache<Name, Fields, PrimaryKeyColumns> => {
388
+ const target = table as {
389
+ [SchemaCacheSymbol]?: TableSchemaCache<Name, Fields, PrimaryKeyColumns>
390
+ }
391
+ if (target[SchemaCacheSymbol] !== undefined) {
392
+ return target[SchemaCacheSymbol]
393
+ }
394
+ const cache: TableSchemaCache<Name, Fields, PrimaryKeyColumns> = {}
395
+ Object.defineProperty(table, SchemaCacheSymbol, {
396
+ configurable: true,
397
+ value: cache
398
+ })
399
+ return cache
400
+ }
401
+
402
+ const deriveTableSchema = <
403
+ Variant extends TableSchemaVariant,
404
+ Name extends string,
405
+ Fields extends TableFieldMap,
406
+ PrimaryKeyColumns extends keyof Fields & string
407
+ >(
408
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
409
+ variant: Variant
410
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
411
+ const state = table[TypeId]
412
+ switch (variant) {
413
+ case "select":
414
+ return deriveSelectSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
415
+ case "insert":
416
+ return deriveInsertSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
417
+ case "update":
418
+ return deriveUpdateSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
419
+ }
420
+ }
421
+
422
+ const schemaFor = <
423
+ Variant extends TableSchemaVariant,
424
+ Name extends string,
425
+ Fields extends TableFieldMap,
426
+ PrimaryKeyColumns extends keyof Fields & string
427
+ >(
428
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
429
+ variant: Variant
430
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
431
+ const cache = getSchemaCache(table)
432
+ const cached = cache[variant]
433
+ if (cached !== undefined) {
434
+ return cached as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
435
+ }
436
+ const schema = deriveTableSchema(table, variant)
437
+ cache[variant] = schema as any
438
+ return schema
439
+ }
440
+
441
+ export function selectSchema<
442
+ Name extends string,
443
+ Fields extends TableFieldMap,
444
+ PrimaryKeyColumns extends keyof Fields & string
445
+ >(
446
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
447
+ ): Schema.Schema<SelectRow<Name, Fields>> {
448
+ return schemaFor(table, "select") as Schema.Schema<SelectRow<Name, Fields>>
449
+ }
450
+
451
+ export function insertSchema<
452
+ Name extends string,
453
+ Fields extends TableFieldMap,
454
+ PrimaryKeyColumns extends keyof Fields & string
455
+ >(
456
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
457
+ ): Schema.Schema<InsertRow<Name, Fields>> {
458
+ return schemaFor(table, "insert") as Schema.Schema<InsertRow<Name, Fields>>
459
+ }
460
+
461
+ export function updateSchema<
462
+ Name extends string,
463
+ Fields extends TableFieldMap,
464
+ PrimaryKeyColumns extends keyof Fields & string
465
+ >(
466
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
467
+ ): Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>> {
468
+ return schemaFor(table, "update") as Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
469
+ }
470
+
471
+ const schemasFor = <
472
+ Name extends string,
473
+ Fields extends TableFieldMap,
474
+ PrimaryKeyColumns extends keyof Fields & string
475
+ >(
476
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
477
+ ): TableSchemas<Name, Fields, PrimaryKeyColumns> => {
478
+ const cache = getSchemaCache(table)
479
+ if (cache.schemas !== undefined) {
480
+ return cache.schemas
481
+ }
482
+ const schemas = {} as TableSchemas<Name, Fields, PrimaryKeyColumns>
483
+ Object.defineProperties(schemas, {
484
+ select: {
485
+ enumerable: true,
486
+ get: () => selectSchema(table)
487
+ },
488
+ insert: {
489
+ enumerable: true,
490
+ get: () => insertSchema(table)
491
+ },
492
+ update: {
493
+ enumerable: true,
494
+ get: () => updateSchema(table)
495
+ }
496
+ })
497
+ cache.schemas = schemas
498
+ return schemas
499
+ }
500
+
501
+ const defineSchemasGetter = <
502
+ Name extends string,
503
+ Fields extends TableFieldMap,
504
+ PrimaryKeyColumns extends keyof Fields & string
505
+ >(
506
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any>
507
+ ): void => {
508
+ Object.defineProperty(table, "schemas", {
509
+ configurable: true,
510
+ enumerable: true,
511
+ get() {
512
+ return schemasFor(table)
513
+ }
514
+ })
515
+ }
516
+
326
517
  const makeTable = <
327
518
  Name extends string,
328
519
  Fields extends TableFieldMap,
@@ -336,24 +527,26 @@ const makeTable = <
336
527
  baseName: string = name,
337
528
  kind: Kind = "schema" as Kind,
338
529
  schemaName?: SchemaName,
339
- schemaMode: "default" | "explicit" = "default"
530
+ schemaMode: "default" | "explicit" = "default",
531
+ casing?: Casing.Options
340
532
  ): TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> => {
341
533
  const resolvedSchemaName = schemaMode === "explicit"
342
534
  ? schemaName
343
535
  : ("public" as SchemaName)
344
- const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName)
536
+ const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName, casing)
345
537
  const dialect = resolveFieldDialect(fields)
346
538
  const table = attachPipe(Object.create(TableProto))
347
539
  table.name = name
348
540
  table.columns = artifacts.columns
349
- table.schemas = artifacts.schemas
541
+ defineSchemasGetter(table)
350
542
  table[TypeId] = {
351
543
  name,
352
544
  baseName,
353
545
  schemaName: resolvedSchemaName,
354
546
  fields,
355
547
  primaryKey: artifacts.primaryKey,
356
- kind
548
+ kind,
549
+ casing
357
550
  }
358
551
  table[Plan.TypeId] = {
359
552
  selection: artifacts.columns,
@@ -400,23 +593,17 @@ const applyDeclaredOptions = <
400
593
  ) as unknown as Table
401
594
  }
402
595
 
403
- const validateClassOptions = (declaredOptions: readonly TableOptionSpec[]): void => {
404
- for (const option of declaredOptions) {
405
- if (option.kind === "primaryKey") {
406
- throw new Error("Table.Class does not support table-level primary keys; declare primary keys inline on columns")
407
- }
408
- }
409
- }
410
-
411
596
  const resolveFieldDialect = (fields: TableFieldMap): string => {
412
597
  const dialects = [...new Set(Object.values(fields).map((field) => field.metadata.dbType.dialect))]
413
598
  if (dialects.length === 0) {
414
599
  throw new Error("Cannot infer table dialect from an empty field set")
415
600
  }
416
- if (dialects.length > 1) {
601
+ const concreteDialects = dialects.filter((dialect) => dialect !== "standard")
602
+ const uniqueConcreteDialects = [...new Set(concreteDialects)]
603
+ if (uniqueConcreteDialects.length > 1) {
417
604
  throw new Error(`Mixed table dialects are not supported: ${dialects.join(", ")}`)
418
605
  }
419
- return dialects[0]!
606
+ return uniqueConcreteDialects[0] ?? "standard"
420
607
  }
421
608
 
422
609
  const validateFieldDialects = (tableName: string, fields: TableFieldMap): void => {
@@ -442,7 +629,6 @@ const ensureClassArtifacts = <
442
629
  }
443
630
  const state = self[TypeId]
444
631
  const classOptions = self[options]
445
- validateClassOptions(extractDeclaredOptions(classOptions))
446
632
  const table = applyDeclaredOptions(
447
633
  makeTable(
448
634
  state.name,
@@ -451,13 +637,13 @@ const ensureClassArtifacts = <
451
637
  state.name,
452
638
  "schema",
453
639
  state.schemaName,
454
- state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"
640
+ state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit",
641
+ state.casing
455
642
  ) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", typeof state.schemaName>,
456
643
  classOptions
457
644
  )
458
645
  const artifacts = {
459
646
  columns: table.columns,
460
- schemas: table.schemas,
461
647
  normalizedOptions: table[OptionsSymbol],
462
648
  primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
463
649
  } satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
@@ -476,9 +662,6 @@ const appendOption = <
476
662
  option: Spec
477
663
  ): ApplyOption<Table, Spec> => {
478
664
  const state = table[TypeId]
479
- if (state.kind !== "schema") {
480
- throw new Error("Table options can only be applied to schema tables, not aliased query sources")
481
- }
482
665
  return makeTable(
483
666
  state.name,
484
667
  state.fields,
@@ -486,25 +669,37 @@ const appendOption = <
486
669
  state.baseName,
487
670
  state.kind,
488
671
  state.schemaName,
489
- "explicit"
672
+ "explicit",
673
+ state.casing
490
674
  ) as unknown as ApplyOption<Table, Spec>
491
675
  }
492
676
 
493
677
  const makeOption = <Spec extends TableOptionSpec>(option: Spec): TableOption<Spec> => {
494
- const builder = ((table: TableDefinition<any, any, any, "schema", any>) =>
495
- appendOption(table, option)) as unknown as TableOption<Spec>
496
- ;(builder as { option: Spec }).option = option
497
- return builder
678
+ return attachPipe(Object.assign(
679
+ <Table extends TableDefinition<any, any, any, "schema", any>>(
680
+ table: Table,
681
+ ..._validation: OptionValidationArgs<Table, Spec>
682
+ ): ApplyTableOption<Table, Spec> =>
683
+ appendOption(table, option) as unknown as ApplyTableOption<Table, Spec>,
684
+ { option }
685
+ )) as TableOption<Spec>
498
686
  }
499
687
 
500
688
  const makeResolvedOption = <Spec extends TableOptionSpec>(
501
689
  option: Spec,
502
690
  resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
503
691
  ): TableOption<Spec> => {
504
- const builder = ((table: TableDefinition<any, any, any, "schema", any>) =>
505
- appendOption(table, resolve(table))) as unknown as TableOption<Spec>
506
- ;(builder as { option: Spec }).option = option
507
- return builder
692
+ return attachPipe(Object.assign(
693
+ <Table extends TableDefinition<any, any, any, "schema", any>>(
694
+ table: Table,
695
+ ..._validation: OptionValidationArgs<Table, Spec>
696
+ ): ApplyTableOption<Table, Spec> =>
697
+ appendOption(
698
+ table,
699
+ resolve(table)
700
+ ) as unknown as ApplyTableOption<Table, Spec>,
701
+ { option }
702
+ )) as TableOption<Spec>
508
703
  }
509
704
 
510
705
  export const option = <Spec extends TableOptionSpec>(spec: Spec): TableOption<Spec> =>
@@ -517,18 +712,30 @@ export const optionFromTable = <Spec extends TableOptionSpec>(
517
712
  makeResolvedOption(spec, resolve)
518
713
 
519
714
  /** Creates a table definition from a name and field map. */
715
+ export function make<
716
+ Name extends string,
717
+ Fields extends TableFieldMap
718
+ >(
719
+ name: NonEmptyStringInput<Name>,
720
+ fields: Fields & NonEmptyFieldMap<Fields>
721
+ ): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", DefaultSchemaName>
520
722
  export function make<
521
723
  Name extends string,
522
724
  Fields extends TableFieldMap,
523
- SchemaName extends string | undefined = DefaultSchemaName
725
+ const SchemaName extends string
524
726
  >(
525
- name: Name,
526
- fields: Fields,
527
- schemaName?: SchemaName
528
- ): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", SchemaName> {
727
+ name: NonEmptyStringInput<Name>,
728
+ fields: Fields & NonEmptyFieldMap<Fields>,
729
+ schemaName: NonEmptySchemaNameInput<SchemaName>
730
+ ): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", SchemaName>
731
+ export function make(
732
+ name: string,
733
+ fields: TableFieldMap,
734
+ schemaName?: string
735
+ ): TableDefinition<string, TableFieldMap, string, "schema", string | undefined> {
529
736
  const resolvedSchemaName = arguments.length >= 3
530
737
  ? schemaName
531
- : ("public" as SchemaName)
738
+ : "public"
532
739
  return makeTable(
533
740
  name,
534
741
  fields,
@@ -540,38 +747,56 @@ export function make<
540
747
  )
541
748
  }
542
749
 
543
- /**
544
- * Creates a namespace-scoped builder for a concrete SQL schema/database.
545
- */
546
- export const schema = <SchemaName extends string>(
547
- schemaName: SchemaName
548
- ): TableSchemaNamespace<SchemaName> => {
549
- const table = <
550
- Name extends string,
551
- Fields extends TableFieldMap,
552
- const Options extends DeclaredTableOptions,
553
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
554
- >(
555
- name: Name,
556
- fields: Fields,
557
- ...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
558
- ): ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options> =>
559
- applyDeclaredOptions(
560
- makeTable(
561
- name,
562
- fields,
563
- [],
564
- name,
565
- "schema",
566
- schemaName,
567
- "explicit"
568
- ) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
569
- options as unknown as Options
570
- ) as ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
571
- return {
750
+ export const withCasing = <
751
+ Table extends TableDefinition<any, any, any, any, any>
752
+ >(
753
+ table: Table,
754
+ casing: Casing.Options
755
+ ): Table => {
756
+ const state = table[TypeId]
757
+ return makeTable(
758
+ state.name,
759
+ state.fields,
760
+ table[DeclaredOptionsSymbol],
761
+ state.baseName,
762
+ state.kind,
763
+ state.schemaName,
764
+ "explicit",
765
+ Casing.merge(state.casing, casing)
766
+ ) as Table
767
+ }
768
+
769
+ export const withSchema = <
770
+ Table extends TableDefinition<any, any, any, any, any>,
771
+ SchemaName extends string
772
+ >(
773
+ table: Table,
774
+ schemaName: SchemaName,
775
+ schemaCasing?: Casing.Options
776
+ ): TableDefinition<
777
+ Table[typeof TypeId]["name"],
778
+ Table[typeof TypeId]["fields"],
779
+ Table[typeof TypeId]["primaryKey"][number],
780
+ Table[typeof TypeId]["kind"],
781
+ SchemaName
782
+ > => {
783
+ const state = table[TypeId]
784
+ return makeTable(
785
+ state.name,
786
+ state.fields,
787
+ table[DeclaredOptionsSymbol],
788
+ state.baseName,
789
+ state.kind,
572
790
  schemaName,
573
- table
574
- } as unknown as TableSchemaNamespace<SchemaName>
791
+ "explicit",
792
+ Casing.merge(schemaCasing, state.casing)
793
+ ) as TableDefinition<
794
+ Table[typeof TypeId]["name"],
795
+ Table[typeof TypeId]["fields"],
796
+ Table[typeof TypeId]["primaryKey"][number],
797
+ Table[typeof TypeId]["kind"],
798
+ SchemaName
799
+ >
575
800
  }
576
801
 
577
802
  /**
@@ -589,7 +814,7 @@ export const alias = <
589
814
  AliasName extends string
590
815
  >(
591
816
  table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName>,
592
- aliasName: AliasName
817
+ aliasName: LiteralStringInput<AliasName>
593
818
  ): TableDefinition<
594
819
  AliasName,
595
820
  Fields,
@@ -599,26 +824,27 @@ export const alias = <
599
824
  > => {
600
825
  const state = table[TypeId]
601
826
  const columns = Object.fromEntries(
602
- Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column as AnyColumnDefinition, state.baseName, state.schemaName)])
827
+ Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName as AliasName, key, column as AnyColumnDefinition, state.baseName, state.schemaName, state.casing)])
603
828
  ) as BoundColumns<AliasName, Fields>
604
829
  const aliased = attachPipe(Object.create(TableProto))
605
- aliased.name = aliasName
830
+ aliased.name = aliasName as AliasName
606
831
  aliased.columns = columns
607
- aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey)
832
+ defineSchemasGetter(aliased)
608
833
  aliased[TypeId] = {
609
- name: aliasName,
834
+ name: aliasName as AliasName,
610
835
  baseName: state.baseName,
611
836
  schemaName: state.schemaName,
612
837
  fields: state.fields,
613
838
  primaryKey: state.primaryKey,
614
- kind: "alias"
839
+ kind: "alias",
840
+ casing: state.casing
615
841
  }
616
842
  aliased[Plan.TypeId] = {
617
843
  selection: columns,
618
844
  required: undefined as never,
619
845
  available: {
620
846
  [aliasName]: {
621
- name: aliasName,
847
+ name: aliasName as AliasName,
622
848
  mode: "required",
623
849
  baseName: state.baseName
624
850
  }
@@ -642,19 +868,38 @@ export const alias = <
642
868
  * The returned base class can be extended and configured with
643
869
  * `static readonly [Table.options]`.
644
870
  */
871
+ export function Class<Self = never>(
872
+ name: "",
873
+ schemaName?: string | undefined
874
+ ): never
875
+ export function Class<Self = never>(
876
+ name: string,
877
+ schemaName: ""
878
+ ): never
645
879
  export function Class<
646
880
  Self = never,
647
- SchemaName extends string | undefined = DefaultSchemaName
881
+ const SchemaName extends string | undefined = DefaultSchemaName,
882
+ const Name extends string = string
883
+ >(
884
+ name: NonEmptyStringInput<Name>,
885
+ schemaName?: NonEmptySchemaNameInput<SchemaName>
886
+ ): <Fields extends TableFieldMap>(fields: Fields & NonEmptyFieldMap<Fields>) => [Self] extends [never]
887
+ ? MissingSelfGeneric
888
+ : TableClassStatic<Name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName>
889
+ export function Class<
890
+ Self = never,
891
+ SchemaName extends string | undefined = DefaultSchemaName,
892
+ Name extends string = string
648
893
  >(
649
894
  name: string,
650
895
  schemaName?: SchemaName
651
- ) {
896
+ ): any {
652
897
  const resolvedSchemaName = arguments.length >= 2
653
898
  ? schemaName
654
899
  : ("public" as SchemaName)
655
- return <Fields extends TableFieldMap>(fields: Fields): [Self] extends [never]
900
+ return <Fields extends TableFieldMap>(fields: Fields & NonEmptyFieldMap<Fields>): [Self] extends [never]
656
901
  ? MissingSelfGeneric
657
- : TableClassStatic<typeof name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName> => {
902
+ : TableClassStatic<Name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName> => {
658
903
  abstract class TableClassBase {
659
904
  static readonly tableName = name
660
905
 
@@ -663,12 +908,11 @@ export function Class<
663
908
  }
664
909
 
665
910
  static get schemas() {
666
- return ensureClassArtifacts(this as any).schemas
911
+ return schemasFor(this as any)
667
912
  }
668
913
 
669
914
  static get [TypeId]() {
670
- const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<typeof name, Fields>)[options])
671
- validateClassOptions(declaredOptions)
915
+ const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<Name, Fields>)[options])
672
916
  return {
673
917
  name,
674
918
  baseName: name,
@@ -699,7 +943,7 @@ export function Class<
699
943
  return ensureClassArtifacts(this as any).normalizedOptions
700
944
  }
701
945
 
702
- static pipe(this: unknown) {
946
+ static pipe(this: Pipeable) {
703
947
  return pipeArguments(this, arguments)
704
948
  }
705
949
  }
@@ -781,14 +1025,15 @@ export const foreignKey = <
781
1025
  references: () => ({
782
1026
  tableName: target()[TypeId].baseName,
783
1027
  schemaName: target()[TypeId].schemaName,
1028
+ casing: target()[TypeId].casing,
784
1029
  columns: normalizeColumnList(referencedColumns) as NormalizeColumns<TargetColumns>,
785
- knownColumns: Object.keys(target()[TypeId].fields) as unknown as readonly ColumnNamesOfAnyTable<TargetTable>[]
1030
+ knownColumns: Object.keys(target()[TypeId].fields).map((key) => key as ColumnNamesOfAnyTable<TargetTable>)
786
1031
  })
787
1032
  })
788
1033
 
789
1034
  /** Declares a check constraint expression. */
790
- export const check = <Name extends string>(
791
- name: Name,
1035
+ export const check = <const Name extends string>(
1036
+ name: NonEmptyStringInput<Name>,
792
1037
  predicate: DdlExpressionLike
793
1038
  ): TableOption<{
794
1039
  readonly kind: "check"
@@ -800,15 +1045,21 @@ export const check = <Name extends string>(
800
1045
  predicate
801
1046
  })
802
1047
 
803
- /** Extracts the row type of a table's select schema. */
804
- export type SelectOf<Table extends { readonly schemas: { readonly select: Schema.Schema<any> } }> = Schema.Schema.Type<
805
- Table["schemas"]["select"]
806
- >
807
- /** Extracts the payload type of a table's insert schema. */
808
- export type InsertOf<Table extends { readonly schemas: { readonly insert: Schema.Schema<any> } }> = Schema.Schema.Type<
809
- Table["schemas"]["insert"]
810
- >
811
- /** Extracts the payload type of a table's update schema. */
812
- export type UpdateOf<Table extends { readonly schemas: { readonly update: Schema.Schema<any> } }> = Schema.Schema.Type<
813
- Table["schemas"]["update"]
814
- >
1048
+ /** Extracts the row type produced by `selectSchema(table)`. */
1049
+ export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
1050
+ readonly name: infer Name extends string
1051
+ readonly fields: infer Fields extends TableFieldMap
1052
+ } ? SelectRow<Name, Fields> : never
1053
+
1054
+ /** Extracts the payload type produced by `insertSchema(table)`. */
1055
+ export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
1056
+ readonly name: infer Name extends string
1057
+ readonly fields: infer Fields extends TableFieldMap
1058
+ } ? InsertRow<Name, Fields> : never
1059
+
1060
+ /** Extracts the payload type produced by `updateSchema(table)`. */
1061
+ export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
1062
+ readonly name: infer Name extends string
1063
+ readonly fields: infer Fields extends TableFieldMap
1064
+ readonly primaryKey: readonly (infer PrimaryKeyColumns)[]
1065
+ } ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never