effect-qb 0.16.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 (128) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +8065 -0
  3. package/dist/mysql.js +4036 -2418
  4. package/dist/postgres/metadata.js +2536 -625
  5. package/dist/postgres.js +8248 -7857
  6. package/dist/sqlite.js +8854 -0
  7. package/dist/standard.js +8019 -0
  8. package/package.json +15 -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 +7 -13
  18. package/src/internal/dialect-renderers/mysql.ts +2046 -0
  19. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +867 -283
  20. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +834 -358
  21. package/src/internal/dialect.ts +37 -0
  22. package/src/internal/dsl-mutation-runtime.ts +29 -10
  23. package/src/internal/dsl-plan-runtime.ts +41 -24
  24. package/src/internal/dsl-query-runtime.ts +11 -31
  25. package/src/internal/dsl-transaction-ddl-runtime.ts +61 -15
  26. package/src/internal/executor.ts +57 -15
  27. package/src/internal/expression-ast.ts +3 -2
  28. package/src/internal/grouping-key.ts +216 -9
  29. package/src/internal/implication-runtime.ts +3 -2
  30. package/src/internal/json/types.ts +155 -40
  31. package/src/internal/predicate/context.ts +14 -1
  32. package/src/internal/predicate/key.ts +19 -2
  33. package/src/internal/predicate/runtime.ts +30 -3
  34. package/src/internal/query.d.ts +38 -11
  35. package/src/internal/query.ts +315 -54
  36. package/src/internal/renderer.ts +51 -6
  37. package/src/internal/runtime/driver-value-mapping.ts +58 -0
  38. package/src/internal/runtime/normalize.ts +74 -43
  39. package/src/internal/runtime/schema.ts +5 -3
  40. package/src/internal/runtime/value.ts +153 -30
  41. package/src/internal/scalar.ts +6 -1
  42. package/src/internal/schema-derivation.d.ts +12 -61
  43. package/src/internal/schema-derivation.ts +90 -38
  44. package/src/internal/schema-expression.ts +2 -2
  45. package/src/internal/sql-expression-renderer.ts +19 -0
  46. package/src/internal/standard-dsl.ts +6885 -0
  47. package/src/internal/table-options.ts +229 -62
  48. package/src/internal/table.d.ts +33 -32
  49. package/src/internal/table.ts +469 -160
  50. package/src/mysql/column-extension.ts +3 -0
  51. package/src/mysql/column.ts +27 -12
  52. package/src/mysql/datatypes/index.ts +24 -2
  53. package/src/mysql/errors/catalog.ts +5 -5
  54. package/src/mysql/errors/normalize.ts +2 -2
  55. package/src/mysql/executor.ts +7 -5
  56. package/src/mysql/internal/dialect.ts +9 -4
  57. package/src/mysql/internal/dsl.ts +906 -324
  58. package/src/mysql/internal/renderer.ts +7 -2
  59. package/src/mysql/json.ts +37 -0
  60. package/src/mysql/query-extension.ts +16 -0
  61. package/src/mysql/query.ts +9 -2
  62. package/src/mysql/renderer.ts +31 -4
  63. package/src/mysql.ts +4 -12
  64. package/src/postgres/column-extension.ts +28 -0
  65. package/src/postgres/column.ts +9 -13
  66. package/src/postgres/datatypes/index.d.ts +2 -1
  67. package/src/postgres/datatypes/index.ts +3 -2
  68. package/src/postgres/errors/normalize.ts +2 -2
  69. package/src/postgres/executor.ts +55 -10
  70. package/src/postgres/function/core.ts +20 -4
  71. package/src/postgres/function/index.ts +1 -17
  72. package/src/postgres/internal/dialect.ts +9 -4
  73. package/src/postgres/internal/dsl.ts +850 -359
  74. package/src/postgres/internal/renderer.ts +7 -2
  75. package/src/postgres/internal/schema-ddl.ts +22 -9
  76. package/src/postgres/internal/schema-model.ts +244 -10
  77. package/src/postgres/json.ts +100 -24
  78. package/src/postgres/jsonb.ts +38 -0
  79. package/src/postgres/query-extension.ts +2 -0
  80. package/src/postgres/query.ts +9 -2
  81. package/src/postgres/renderer.ts +31 -4
  82. package/src/postgres/schema-management.ts +108 -16
  83. package/src/postgres/schema.ts +98 -15
  84. package/src/postgres/table.ts +203 -398
  85. package/src/postgres/type.ts +8 -7
  86. package/src/postgres.ts +9 -11
  87. package/src/sqlite/column-extension.ts +3 -0
  88. package/src/sqlite/column.ts +127 -0
  89. package/src/sqlite/datatypes/index.ts +80 -0
  90. package/src/sqlite/datatypes/spec.ts +98 -0
  91. package/src/sqlite/errors/catalog.ts +103 -0
  92. package/src/sqlite/errors/fields.ts +19 -0
  93. package/src/sqlite/errors/index.ts +19 -0
  94. package/src/sqlite/errors/normalize.ts +229 -0
  95. package/src/sqlite/errors/requirements.ts +71 -0
  96. package/src/sqlite/errors/types.ts +29 -0
  97. package/src/sqlite/executor.ts +229 -0
  98. package/src/sqlite/function/aggregate.ts +2 -0
  99. package/src/sqlite/function/core.ts +2 -0
  100. package/src/sqlite/function/index.ts +19 -0
  101. package/src/sqlite/function/string.ts +2 -0
  102. package/src/sqlite/function/temporal.ts +100 -0
  103. package/src/sqlite/function/window.ts +2 -0
  104. package/src/sqlite/internal/dialect.ts +42 -0
  105. package/src/sqlite/internal/dsl.ts +6979 -0
  106. package/src/sqlite/internal/renderer.ts +51 -0
  107. package/src/sqlite/json.ts +39 -0
  108. package/src/sqlite/query-extension.ts +2 -0
  109. package/src/sqlite/query.ts +196 -0
  110. package/src/sqlite/renderer.ts +51 -0
  111. package/src/sqlite.ts +14 -0
  112. package/src/standard/column.ts +163 -0
  113. package/src/standard/datatypes/index.ts +83 -0
  114. package/src/standard/datatypes/spec.ts +98 -0
  115. package/src/standard/dialect.ts +40 -0
  116. package/src/standard/function/aggregate.ts +2 -0
  117. package/src/standard/function/core.ts +2 -0
  118. package/src/standard/function/index.ts +18 -0
  119. package/src/standard/function/string.ts +2 -0
  120. package/src/standard/function/temporal.ts +78 -0
  121. package/src/standard/function/window.ts +2 -0
  122. package/src/standard/internal/renderer.ts +45 -0
  123. package/src/standard/query.ts +152 -0
  124. package/src/standard/renderer.ts +21 -0
  125. package/src/standard/table.ts +147 -0
  126. package/src/standard.ts +18 -0
  127. package/src/internal/aggregation-validation.ts +0 -57
  128. package/src/mysql/table.ts +0 -157
@@ -12,20 +12,30 @@ import {
12
12
  resolvePrimaryKeyColumns,
13
13
  type DdlExpressionLike,
14
14
  type IndexKeySpec,
15
+ type LiteralStringInput,
16
+ type MatchingColumnArityInput,
17
+ type NonEmptyColumnInput,
18
+ type NonEmptyStringInput,
15
19
  type NormalizeColumns,
16
20
  type ReferentialAction,
17
21
  type TableOptionSpec,
22
+ type ValidateForeignKeyOptionColumns,
23
+ type ValidateIndexOptionColumns,
18
24
  type ValidateKnownColumns,
19
25
  type ValidatePrimaryKeyColumns,
20
26
  validateOptions
21
27
  } from "./table-options.js"
22
28
  import {
23
- deriveSchemas,
29
+ deriveInsertSchema,
30
+ deriveSelectSchema,
31
+ deriveUpdateSchema,
24
32
  type InsertRow,
25
33
  type SelectRow,
26
34
  type TableFieldMap,
35
+ type TableSchemaVariant,
27
36
  type UpdateRow
28
37
  } from "./schema-derivation.js"
38
+ import * as Casing from "./casing.js"
29
39
 
30
40
  /** Symbol used to attach table-definition metadata. */
31
41
  export const TypeId: unique symbol = Symbol.for("effect-qb/Table")
@@ -35,60 +45,141 @@ export const OptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/normaliz
35
45
  export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOptions")
36
46
 
37
47
  const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
48
+ const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
38
49
  const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
39
50
 
40
51
  type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
41
52
  [K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never
42
53
  }[keyof Fields], string>
43
54
 
44
- 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>
45
60
  type TableKind = "schema" | "alias"
46
61
  type DefaultSchemaName = "public"
47
- type ClassOptionSpec = Exclude<TableOptionSpec, { readonly kind: "primaryKey" }>
62
+ type NonEmptyFieldMap<Fields extends TableFieldMap> =
63
+ string extends keyof Fields ? Fields : "" extends keyof Fields ? never : Fields
64
+ type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
65
+ type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
66
+ type FieldIndexKeySpec<Fields extends TableFieldMap> =
67
+ | (Extract<IndexKeySpec, { readonly kind: "column" }> & { readonly column: FieldColumnName<Fields> })
68
+ | Extract<IndexKeySpec, { readonly kind: "expression" }>
69
+ type ClassOptionSpec<Fields extends TableFieldMap = TableFieldMap> =
70
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "index" }>, "columns" | "include" | "keys"> & {
71
+ readonly columns?: FieldColumnList<Fields>
72
+ readonly include?: readonly FieldColumnName<Fields>[]
73
+ readonly keys?: readonly [FieldIndexKeySpec<Fields>, ...FieldIndexKeySpec<Fields>[]]
74
+ })
75
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "unique" }>, "columns"> & {
76
+ readonly columns: FieldColumnList<Fields>
77
+ })
78
+ | (Omit<Extract<TableOptionSpec, { readonly kind: "foreignKey" }>, "columns"> & {
79
+ readonly columns: FieldColumnList<Fields>
80
+ })
81
+ | Extract<TableOptionSpec, { readonly kind: "check" }>
48
82
  interface TableOptionBuilderLike<
49
83
  Spec extends TableOptionSpec = TableOptionSpec
50
84
  > {
51
- (
52
- table: TableDefinition<any, any, any, "schema", any>
53
- ): TableDefinition<any, any, any, "schema", any>
54
85
  readonly option: Spec
55
86
  }
56
87
 
57
- type ClassTableOption = TableOptionBuilderLike<ClassOptionSpec>
58
- type ClassDeclaredTableOptions = readonly ClassTableOption[]
88
+ type ClassTableOption<Fields extends TableFieldMap> = TableOptionBuilderLike<ClassOptionSpec<Fields>>
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
59
98
 
60
99
  type BuildPrimaryKey<
61
100
  Table extends TableDefinition<any, any, any, "schema", any>,
62
101
  Spec extends TableOptionSpec
63
102
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
64
- ? Columns[number] & keyof Table[typeof TypeId]["fields"] & string
65
- : Table[typeof TypeId]["primaryKey"][number]
103
+ ? Columns[number] & keyof TableFieldsOf<Table> & string
104
+ : TablePrimaryKeyOf<Table>
66
105
 
67
- type OptionInputTable<
106
+ type OptionInputConstraint<
68
107
  Table extends TableDefinition<any, any, any, "schema", any>,
69
108
  Spec extends TableOptionSpec
70
109
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
71
- ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
72
- : Spec extends { readonly columns: infer Columns extends readonly string[] }
73
- ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
74
- : Table
110
+ ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
111
+ : Spec extends { readonly kind: "index" }
112
+ ? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
113
+ : Spec extends { readonly kind: "foreignKey" }
114
+ ? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
115
+ : Spec extends { readonly columns: infer Columns extends readonly string[] }
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] : []
75
128
 
76
129
  type ApplyOption<
77
130
  Table extends TableDefinition<any, any, any, "schema", any>,
78
131
  Spec extends TableOptionSpec
79
132
  > = Spec extends { readonly kind: "primaryKey" }
80
133
  ? TableDefinition<
81
- Table[typeof TypeId]["name"],
82
- Table[typeof TypeId]["fields"],
134
+ TableNameOf<Table>,
135
+ TableFieldsOf<Table>,
83
136
  BuildPrimaryKey<Table, Spec>,
84
- "schema"
85
- >
86
- : TableDefinition<
87
- Table[typeof TypeId]["name"],
88
- Table[typeof TypeId]["fields"],
89
- Table[typeof TypeId]["primaryKey"][number],
90
- "schema"
137
+ "schema",
138
+ TableSchemaNameOf<Table>
91
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
+ : {}
163
+
164
+ export type ValidateDeclaredOptions<
165
+ Table extends TableDefinition<any, any, any, "schema", any>,
166
+ Options extends DeclaredTableOptions
167
+ > = {
168
+ readonly [K in keyof Options]: Options[K] extends TableOptionBuilderLike<infer Spec>
169
+ ? OptionInputTable<Table, Spec> extends never ? never : Options[K]
170
+ : never
171
+ }
172
+
173
+ export type ApplyDeclaredOptions<
174
+ Table extends TableDefinition<any, any, any, "schema", any>,
175
+ Options extends DeclaredTableOptions
176
+ > = Options extends readonly [infer Head, ...infer Tail]
177
+ ? Head extends TableOptionBuilderLike<infer Spec>
178
+ ? Tail extends DeclaredTableOptions
179
+ ? ApplyDeclaredOptions<ApplyOption<Table, Spec>, Tail>
180
+ : ApplyOption<Table, Spec>
181
+ : Table
182
+ : Table
92
183
 
93
184
  export type MissingSelfGeneric = "Missing `Self` generic - use `class Self extends Table.Class<Self>(...) {}`"
94
185
 
@@ -111,6 +202,20 @@ export interface TableSchemas<
111
202
  readonly update: Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
112
203
  }
113
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
+
114
219
  interface TableState<
115
220
  Name extends string,
116
221
  Fields extends TableFieldMap,
@@ -124,24 +229,14 @@ interface TableState<
124
229
  readonly fields: Fields
125
230
  readonly primaryKey: readonly PrimaryKeyColumns[]
126
231
  readonly kind: Kind
127
- }
128
-
129
- /** Namespace-scoped table builder. */
130
- export interface TableSchemaNamespace<SchemaName extends string> {
131
- readonly schemaName: SchemaName
132
- readonly table: <
133
- Name extends string,
134
- Fields extends TableFieldMap,
135
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
136
- >(
137
- name: Name,
138
- fields: Fields,
139
- ...options: DeclaredTableOptions
140
- ) => TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
232
+ readonly casing?: Casing.Options
141
233
  }
142
234
 
143
235
  export type DeclaredTableOptions = readonly TableOptionBuilderLike[]
144
- export type { DdlExpressionLike, IndexKeySpec, 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
145
240
 
146
241
  export type TableDefinition<
147
242
  Name extends string,
@@ -149,10 +244,10 @@ export type TableDefinition<
149
244
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
150
245
  Kind extends TableKind = "schema",
151
246
  SchemaName extends string | undefined = DefaultSchemaName
152
- > = Pipeable & {
247
+ > = TableOptionPipe<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> & Pipeable & {
153
248
  readonly name: Name
154
249
  readonly columns: BoundColumns<Name, Fields>
155
- readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
250
+ readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns> & AnyTableSchemas
156
251
  readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName>
157
252
  readonly [Plan.TypeId]: Plan.State<
158
253
  BoundColumns<Name, Fields>,
@@ -192,7 +287,7 @@ export type TableClassStatic<
192
287
  >
193
288
  readonly [OptionsSymbol]: readonly TableOptionSpec[]
194
289
  readonly [DeclaredOptionsSymbol]?: readonly TableOptionSpec[]
195
- readonly [options]?: ClassDeclaredTableOptions
290
+ readonly [options]?: ClassDeclaredTableOptions<Fields>
196
291
  readonly tableName: Name
197
292
  } & BoundColumns<Name, Fields> & Plan.RowSet<
198
293
  BoundColumns<Name, Fields>,
@@ -202,24 +297,37 @@ export type TableClassStatic<
202
297
  >
203
298
 
204
299
  /** Minimal structural table-like contract used across helper APIs. */
205
- 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>
304
+
305
+ type FieldsOfAnyTable<Table extends AnyTable> = Table[typeof TypeId]["fields"]
306
+
307
+ type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
206
308
 
207
309
  /** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
208
310
  export type TableOption<
209
311
  Spec extends TableOptionSpec = TableOptionSpec
210
- > = {
211
- <
212
- Name extends string,
213
- Fields extends TableFieldMap,
214
- PrimaryKeyColumns extends keyof Fields & string
215
- >(
216
- table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
217
- ): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
312
+ > = Pipeable & {
313
+ readonly pipe: Pipeable["pipe"]
218
314
  readonly option: Spec
219
- }
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
+ })
220
328
 
221
329
  const TableProto = {
222
- pipe(this: unknown) {
330
+ pipe(this: Pipeable) {
223
331
  return pipeArguments(this, arguments)
224
332
  }
225
333
  }
@@ -228,7 +336,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
228
336
  Object.defineProperty(value, "pipe", {
229
337
  configurable: true,
230
338
  writable: true,
231
- value: function(this: unknown) {
339
+ value: function(this: Value) {
232
340
  return pipeArguments(value, arguments)
233
341
  }
234
342
  })
@@ -241,7 +349,6 @@ type BuildArtifacts<
241
349
  PrimaryKeyColumns extends keyof Fields & string
242
350
  > = {
243
351
  readonly columns: BoundColumns<Name, Fields>
244
- readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
245
352
  readonly normalizedOptions: readonly TableOptionSpec[]
246
353
  readonly primaryKey: readonly PrimaryKeyColumns[]
247
354
  }
@@ -254,24 +361,159 @@ const buildArtifacts = <
254
361
  name: Name,
255
362
  fields: Fields,
256
363
  declaredOptions: readonly TableOptionSpec[],
257
- schemaName: SchemaName
364
+ schemaName: SchemaName,
365
+ casing?: Casing.Options
258
366
  ): BuildArtifacts<Name, Fields, keyof Fields & string> => {
259
367
  const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions]
260
368
  validateFieldDialects(name, fields)
261
369
  validateOptions(name, fields, declaredOptions)
262
370
  const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions) as readonly (keyof Fields & string)[]
263
371
  const columns = Object.fromEntries(
264
- 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)])
265
373
  ) as BoundColumns<Name, Fields>
266
- const schemas = deriveSchemas(name, fields, primaryKey)
267
374
  return {
268
375
  columns,
269
- schemas,
270
376
  normalizedOptions,
271
377
  primaryKey
272
378
  }
273
379
  }
274
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
+
275
517
  const makeTable = <
276
518
  Name extends string,
277
519
  Fields extends TableFieldMap,
@@ -285,24 +527,26 @@ const makeTable = <
285
527
  baseName: string = name,
286
528
  kind: Kind = "schema" as Kind,
287
529
  schemaName?: SchemaName,
288
- schemaMode: "default" | "explicit" = "default"
530
+ schemaMode: "default" | "explicit" = "default",
531
+ casing?: Casing.Options
289
532
  ): TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> => {
290
533
  const resolvedSchemaName = schemaMode === "explicit"
291
534
  ? schemaName
292
535
  : ("public" as SchemaName)
293
- const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName)
536
+ const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName, casing)
294
537
  const dialect = resolveFieldDialect(fields)
295
538
  const table = attachPipe(Object.create(TableProto))
296
539
  table.name = name
297
540
  table.columns = artifacts.columns
298
- table.schemas = artifacts.schemas
541
+ defineSchemasGetter(table)
299
542
  table[TypeId] = {
300
543
  name,
301
544
  baseName,
302
545
  schemaName: resolvedSchemaName,
303
546
  fields,
304
547
  primaryKey: artifacts.primaryKey,
305
- kind
548
+ kind,
549
+ casing
306
550
  }
307
551
  table[Plan.TypeId] = {
308
552
  selection: artifacts.columns,
@@ -341,28 +585,25 @@ const applyDeclaredOptions = <
341
585
  return table
342
586
  }
343
587
  return declaredOptions.reduce<TableDefinition<any, any, any, "schema", any>>(
344
- (current, option) => option(current),
588
+ (current, option) =>
589
+ (option as unknown as (
590
+ table: TableDefinition<any, any, any, "schema", any>
591
+ ) => TableDefinition<any, any, any, "schema", any>)(current),
345
592
  table
346
593
  ) as unknown as Table
347
594
  }
348
595
 
349
- const validateClassOptions = (declaredOptions: readonly TableOptionSpec[]): void => {
350
- for (const option of declaredOptions) {
351
- if (option.kind === "primaryKey") {
352
- throw new Error("Table.Class does not support table-level primary keys; declare primary keys inline on columns")
353
- }
354
- }
355
- }
356
-
357
596
  const resolveFieldDialect = (fields: TableFieldMap): string => {
358
597
  const dialects = [...new Set(Object.values(fields).map((field) => field.metadata.dbType.dialect))]
359
598
  if (dialects.length === 0) {
360
599
  throw new Error("Cannot infer table dialect from an empty field set")
361
600
  }
362
- if (dialects.length > 1) {
601
+ const concreteDialects = dialects.filter((dialect) => dialect !== "standard")
602
+ const uniqueConcreteDialects = [...new Set(concreteDialects)]
603
+ if (uniqueConcreteDialects.length > 1) {
363
604
  throw new Error(`Mixed table dialects are not supported: ${dialects.join(", ")}`)
364
605
  }
365
- return dialects[0]!
606
+ return uniqueConcreteDialects[0] ?? "standard"
366
607
  }
367
608
 
368
609
  const validateFieldDialects = (tableName: string, fields: TableFieldMap): void => {
@@ -388,7 +629,6 @@ const ensureClassArtifacts = <
388
629
  }
389
630
  const state = self[TypeId]
390
631
  const classOptions = self[options]
391
- validateClassOptions(extractDeclaredOptions(classOptions))
392
632
  const table = applyDeclaredOptions(
393
633
  makeTable(
394
634
  state.name,
@@ -397,13 +637,13 @@ const ensureClassArtifacts = <
397
637
  state.name,
398
638
  "schema",
399
639
  state.schemaName,
400
- state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"
640
+ state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit",
641
+ state.casing
401
642
  ) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", typeof state.schemaName>,
402
643
  classOptions
403
644
  )
404
645
  const artifacts = {
405
646
  columns: table.columns,
406
- schemas: table.schemas,
407
647
  normalizedOptions: table[OptionsSymbol],
408
648
  primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
409
649
  } satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
@@ -422,9 +662,6 @@ const appendOption = <
422
662
  option: Spec
423
663
  ): ApplyOption<Table, Spec> => {
424
664
  const state = table[TypeId]
425
- if (state.kind !== "schema") {
426
- throw new Error("Table options can only be applied to schema tables, not aliased query sources")
427
- }
428
665
  return makeTable(
429
666
  state.name,
430
667
  state.fields,
@@ -432,25 +669,37 @@ const appendOption = <
432
669
  state.baseName,
433
670
  state.kind,
434
671
  state.schemaName,
435
- "explicit"
672
+ "explicit",
673
+ state.casing
436
674
  ) as unknown as ApplyOption<Table, Spec>
437
675
  }
438
676
 
439
677
  const makeOption = <Spec extends TableOptionSpec>(option: Spec): TableOption<Spec> => {
440
- const builder = ((table: TableDefinition<any, any, any, "schema", any>) =>
441
- appendOption(table, option)) as unknown as TableOption<Spec>
442
- ;(builder as { option: Spec }).option = option
443
- 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>
444
686
  }
445
687
 
446
688
  const makeResolvedOption = <Spec extends TableOptionSpec>(
447
689
  option: Spec,
448
690
  resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
449
691
  ): TableOption<Spec> => {
450
- const builder = ((table: TableDefinition<any, any, any, "schema", any>) =>
451
- appendOption(table, resolve(table))) as unknown as TableOption<Spec>
452
- ;(builder as { option: Spec }).option = option
453
- 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>
454
703
  }
455
704
 
456
705
  export const option = <Spec extends TableOptionSpec>(spec: Spec): TableOption<Spec> =>
@@ -463,18 +712,30 @@ export const optionFromTable = <Spec extends TableOptionSpec>(
463
712
  makeResolvedOption(spec, resolve)
464
713
 
465
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>
466
722
  export function make<
467
723
  Name extends string,
468
724
  Fields extends TableFieldMap,
469
- SchemaName extends string | undefined = DefaultSchemaName
725
+ const SchemaName extends string
470
726
  >(
471
- name: Name,
472
- fields: Fields,
473
- schemaName?: SchemaName
474
- ): 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> {
475
736
  const resolvedSchemaName = arguments.length >= 3
476
737
  ? schemaName
477
- : ("public" as SchemaName)
738
+ : "public"
478
739
  return makeTable(
479
740
  name,
480
741
  fields,
@@ -486,35 +747,57 @@ export function make<
486
747
  )
487
748
  }
488
749
 
489
- /**
490
- * Creates a namespace-scoped builder for a concrete SQL schema/database.
491
- */
492
- export const schema = <SchemaName extends string>(
493
- schemaName: SchemaName
494
- ): TableSchemaNamespace<SchemaName> => ({
495
- schemaName,
496
- table: <
497
- Name extends string,
498
- Fields extends TableFieldMap,
499
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
500
- >(
501
- name: Name,
502
- fields: Fields,
503
- ...options: DeclaredTableOptions
504
- ): TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName> =>
505
- applyDeclaredOptions(
506
- makeTable(
507
- name,
508
- fields,
509
- [],
510
- name,
511
- "schema",
512
- schemaName,
513
- "explicit"
514
- ) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
515
- options
516
- )
517
- })
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,
790
+ 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
+ >
800
+ }
518
801
 
519
802
  /**
520
803
  * Creates an aliased source from an existing table definition.
@@ -531,7 +814,7 @@ export const alias = <
531
814
  AliasName extends string
532
815
  >(
533
816
  table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName>,
534
- aliasName: AliasName
817
+ aliasName: LiteralStringInput<AliasName>
535
818
  ): TableDefinition<
536
819
  AliasName,
537
820
  Fields,
@@ -541,26 +824,27 @@ export const alias = <
541
824
  > => {
542
825
  const state = table[TypeId]
543
826
  const columns = Object.fromEntries(
544
- 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)])
545
828
  ) as BoundColumns<AliasName, Fields>
546
829
  const aliased = attachPipe(Object.create(TableProto))
547
- aliased.name = aliasName
830
+ aliased.name = aliasName as AliasName
548
831
  aliased.columns = columns
549
- aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey)
832
+ defineSchemasGetter(aliased)
550
833
  aliased[TypeId] = {
551
- name: aliasName,
834
+ name: aliasName as AliasName,
552
835
  baseName: state.baseName,
553
836
  schemaName: state.schemaName,
554
837
  fields: state.fields,
555
838
  primaryKey: state.primaryKey,
556
- kind: "alias"
839
+ kind: "alias",
840
+ casing: state.casing
557
841
  }
558
842
  aliased[Plan.TypeId] = {
559
843
  selection: columns,
560
844
  required: undefined as never,
561
845
  available: {
562
846
  [aliasName]: {
563
- name: aliasName,
847
+ name: aliasName as AliasName,
564
848
  mode: "required",
565
849
  baseName: state.baseName
566
850
  }
@@ -584,19 +868,38 @@ export const alias = <
584
868
  * The returned base class can be extended and configured with
585
869
  * `static readonly [Table.options]`.
586
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
587
879
  export function Class<
588
880
  Self = never,
589
- 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
590
893
  >(
591
894
  name: string,
592
895
  schemaName?: SchemaName
593
- ) {
896
+ ): any {
594
897
  const resolvedSchemaName = arguments.length >= 2
595
898
  ? schemaName
596
899
  : ("public" as SchemaName)
597
- return <Fields extends TableFieldMap>(fields: Fields): [Self] extends [never]
900
+ return <Fields extends TableFieldMap>(fields: Fields & NonEmptyFieldMap<Fields>): [Self] extends [never]
598
901
  ? MissingSelfGeneric
599
- : TableClassStatic<typeof name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName> => {
902
+ : TableClassStatic<Name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName> => {
600
903
  abstract class TableClassBase {
601
904
  static readonly tableName = name
602
905
 
@@ -605,12 +908,11 @@ export function Class<
605
908
  }
606
909
 
607
910
  static get schemas() {
608
- return ensureClassArtifacts(this as any).schemas
911
+ return schemasFor(this as any)
609
912
  }
610
913
 
611
914
  static get [TypeId]() {
612
- const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<typeof name, Fields>)[options])
613
- validateClassOptions(declaredOptions)
915
+ const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<Name, Fields>)[options])
614
916
  return {
615
917
  name,
616
918
  baseName: name,
@@ -641,7 +943,7 @@ export function Class<
641
943
  return ensureClassArtifacts(this as any).normalizedOptions
642
944
  }
643
945
 
644
- static pipe(this: unknown) {
946
+ static pipe(this: Pipeable) {
645
947
  return pipeArguments(this, arguments)
646
948
  }
647
949
  }
@@ -664,7 +966,7 @@ export function Class<
664
966
  export const primaryKey = <
665
967
  const Columns extends string | readonly string[]
666
968
  >(
667
- columns: Columns
969
+ columns: Columns & NonEmptyColumnInput<Columns>
668
970
  ): TableOption<{
669
971
  readonly kind: "primaryKey"
670
972
  readonly columns: NormalizeColumns<Columns>
@@ -677,7 +979,7 @@ export const primaryKey = <
677
979
  export const unique = <
678
980
  const Columns extends string | readonly string[]
679
981
  >(
680
- columns: Columns
982
+ columns: Columns & NonEmptyColumnInput<Columns>
681
983
  ): TableOption<{
682
984
  readonly kind: "unique"
683
985
  readonly columns: NormalizeColumns<Columns>
@@ -690,7 +992,7 @@ export const unique = <
690
992
  export const index = <
691
993
  const Columns extends string | readonly string[]
692
994
  >(
693
- columns: Columns
995
+ columns: Columns & NonEmptyColumnInput<Columns>
694
996
  ): TableOption<{
695
997
  readonly kind: "index"
696
998
  readonly columns: NormalizeColumns<Columns>
@@ -705,9 +1007,9 @@ export const foreignKey = <
705
1007
  TargetTable extends AnyTable,
706
1008
  const TargetColumns extends string | readonly string[]
707
1009
  >(
708
- columns: LocalColumns,
1010
+ columns: LocalColumns & NonEmptyColumnInput<LocalColumns>,
709
1011
  target: () => TargetTable,
710
- referencedColumns: TargetColumns
1012
+ referencedColumns: TargetColumns & NonEmptyColumnInput<TargetColumns> & MatchingColumnArityInput<LocalColumns, TargetColumns>
711
1013
  ): TableOption<{
712
1014
  readonly kind: "foreignKey"
713
1015
  readonly columns: NormalizeColumns<LocalColumns>
@@ -715,7 +1017,7 @@ export const foreignKey = <
715
1017
  readonly tableName: string
716
1018
  readonly schemaName?: string
717
1019
  readonly columns: NormalizeColumns<TargetColumns>
718
- readonly knownColumns: readonly string[]
1020
+ readonly knownColumns: readonly ColumnNamesOfAnyTable<TargetTable>[]
719
1021
  }
720
1022
  }> => makeOption({
721
1023
  kind: "foreignKey",
@@ -723,14 +1025,15 @@ export const foreignKey = <
723
1025
  references: () => ({
724
1026
  tableName: target()[TypeId].baseName,
725
1027
  schemaName: target()[TypeId].schemaName,
1028
+ casing: target()[TypeId].casing,
726
1029
  columns: normalizeColumnList(referencedColumns) as NormalizeColumns<TargetColumns>,
727
- knownColumns: Object.keys(target()[TypeId].fields)
1030
+ knownColumns: Object.keys(target()[TypeId].fields).map((key) => key as ColumnNamesOfAnyTable<TargetTable>)
728
1031
  })
729
1032
  })
730
1033
 
731
1034
  /** Declares a check constraint expression. */
732
- export const check = <Name extends string>(
733
- name: Name,
1035
+ export const check = <const Name extends string>(
1036
+ name: NonEmptyStringInput<Name>,
734
1037
  predicate: DdlExpressionLike
735
1038
  ): TableOption<{
736
1039
  readonly kind: "check"
@@ -742,15 +1045,21 @@ export const check = <Name extends string>(
742
1045
  predicate
743
1046
  })
744
1047
 
745
- /** Extracts the row type of a table's select schema. */
746
- export type SelectOf<Table extends { readonly schemas: { readonly select: Schema.Schema<any> } }> = Schema.Schema.Type<
747
- Table["schemas"]["select"]
748
- >
749
- /** Extracts the payload type of a table's insert schema. */
750
- export type InsertOf<Table extends { readonly schemas: { readonly insert: Schema.Schema<any> } }> = Schema.Schema.Type<
751
- Table["schemas"]["insert"]
752
- >
753
- /** Extracts the payload type of a table's update schema. */
754
- export type UpdateOf<Table extends { readonly schemas: { readonly update: Schema.Schema<any> } }> = Schema.Schema.Type<
755
- Table["schemas"]["update"]
756
- >
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