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