effect-qb 4.0.0-beta.66 → 4.0.0-beta.98

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 (129) hide show
  1. package/README.md +5 -2
  2. package/dist/index.js +9376 -0
  3. package/dist/mysql.js +3921 -2573
  4. package/dist/postgres/metadata.js +2491 -1373
  5. package/dist/postgres.js +5453 -5155
  6. package/dist/sqlite.js +6895 -5529
  7. package/dist/standard.js +9330 -0
  8. package/package.json +9 -2
  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/coercion/rules.ts +13 -1
  13. package/src/internal/column-state.ts +21 -15
  14. package/src/internal/column.ts +44 -7
  15. package/src/internal/datatypes/define.ts +7 -1
  16. package/src/internal/datatypes/enrich.ts +23 -0
  17. package/src/internal/datatypes/lookup.ts +81 -25
  18. package/src/internal/datatypes/matrix.ts +903 -0
  19. package/src/internal/datatypes/shape.ts +2 -0
  20. package/src/internal/derived-table.ts +4 -36
  21. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +552 -361
  22. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +657 -400
  23. package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +505 -347
  24. package/src/internal/dialect.ts +35 -0
  25. package/src/internal/dsl-mutation-runtime.ts +12 -162
  26. package/src/internal/dsl-plan-runtime.ts +10 -138
  27. package/src/internal/dsl-query-runtime.ts +5 -79
  28. package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
  29. package/src/internal/executor.ts +14 -16
  30. package/src/internal/grouping-key.ts +87 -20
  31. package/src/internal/implication-runtime.ts +1 -1
  32. package/src/internal/json/path-access.ts +351 -0
  33. package/src/internal/predicate/runtime.ts +3 -0
  34. package/src/internal/query.d.ts +38 -11
  35. package/src/internal/query.ts +64 -25
  36. package/src/internal/renderer.ts +26 -14
  37. package/src/internal/runtime/normalize.ts +12 -5
  38. package/src/internal/scalar.ts +7 -1
  39. package/src/internal/schema-derivation.d.ts +7 -7
  40. package/src/internal/schema-derivation.ts +9 -9
  41. package/src/internal/schema-expression.ts +2 -2
  42. package/src/internal/sql-expression-renderer.ts +19 -0
  43. package/src/internal/standard-dsl.ts +6978 -0
  44. package/src/internal/table-options.ts +126 -66
  45. package/src/internal/table.ts +652 -219
  46. package/src/mysql/column-extension.ts +3 -0
  47. package/src/mysql/column.ts +8 -9
  48. package/src/mysql/datatypes/index.ts +4 -2
  49. package/src/mysql/datatypes/spec.ts +6 -176
  50. package/src/mysql/errors/normalize.ts +0 -1
  51. package/src/mysql/executor.ts +7 -7
  52. package/src/mysql/internal/dialect.ts +9 -4
  53. package/src/mysql/internal/dsl.ts +312 -154
  54. package/src/mysql/internal/renderer.ts +6 -2
  55. package/src/mysql/json.ts +7 -2
  56. package/src/mysql/query-extension.ts +16 -0
  57. package/src/mysql/renderer.ts +37 -3
  58. package/src/mysql/type.ts +60 -0
  59. package/src/mysql.ts +7 -13
  60. package/src/postgres/check.ts +1 -0
  61. package/src/postgres/column-extension.ts +28 -0
  62. package/src/postgres/column.ts +2 -8
  63. package/src/postgres/datatypes/index.d.ts +2 -1
  64. package/src/postgres/datatypes/index.ts +4 -2
  65. package/src/postgres/datatypes/spec.ts +6 -260
  66. package/src/postgres/errors/normalize.ts +0 -1
  67. package/src/postgres/executor.ts +7 -7
  68. package/src/postgres/foreign-key.ts +24 -0
  69. package/src/postgres/function/core.ts +1 -3
  70. package/src/postgres/function/index.ts +1 -17
  71. package/src/postgres/index.ts +1 -0
  72. package/src/postgres/internal/dialect.ts +9 -4
  73. package/src/postgres/internal/dsl.ts +306 -163
  74. package/src/postgres/internal/renderer.ts +6 -2
  75. package/src/postgres/internal/schema-ddl.ts +22 -10
  76. package/src/postgres/internal/schema-model.ts +238 -7
  77. package/src/postgres/json-extension.ts +7 -0
  78. package/src/postgres/json.ts +762 -173
  79. package/src/postgres/jsonb.ts +37 -0
  80. package/src/postgres/primary-key.ts +24 -0
  81. package/src/postgres/query-extension.ts +2 -0
  82. package/src/postgres/renderer.ts +37 -3
  83. package/src/postgres/schema-management.ts +12 -11
  84. package/src/postgres/schema.ts +106 -15
  85. package/src/postgres/table.ts +205 -530
  86. package/src/postgres/type.ts +93 -10
  87. package/src/postgres/unique.ts +32 -0
  88. package/src/postgres.ts +20 -16
  89. package/src/sqlite/column-extension.ts +3 -0
  90. package/src/sqlite/column.ts +8 -9
  91. package/src/sqlite/datatypes/index.ts +4 -2
  92. package/src/sqlite/datatypes/spec.ts +6 -94
  93. package/src/sqlite/errors/normalize.ts +0 -1
  94. package/src/sqlite/executor.ts +7 -7
  95. package/src/sqlite/internal/dialect.ts +9 -4
  96. package/src/sqlite/internal/dsl.ts +301 -154
  97. package/src/sqlite/internal/renderer.ts +6 -2
  98. package/src/sqlite/json.ts +8 -2
  99. package/src/sqlite/query-extension.ts +2 -0
  100. package/src/sqlite/renderer.ts +37 -3
  101. package/src/sqlite/type.ts +40 -0
  102. package/src/sqlite.ts +7 -13
  103. package/src/standard/cast.ts +113 -0
  104. package/src/standard/check.ts +17 -0
  105. package/src/standard/column.ts +163 -0
  106. package/src/standard/datatypes/index.ts +83 -0
  107. package/src/standard/datatypes/spec.ts +12 -0
  108. package/src/standard/dialect.ts +40 -0
  109. package/src/standard/foreign-key.ts +37 -0
  110. package/src/standard/function/aggregate.ts +2 -0
  111. package/src/standard/function/core.ts +2 -0
  112. package/src/standard/function/index.ts +18 -0
  113. package/src/standard/function/string.ts +2 -0
  114. package/src/standard/function/temporal.ts +78 -0
  115. package/src/standard/function/window.ts +2 -0
  116. package/src/standard/index.ts +17 -0
  117. package/src/standard/internal/renderer.ts +45 -0
  118. package/src/standard/json.ts +883 -0
  119. package/src/standard/primary-key.ts +17 -0
  120. package/src/standard/query.ts +152 -0
  121. package/src/standard/renderer.ts +49 -0
  122. package/src/standard/table.ts +151 -0
  123. package/src/standard/unique.ts +17 -0
  124. package/src/standard.ts +32 -0
  125. package/src/internal/aggregation-validation.ts +0 -57
  126. package/src/internal/table.d.ts +0 -180
  127. package/src/mysql/table.ts +0 -186
  128. package/src/postgres/cast.ts +0 -45
  129. package/src/sqlite/table.ts +0 -175
@@ -1,351 +1,73 @@
1
- import type * as Expression from "../internal/scalar.js"
2
- import { ColumnTypeId, type AnyColumnDefinition } from "../internal/column-state.js"
3
1
  import * as BaseTable from "../internal/table.js"
4
2
  import type { TableOptionSpec } from "../internal/table-options.js"
5
3
 
6
- type Dialect = "postgres"
4
+ export type {
5
+ DdlExpressionLike,
6
+ IndexKeySpec as IndexKey,
7
+ ReferentialAction,
8
+ TableOption
9
+ } from "../internal/table.js"
7
10
 
8
- type DialectColumn = AnyColumnDefinition & {
9
- readonly [ColumnTypeId]: {
10
- readonly dbType: Expression.DbType.Any & { readonly dialect: Dialect }
11
- }
12
- }
13
-
14
- type DialectFieldMap = Record<string, DialectColumn>
15
-
16
- type InlinePrimaryKeyKeys<Fields extends DialectFieldMap> = Extract<{
17
- [K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never
18
- }[keyof Fields], string>
19
-
20
- export type TableDefinition<
21
- Name extends string,
22
- Fields extends DialectFieldMap,
23
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
24
- Kind extends "schema" | "alias" = "schema",
25
- SchemaName extends string | undefined = "public"
26
- > = BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName>
27
-
28
- export type TableClassStatic<
29
- Name extends string,
30
- Fields extends DialectFieldMap,
31
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
32
- SchemaName extends string | undefined = "public"
33
- > = BaseTable.TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName>
34
-
35
- export type AnyTable = BaseTable.AnyTable<Dialect>
36
-
37
- type FieldsOfTable<Table extends BaseTable.AnyTable> = Table[typeof BaseTable.TypeId]["fields"] extends infer Fields extends DialectFieldMap
38
- ? Fields
39
- : never
40
-
41
- type ColumnNamesOfTable<Table extends BaseTable.AnyTable> = Extract<keyof FieldsOfTable<Table>, string>
42
-
43
- type PrimaryKeyOfTable<Table extends BaseTable.AnyTable> = Table[typeof BaseTable.TypeId]["primaryKey"][number]
44
-
45
- type SchemaNameOfTable<Table extends BaseTable.AnyTable> = Table[typeof BaseTable.TypeId]["schemaName"]
46
-
47
- type ApplySchemaTableOptions<
48
- Name extends string,
49
- Fields extends DialectFieldMap,
50
- PrimaryKeyColumns extends keyof Fields & string,
51
- SchemaName extends string,
52
- Options extends BaseTable.DeclaredTableOptions
53
- > = BaseTable.ApplyDeclaredOptions<
54
- BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
55
- Options
56
- > extends BaseTable.TableDefinition<any, any, infer AppliedPrimaryKeyColumns extends keyof Fields & string, "schema", any>
57
- ? TableDefinition<Name, Fields, AppliedPrimaryKeyColumns, "schema", SchemaName>
58
- : TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
59
-
60
- export type TableSchemaNamespace<SchemaName extends string> = {
61
- readonly schemaName: SchemaName
62
- readonly table: <
63
- Name extends string,
64
- Fields extends DialectFieldMap,
65
- const Options extends BaseTable.DeclaredTableOptions,
66
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
67
- >(
68
- name: Name,
69
- fields: Fields,
70
- ...options: Options & BaseTable.ValidateDeclaredOptions<BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
71
- ) => ApplySchemaTableOptions<Name, Fields, PrimaryKeyColumns, SchemaName, Options>
72
- }
73
-
74
- export type TableOption = BaseTable.TableOption
75
- export type DdlExpressionLike = BaseTable.DdlExpressionLike
76
- export type IndexKey = BaseTable.IndexKeySpec
77
- export type ReferentialAction = BaseTable.ReferentialAction
78
-
79
- type SchemaTable = {
80
- readonly columns: Record<string, unknown>
81
- }
82
-
83
- type TableExpressionFactory<Table extends SchemaTable> = (
84
- columns: Table["columns"]
85
- ) => DdlExpressionLike
86
-
87
- type TableScopedOptionBuilder<
88
- Table extends SchemaTable,
89
- Spec extends import("../internal/table-options.js").TableOptionSpec = import("../internal/table-options.js").TableOptionSpec
90
- > = {
91
- (table: Table): Table
92
- readonly option: Spec
93
- }
94
-
95
- export const TypeId = BaseTable.TypeId
96
- export const OptionsSymbol = BaseTable.OptionsSymbol
97
- export const options = BaseTable.options
98
-
99
- export const make = <
100
- Name extends string,
101
- Fields extends DialectFieldMap,
102
- SchemaName extends string | undefined = "public"
103
- >(
104
- name: Name,
105
- fields: Fields,
106
- schemaName: SchemaName = "public" as SchemaName
107
- ): TableDefinition<Name, Fields> =>
108
- BaseTable.make(name, fields, schemaName) as TableDefinition<Name, Fields>
109
-
110
- export const schema = <SchemaName extends string>(
111
- schemaName: SchemaName
112
- ): TableSchemaNamespace<SchemaName> => {
113
- const table = <
114
- Name extends string,
115
- Fields extends DialectFieldMap,
116
- const Options extends BaseTable.DeclaredTableOptions,
117
- PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
118
- >(
119
- name: Name,
120
- fields: Fields,
121
- ...declaredOptions: Options & BaseTable.ValidateDeclaredOptions<BaseTable.TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
122
- ) =>
123
- (BaseTable.schema(schemaName).table as (
124
- name: Name,
125
- fields: Fields,
126
- ...options: BaseTable.DeclaredTableOptions
127
- ) => BaseTable.TableDefinition<any, any, any, "schema", any>)(
128
- name,
129
- fields,
130
- ...declaredOptions
131
- ) as ApplySchemaTableOptions<Name, Fields, PrimaryKeyColumns, SchemaName, Options>
132
- return {
133
- schemaName,
134
- table
135
- } as unknown as TableSchemaNamespace<SchemaName>
136
- }
137
-
138
- export const alias = <
139
- Table extends AnyTable,
140
- AliasName extends string
141
- >(
142
- table: Table,
143
- aliasName: AliasName
144
- ): TableDefinition<
145
- AliasName,
146
- FieldsOfTable<Table>,
147
- PrimaryKeyOfTable<Table>,
148
- "alias",
149
- SchemaNameOfTable<Table>
150
- > =>
151
- BaseTable.alias(table as any, aliasName) as TableDefinition<
152
- AliasName,
153
- FieldsOfTable<Table>,
154
- PrimaryKeyOfTable<Table>,
155
- "alias",
156
- SchemaNameOfTable<Table>
157
- >
11
+ type NamedSpec = Extract<TableOptionSpec, { readonly name?: string }>
12
+ type PrimaryKeySpec = Extract<TableOptionSpec, { readonly kind: "primaryKey" }>
13
+ type UniqueSpec = Extract<TableOptionSpec, { readonly kind: "unique" }>
14
+ type IndexSpec = Extract<TableOptionSpec, { readonly kind: "index" }>
15
+ type ForeignKeySpec = Extract<TableOptionSpec, { readonly kind: "foreignKey" }>
16
+ type CheckSpec = Extract<TableOptionSpec, { readonly kind: "check" }>
158
17
 
159
- export const Class = <Self = never, SchemaName extends string | undefined = "public">(
160
- name: string,
161
- schemaName: SchemaName = "public" as SchemaName
162
- ) => {
163
- const base = BaseTable.Class<Self, SchemaName>(name, schemaName)
164
- return base as unknown as <
165
- Fields extends DialectFieldMap
166
- >(fields: Fields) => [Self] extends [never]
167
- ? BaseTable.MissingSelfGeneric
168
- : TableClassStatic<typeof name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName>
18
+ type IndexKeyOptions = {
19
+ readonly order?: "asc" | "desc"
20
+ readonly nulls?: "first" | "last"
21
+ readonly operatorClass?: string
22
+ readonly collation?: string
169
23
  }
170
24
 
171
- export const option = BaseTable.option
172
-
173
- type RichPrimaryKeyInput<Columns extends string | readonly string[]> = {
174
- readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
175
- readonly name?: string
176
- readonly deferrable?: boolean
177
- readonly initiallyDeferred?: boolean
178
- }
179
-
180
- type RichUniqueInput<Columns extends string | readonly string[]> = {
181
- readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
182
- readonly name?: string
183
- readonly nullsNotDistinct?: boolean
184
- readonly deferrable?: boolean
185
- readonly initiallyDeferred?: boolean
186
- }
187
-
188
- type RichIndexKeyInput =
25
+ type IndexKeyInput<Table extends BaseTable.SchemaTableDefinition = BaseTable.SchemaTableDefinition> =
189
26
  | {
190
- readonly column: string
191
- readonly order?: "asc" | "desc"
192
- readonly nulls?: "first" | "last"
193
- readonly operatorClass?: string
194
- readonly collation?: string
195
- }
27
+ readonly column: BaseTable.TableColumn<Table>
28
+ } & IndexKeyOptions
196
29
  | {
197
- readonly expression: DdlExpressionLike
198
- readonly order?: "asc" | "desc"
199
- readonly nulls?: "first" | "last"
200
- readonly operatorClass?: string
201
- readonly collation?: string
202
- }
30
+ readonly expression: BaseTable.DdlExpressionLike
31
+ } & IndexKeyOptions
203
32
 
204
- type RichIndexDetails = {
205
- readonly name?: string
206
- readonly unique?: boolean
207
- readonly method?: string
208
- readonly include?: readonly string[]
209
- readonly predicate?: DdlExpressionLike
210
- }
211
-
212
- type RichIndexInput<Columns extends string | readonly string[] = string | readonly string[]> = RichIndexDetails & (
213
- | {
214
- readonly columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
215
- readonly keys?: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
216
- }
217
- | {
218
- readonly columns?: Columns & BaseTable.NonEmptyColumnInput<Columns>
219
- readonly keys: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
220
- }
221
- )
222
-
223
- type PrimaryKeyOptionSpec = Extract<TableOptionSpec, { readonly kind: "primaryKey" }>
224
- type UniqueOptionSpec = Extract<TableOptionSpec, { readonly kind: "unique" }>
225
- type IndexOptionSpec = Extract<TableOptionSpec, { readonly kind: "index" }>
226
- type ForeignKeyOptionSpec = Extract<TableOptionSpec, { readonly kind: "foreignKey" }>
227
-
228
- type RichPrimaryKeyOptionSpec<Columns extends string | readonly string[]> = PrimaryKeyOptionSpec & {
229
- readonly kind: "primaryKey"
230
- readonly columns: BaseTable.NormalizeColumns<Columns>
231
- }
232
-
233
- type RichUniqueOptionSpec<Columns extends string | readonly string[]> = UniqueOptionSpec & {
234
- readonly kind: "unique"
235
- readonly columns: BaseTable.NormalizeColumns<Columns>
236
- }
237
-
238
- type KnownTargetColumnsInput<
239
- TargetTable extends AnyTable,
240
- Columns extends string | readonly string[]
241
- > = BaseTable.NormalizeColumns<Columns> extends infer NormalizedColumns extends readonly string[]
242
- ? string extends NormalizedColumns[number]
243
- ? unknown
244
- : Exclude<NormalizedColumns[number], ColumnNamesOfTable<TargetTable>> extends never
245
- ? unknown
246
- : never
33
+ type EmptyIndexKeyOperatorClass<Key> = Key extends { readonly operatorClass: infer OperatorClass extends string }
34
+ ? BaseTable.NonEmptyStringInput<OperatorClass> extends never ? Key : never
247
35
  : never
248
36
 
249
- type RichIndexColumnOption<Spec> = Spec extends { readonly columns: infer Columns extends string | readonly string[] }
250
- ? { readonly columns: BaseTable.NormalizeColumns<Columns> }
251
- : {}
252
-
253
- type RichIndexIncludeOption<Spec> = Spec extends { readonly include: infer Include extends readonly string[] }
254
- ? { readonly include: Include }
255
- : {}
256
-
257
- type RichIndexKeySpec<Key> = Key extends { readonly column: infer Column extends string }
258
- ? BaseTable.IndexKeySpec & { readonly kind: "column"; readonly column: Column }
259
- : BaseTable.IndexKeySpec & { readonly kind: "expression" }
260
-
261
- type RichIndexKeys<Keys extends readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]> = {
262
- readonly [K in keyof Keys]: Keys[K] extends RichIndexKeyInput ? RichIndexKeySpec<Keys[K]> : never
263
- } & readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
264
-
265
- type RichIndexKeysOption<Spec> = Spec extends { readonly keys: infer Keys extends readonly [RichIndexKeyInput, ...RichIndexKeyInput[]] }
266
- ? { readonly keys: RichIndexKeys<Keys> }
267
- : {}
268
-
269
- type RichIndexColumnsConstraint<Spec> = Spec extends { readonly columns: infer Columns extends string | readonly string[] }
270
- ? BaseTable.NonEmptyColumnInput<Columns> extends never ? never : unknown
271
- : unknown
272
-
273
- type RichIndexOptionSpec<Spec> = IndexOptionSpec & {
274
- readonly kind: "index"
275
- readonly name?: string
276
- readonly unique?: boolean
277
- readonly method?: string
278
- readonly predicate?: DdlExpressionLike
279
- } & RichIndexColumnOption<Spec> & RichIndexIncludeOption<Spec> & RichIndexKeysOption<Spec>
280
-
281
- type RichForeignKeyOptionSpec<
282
- LocalColumns extends string | readonly string[],
283
- TargetTable extends AnyTable,
284
- TargetColumns extends string | readonly string[]
285
- > = ForeignKeyOptionSpec & {
286
- readonly kind: "foreignKey"
287
- readonly columns: BaseTable.NormalizeColumns<LocalColumns>
288
- readonly references: () => {
289
- readonly tableName: string
290
- readonly schemaName?: string
291
- readonly columns: BaseTable.NormalizeColumns<TargetColumns>
292
- readonly knownColumns: readonly ColumnNamesOfTable<TargetTable>[]
293
- }
294
- }
295
-
296
- type RichForeignKeyInput<
297
- LocalColumns extends string | readonly string[],
298
- TargetTable extends AnyTable,
299
- TargetColumns extends string | readonly string[]
300
- > = {
301
- readonly columns: LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>
302
- readonly target: () => TargetTable
303
- readonly referencedColumns: TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
304
- readonly name?: string
305
- readonly onUpdate?: ReferentialAction
306
- readonly onDelete?: ReferentialAction
307
- readonly deferrable?: boolean
308
- readonly initiallyDeferred?: boolean
309
- }
310
-
311
- type RichCheckInput<Name extends string = string> = {
312
- readonly name: Name
313
- readonly predicate: DdlExpressionLike
314
- readonly noInherit?: boolean
315
- }
316
-
317
- const isObject = (value: unknown): value is Record<string, unknown> =>
318
- typeof value === "object" && value !== null && !Array.isArray(value)
319
-
320
- const isTableExpressionFactory = (value: unknown): value is TableExpressionFactory<SchemaTable> =>
321
- typeof value === "function"
322
-
323
- const makeTableScopedOption = <
324
- Table extends SchemaTable,
325
- Spec extends import("../internal/table-options.js").TableOptionSpec
326
- >(
327
- placeholder: Spec,
328
- resolve: (table: Table) => Spec
329
- ): TableScopedOptionBuilder<Table, Spec> => {
330
- const builder = ((table: Table) =>
331
- BaseTable.option(resolve(table))(table as never)) as unknown as TableScopedOptionBuilder<Table, Spec>
332
- ;(builder as { option: Spec }).option = placeholder
333
- return builder
334
- }
37
+ type EmptyIndexKeyCollation<Key> = Key extends { readonly collation: infer Collation extends string }
38
+ ? BaseTable.NonEmptyStringInput<Collation> extends never ? Key : never
39
+ : never
335
40
 
336
- const normalizeColumns = (columns: string | readonly string[]): readonly [string, ...string[]] => {
337
- const normalized = Array.isArray(columns) ? [...columns] : [columns]
338
- if (normalized.length === 0) {
339
- throw new Error("Table options require at least one column")
340
- }
341
- return normalized as unknown as readonly [string, ...string[]]
342
- }
41
+ type InvalidIndexKeyMetadata<Key> =
42
+ | EmptyIndexKeyOperatorClass<Key>
43
+ | EmptyIndexKeyCollation<Key>
44
+
45
+ type NonEmptyIndexKeyInput<Key> =
46
+ [InvalidIndexKeyMetadata<Key>] extends [never] ? unknown : never
47
+
48
+ type NormalizedIndexKey<Key> = Key extends { readonly expression: infer Expression extends BaseTable.DdlExpressionLike }
49
+ ? {
50
+ readonly kind: "expression"
51
+ readonly expression: Expression
52
+ readonly order: Key extends { readonly order: infer Order extends "asc" | "desc" } ? Order : undefined
53
+ readonly nulls: Key extends { readonly nulls: infer Nulls extends "first" | "last" } ? Nulls : undefined
54
+ readonly operatorClass: Key extends { readonly operatorClass: infer OperatorClass extends string } ? OperatorClass : undefined
55
+ readonly collation: Key extends { readonly collation: infer Collation extends string } ? Collation : undefined
56
+ }
57
+ : Key extends { readonly column: infer Column extends BaseTable.AnyColumnSelection }
58
+ ? {
59
+ readonly kind: "column"
60
+ readonly column: BaseTable.SelectedColumns<Column>[number]
61
+ readonly order: Key extends { readonly order: infer Order extends "asc" | "desc" } ? Order : undefined
62
+ readonly nulls: Key extends { readonly nulls: infer Nulls extends "first" | "last" } ? Nulls : undefined
63
+ readonly operatorClass: Key extends { readonly operatorClass: infer OperatorClass extends string } ? OperatorClass : undefined
64
+ readonly collation: Key extends { readonly collation: infer Collation extends string } ? Collation : undefined
65
+ }
66
+ : never
343
67
 
344
- const normalizeIndexKeys = (
345
- keys: readonly [RichIndexKeyInput, ...RichIndexKeyInput[]]
346
- ): readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]] =>
347
- keys.map((key) => "expression" in key
348
- ? {
68
+ const normalizeIndexKey = (key: IndexKeyInput): BaseTable.IndexKeySpec =>
69
+ "expression" in key
70
+ ? {
349
71
  kind: "expression",
350
72
  expression: key.expression,
351
73
  order: key.order,
@@ -355,205 +77,158 @@ const normalizeIndexKeys = (
355
77
  }
356
78
  : {
357
79
  kind: "column",
358
- column: key.column,
80
+ column: BaseTable.selectedColumnList(key.column)[0]!,
359
81
  order: key.order,
360
82
  nulls: key.nulls,
361
83
  operatorClass: key.operatorClass,
362
84
  collation: key.collation
363
- }) as unknown as readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
364
-
365
- export const primaryKey: {
366
- <const Columns extends string | readonly string[]>(
367
- columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
368
- ): BaseTable.TableOption<{
369
- readonly kind: "primaryKey"
370
- readonly columns: BaseTable.NormalizeColumns<Columns>
371
- }>
372
- <const Columns extends string | readonly string[]>(
373
- spec: RichPrimaryKeyInput<Columns>
374
- ): BaseTable.TableOption<RichPrimaryKeyOptionSpec<Columns>>
375
- } = ((input: unknown) =>
376
- isObject(input) && "columns" in input
377
- ? BaseTable.option({
378
- kind: "primaryKey",
379
- columns: normalizeColumns((input as RichPrimaryKeyInput<string | readonly string[]>).columns),
380
- name: (input as RichPrimaryKeyInput<string | readonly string[]>).name,
381
- deferrable: (input as RichPrimaryKeyInput<string | readonly string[]>).deferrable,
382
- initiallyDeferred: (input as RichPrimaryKeyInput<string | readonly string[]>).initiallyDeferred
383
- })
384
- : BaseTable.primaryKey(input as string | readonly string[])) as never
385
-
386
- export const unique: {
387
- <const Columns extends string | readonly string[]>(
388
- columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
389
- ): BaseTable.TableOption<{
390
- readonly kind: "unique"
391
- readonly columns: BaseTable.NormalizeColumns<Columns>
392
- }>
393
- <const Columns extends string | readonly string[]>(
394
- spec: RichUniqueInput<Columns>
395
- ): BaseTable.TableOption<RichUniqueOptionSpec<Columns>>
396
- } = ((input: unknown) =>
397
- isObject(input) && "columns" in input && ("name" in input || "nullsNotDistinct" in input || "deferrable" in input || "initiallyDeferred" in input)
398
- ? BaseTable.option({
399
- kind: "unique",
400
- columns: normalizeColumns((input as RichUniqueInput<string | readonly string[]>).columns),
401
- name: (input as RichUniqueInput<string | readonly string[]>).name,
402
- nullsNotDistinct: (input as RichUniqueInput<string | readonly string[]>).nullsNotDistinct,
403
- deferrable: (input as RichUniqueInput<string | readonly string[]>).deferrable,
404
- initiallyDeferred: (input as RichUniqueInput<string | readonly string[]>).initiallyDeferred
405
- })
406
- : BaseTable.unique(input as string | readonly string[])) as never
85
+ }
407
86
 
408
- export const index: {
409
- <const Columns extends string | readonly string[]>(
410
- columns: Columns & BaseTable.NonEmptyColumnInput<Columns>
411
- ): BaseTable.TableOption<{
412
- readonly kind: "index"
413
- readonly columns: BaseTable.NormalizeColumns<Columns>
414
- }>
415
- <Table extends SchemaTable, const Columns extends string | readonly string[], const Spec extends Omit<RichIndexInput<Columns>, "predicate"> & {
416
- readonly predicate: TableExpressionFactory<Table>
417
- }>(
418
- spec: Spec & RichIndexColumnsConstraint<Spec>
419
- ): TableScopedOptionBuilder<Table, RichIndexOptionSpec<Spec>>
420
- <const Columns extends string | readonly string[], const Spec extends RichIndexInput<Columns>>(
421
- spec: Spec & RichIndexColumnsConstraint<Spec>
422
- ): BaseTable.TableOption<RichIndexOptionSpec<Spec>>
423
- } = ((input: unknown) =>
424
- isObject(input) && ("columns" in input || "keys" in input || "name" in input || "unique" in input || "method" in input || "include" in input || "predicate" in input)
425
- ? (() => {
426
- const spec = input as RichIndexInput<string | readonly string[]> & {
427
- readonly predicate?: DdlExpressionLike | TableExpressionFactory<SchemaTable>
428
- }
429
- const predicate = spec.predicate
430
- const placeholder = {
431
- kind: "index" as const,
432
- columns: spec.columns === undefined
433
- ? undefined
434
- : normalizeColumns(spec.columns),
435
- keys: spec.keys === undefined
436
- ? undefined
437
- : normalizeIndexKeys(spec.keys),
438
- name: spec.name,
439
- unique: spec.unique,
440
- method: spec.method,
441
- include: spec.include,
442
- predicate: predicate as unknown as DdlExpressionLike
443
- }
444
- return isTableExpressionFactory(predicate)
445
- ? makeTableScopedOption(placeholder, (table) => ({
446
- ...placeholder,
447
- predicate: predicate(table.columns)
448
- }))
449
- : BaseTable.option({
450
- ...placeholder,
451
- predicate
452
- })
453
- })()
454
- : BaseTable.index(input as string | readonly string[])) as never
455
- export const foreignKey = <
456
- const LocalColumns extends string | readonly string[],
457
- TargetTable extends AnyTable,
458
- const TargetColumns extends string | readonly string[]
87
+ /** Adds a Postgres constraint or index name to a standard table option. */
88
+ export const named = <const Name extends string>(
89
+ name: BaseTable.NonEmptyStringInput<Name>
90
+ ) =>
91
+ <Spec extends NamedSpec, TableContext extends BaseTable.SchemaTableDefinition>(
92
+ option: BaseTable.TableOption<Spec, TableContext>
93
+ ): BaseTable.TableOption<Spec & { readonly name: Name }, TableContext> =>
94
+ BaseTable.mapOption(option, (spec) => ({
95
+ ...spec,
96
+ name
97
+ } as Spec & { readonly name: Name }))
98
+
99
+ /** Marks a standard primary key, unique, or foreign-key option as deferrable. */
100
+ export const deferrable = <
101
+ Spec extends PrimaryKeySpec | UniqueSpec | ForeignKeySpec,
102
+ TableContext extends BaseTable.SchemaTableDefinition
103
+ >(option: BaseTable.TableOption<Spec, TableContext>): BaseTable.TableOption<Spec & { readonly deferrable: true }, TableContext> =>
104
+ BaseTable.mapOption(option, (spec) => ({
105
+ ...spec,
106
+ deferrable: true
107
+ } as Spec & { readonly deferrable: true }))
108
+
109
+ /** Marks a deferrable standard primary key, unique, or foreign-key option as initially deferred. */
110
+ export const initiallyDeferred = <
111
+ Spec extends PrimaryKeySpec | UniqueSpec | ForeignKeySpec,
112
+ TableContext extends BaseTable.SchemaTableDefinition
113
+ >(option: BaseTable.TableOption<Spec, TableContext>): BaseTable.TableOption<Spec & {
114
+ readonly deferrable: true
115
+ readonly initiallyDeferred: true
116
+ }, TableContext> =>
117
+ BaseTable.mapOption(option, (spec) => ({
118
+ ...spec,
119
+ deferrable: true,
120
+ initiallyDeferred: true
121
+ } as Spec & { readonly deferrable: true; readonly initiallyDeferred: true }))
122
+
123
+ /** Adds Postgres NULLS NOT DISTINCT to a standard unique option. */
124
+ export const nullsNotDistinct = <Spec extends UniqueSpec, TableContext extends BaseTable.SchemaTableDefinition>(
125
+ option: BaseTable.TableOption<Spec, TableContext>
126
+ ): BaseTable.TableOption<Spec & { readonly nullsNotDistinct: true }, TableContext> =>
127
+ BaseTable.mapOption(option, (spec) => ({
128
+ ...spec,
129
+ nullsNotDistinct: true
130
+ } as Spec & { readonly nullsNotDistinct: true }))
131
+
132
+ /** Marks a standard index option as a Postgres unique index. */
133
+ export const uniqueIndex = <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
134
+ option: BaseTable.TableOption<Spec, TableContext>
135
+ ): BaseTable.TableOption<Spec & { readonly unique: true }, TableContext> =>
136
+ BaseTable.mapOption(option, (spec) => ({
137
+ ...spec,
138
+ unique: true
139
+ } as Spec & { readonly unique: true }))
140
+
141
+ /** Adds a Postgres index method to a standard index option. */
142
+ export const using = <const Method extends string>(
143
+ method: BaseTable.NonEmptyStringInput<Method>
144
+ ) =>
145
+ <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
146
+ option: BaseTable.TableOption<Spec, TableContext>
147
+ ): BaseTable.TableOption<Spec & { readonly method: Method }, TableContext> =>
148
+ BaseTable.mapOption(option, (spec) => ({
149
+ ...spec,
150
+ method
151
+ } as Spec & { readonly method: Method }))
152
+
153
+ /** Adds Postgres INCLUDE columns to a standard index option. */
154
+ export const include = <
155
+ Selection extends BaseTable.AnyColumnSelection
459
156
  >(
460
- columnsOrSpec: (LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>) | RichForeignKeyInput<LocalColumns, TargetTable, TargetColumns>,
461
- target?: () => TargetTable,
462
- referencedColumns?: TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
463
- ): BaseTable.TableOption<RichForeignKeyOptionSpec<LocalColumns, TargetTable, TargetColumns>> =>
464
- isObject(columnsOrSpec) && "columns" in columnsOrSpec && "target" in columnsOrSpec
465
- ? (() => {
466
- const spec = columnsOrSpec as RichForeignKeyInput<LocalColumns, TargetTable, TargetColumns>
467
- const targetTable = spec.target()
468
- const targetState = targetTable[BaseTable.TypeId]
469
- return BaseTable.option({
470
- kind: "foreignKey",
471
- columns: normalizeColumns(spec.columns) as BaseTable.NormalizeColumns<LocalColumns>,
472
- name: spec.name,
473
- references: () => ({
474
- tableName: targetState.baseName,
475
- schemaName: targetState.schemaName,
476
- columns: normalizeColumns(spec.referencedColumns) as BaseTable.NormalizeColumns<TargetColumns>,
477
- knownColumns: Object.keys(targetState.fields) as unknown as readonly ColumnNamesOfTable<TargetTable>[]
478
- }),
479
- onUpdate: spec.onUpdate,
480
- onDelete: spec.onDelete,
481
- deferrable: spec.deferrable,
482
- initiallyDeferred: spec.initiallyDeferred
483
- } as RichForeignKeyOptionSpec<LocalColumns, TargetTable, TargetColumns>)
484
- })()
485
- : BaseTable.foreignKey<LocalColumns, TargetTable, TargetColumns>(
486
- columnsOrSpec as LocalColumns & BaseTable.NonEmptyColumnInput<LocalColumns>,
487
- target as () => TargetTable,
488
- referencedColumns as TargetColumns & BaseTable.NonEmptyColumnInput<TargetColumns> & BaseTable.MatchingColumnArityInput<LocalColumns, TargetColumns> & KnownTargetColumnsInput<NoInfer<TargetTable>, TargetColumns>
489
- )
490
-
491
- export const check: {
492
- <Name extends string>(name: Name, predicate: DdlExpressionLike): BaseTable.TableOption
493
- <Name extends string, Table extends SchemaTable>(
494
- name: Name,
495
- predicate: TableExpressionFactory<Table>
496
- ): TableScopedOptionBuilder<Table, {
497
- readonly kind: "check"
498
- readonly name: Name
499
- readonly predicate: DdlExpressionLike
500
- }>
501
- <Name extends string, Table extends SchemaTable>(
502
- spec: Omit<RichCheckInput<Name>, "predicate"> & {
503
- readonly predicate: TableExpressionFactory<Table>
504
- }
505
- ): TableScopedOptionBuilder<Table, {
506
- readonly kind: "check"
507
- readonly name: Name
508
- readonly predicate: DdlExpressionLike
509
- readonly noInherit?: boolean
510
- }>
511
- <Name extends string>(spec: RichCheckInput<Name>): BaseTable.TableOption
512
- } = ((nameOrSpec: string | RichCheckInput, predicate?: DdlExpressionLike) =>
513
- isObject(nameOrSpec)
514
- ? (() => {
515
- const spec = nameOrSpec as RichCheckInput & {
516
- readonly predicate: DdlExpressionLike | TableExpressionFactory<SchemaTable>
517
- }
518
- const specPredicate = spec.predicate
519
- const placeholder = {
520
- kind: "check" as const,
521
- name: spec.name,
522
- predicate: specPredicate as unknown as DdlExpressionLike,
523
- noInherit: spec.noInherit
524
- }
525
- return isTableExpressionFactory(specPredicate)
526
- ? makeTableScopedOption(placeholder, (table) => ({
527
- ...placeholder,
528
- predicate: specPredicate(table.columns)
529
- }))
530
- : BaseTable.option({
531
- ...placeholder,
532
- predicate: specPredicate
533
- })
534
- })()
535
- : (() => {
536
- const predicateOrFactory = predicate as DdlExpressionLike | TableExpressionFactory<SchemaTable>
537
- const placeholder = {
538
- kind: "check" as const,
539
- name: nameOrSpec,
540
- predicate: predicateOrFactory as unknown as DdlExpressionLike
541
- }
542
- return isTableExpressionFactory(predicateOrFactory)
543
- ? makeTableScopedOption(placeholder, (table) => ({
544
- ...placeholder,
545
- predicate: predicateOrFactory(table.columns)
546
- }))
547
- : BaseTable.option({
548
- ...placeholder,
549
- predicate: predicateOrFactory
550
- })
551
- })()) as never
552
-
553
- export const selectSchema = BaseTable.selectSchema
554
- export const insertSchema = BaseTable.insertSchema
555
- export const updateSchema = BaseTable.updateSchema
556
-
557
- export type SelectOf<Table extends AnyTable> = BaseTable.SelectOf<Table>
558
- export type InsertOf<Table extends AnyTable> = BaseTable.InsertOf<Table>
559
- export type UpdateOf<Table extends AnyTable> = BaseTable.UpdateOf<Table>
157
+ columns: (table: any) => Selection
158
+ ) =>
159
+ <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
160
+ option: BaseTable.TableOption<Spec, TableContext>
161
+ ): BaseTable.TableOption<Spec & { readonly include: BaseTable.SelectedColumns<Selection> }, TableContext> =>
162
+ BaseTable.optionFromTable({
163
+ ...option.option,
164
+ include: [] as unknown as BaseTable.SelectedColumns<Selection>
165
+ } as Spec & { readonly include: BaseTable.SelectedColumns<Selection> }, (table) => ({
166
+ ...BaseTable.resolveOption(option, table as TableContext),
167
+ include: BaseTable.selectedColumnList(columns(table))
168
+ } as Spec & { readonly include: BaseTable.SelectedColumns<Selection> }))
169
+
170
+ /** Adds a Postgres partial-index predicate to a standard index option. */
171
+ export const where = <Predicate extends BaseTable.DdlExpressionLike>(
172
+ predicate: Predicate
173
+ ) =>
174
+ <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
175
+ option: BaseTable.TableOption<Spec, TableContext>
176
+ ): BaseTable.TableOption<Spec & { readonly predicate: Predicate }, TableContext> =>
177
+ BaseTable.mapOption(option, (spec) => ({
178
+ ...spec,
179
+ predicate
180
+ } as Spec & { readonly predicate: Predicate }))
181
+
182
+ /** Replaces standard index columns with a single Postgres index key. */
183
+ export const key = <
184
+ Column extends BaseTable.TableColumn<BaseTable.SchemaTableDefinition>,
185
+ const Options extends IndexKeyOptions = {}
186
+ >(
187
+ column: (table: any) => Column,
188
+ options?: Options & NonEmptyIndexKeyInput<Options>
189
+ ) =>
190
+ <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
191
+ option: BaseTable.TableOption<Spec, TableContext>
192
+ ): BaseTable.TableOption<Spec & {
193
+ readonly keys: readonly [NormalizedIndexKey<{ readonly column: Column } & Options>]
194
+ }, TableContext> =>
195
+ BaseTable.optionFromTable({
196
+ ...option.option,
197
+ columns: undefined,
198
+ keys: [] as unknown as readonly [NormalizedIndexKey<{ readonly column: Column } & Options>]
199
+ } as unknown as Spec & { readonly keys: readonly [NormalizedIndexKey<{ readonly column: Column } & Options>] }, (table) => ({
200
+ ...BaseTable.resolveOption(option, table as TableContext),
201
+ columns: undefined,
202
+ keys: [normalizeIndexKey({ column: column(table), ...options })]
203
+ } as unknown as Spec & { readonly keys: readonly [NormalizedIndexKey<{ readonly column: Column } & Options>] }))
204
+
205
+ /** Replaces standard index columns with Postgres index keys. */
206
+ export const keys = (
207
+ keys: (table: any) => readonly [IndexKeyInput, ...IndexKeyInput[]]
208
+ ) =>
209
+ <Spec extends IndexSpec, TableContext extends BaseTable.SchemaTableDefinition>(
210
+ option: BaseTable.TableOption<Spec, TableContext>
211
+ ): BaseTable.TableOption<Spec & {
212
+ readonly keys: readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
213
+ }, TableContext> =>
214
+ BaseTable.optionFromTable({
215
+ ...option.option,
216
+ columns: undefined,
217
+ keys: [] as unknown as readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]]
218
+ } as Spec & { readonly keys: readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]] }, (table) => {
219
+ const resolvedKeys = keys(table)
220
+ return {
221
+ ...BaseTable.resolveOption(option, table as TableContext),
222
+ columns: undefined,
223
+ keys: [normalizeIndexKey(resolvedKeys[0]), ...resolvedKeys.slice(1).map(normalizeIndexKey)]
224
+ } as Spec & { readonly keys: readonly [BaseTable.IndexKeySpec, ...BaseTable.IndexKeySpec[]] }
225
+ })
226
+
227
+ /** Adds Postgres NO INHERIT to a standard check option. */
228
+ export const noInherit = <Spec extends CheckSpec, TableContext extends BaseTable.SchemaTableDefinition>(
229
+ option: BaseTable.TableOption<Spec, TableContext>
230
+ ): BaseTable.TableOption<Spec & { readonly noInherit: true }, TableContext> =>
231
+ BaseTable.mapOption(option, (spec) => ({
232
+ ...spec,
233
+ noInherit: true
234
+ } as Spec & { readonly noInherit: true }))