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.
- package/README.md +11 -1
- package/dist/index.js +9376 -0
- package/dist/mysql.js +4092 -2671
- package/dist/postgres/metadata.js +2589 -1402
- package/dist/postgres.js +3953 -3583
- package/dist/sqlite.js +5527 -4088
- package/dist/standard.js +9330 -0
- package/package.json +9 -4
- package/src/casing.ts +71 -0
- package/src/index.ts +2 -0
- package/src/internal/casing.ts +89 -0
- package/src/internal/coercion/rules.ts +13 -1
- package/src/internal/column-state.d.ts +3 -3
- package/src/internal/column-state.ts +24 -18
- package/src/internal/column.ts +52 -15
- package/src/internal/datatypes/define.ts +7 -1
- package/src/internal/datatypes/enrich.ts +23 -0
- package/src/internal/datatypes/lookup.ts +81 -25
- package/src/internal/datatypes/matrix.ts +903 -0
- package/src/internal/datatypes/shape.ts +2 -0
- package/src/internal/derived-table.ts +4 -36
- package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +552 -361
- package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +657 -400
- package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +505 -347
- package/src/internal/dialect.ts +36 -1
- package/src/internal/dsl-mutation-runtime.ts +12 -162
- package/src/internal/dsl-plan-runtime.ts +10 -138
- package/src/internal/dsl-query-runtime.ts +5 -79
- package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
- package/src/internal/executor.ts +66 -49
- package/src/internal/grouping-key.ts +87 -20
- package/src/internal/implication-runtime.ts +1 -1
- package/src/internal/json/path-access.ts +351 -0
- package/src/internal/predicate/runtime.ts +3 -0
- package/src/internal/query.d.ts +39 -12
- package/src/internal/query.ts +65 -26
- package/src/internal/renderer.ts +26 -14
- package/src/internal/runtime/driver-value-mapping.ts +3 -3
- package/src/internal/runtime/normalize.ts +12 -5
- package/src/internal/runtime/schema.ts +28 -38
- package/src/internal/runtime/value.ts +20 -23
- package/src/internal/scalar.d.ts +1 -1
- package/src/internal/scalar.ts +8 -2
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +95 -43
- package/src/internal/schema-expression.ts +2 -2
- package/src/internal/sql-expression-renderer.ts +19 -0
- package/src/internal/standard-dsl.ts +6978 -0
- package/src/internal/table-options.ts +126 -66
- package/src/internal/table.ts +819 -237
- package/src/mysql/column-extension.ts +3 -0
- package/src/mysql/column.ts +14 -15
- package/src/mysql/datatypes/index.ts +4 -2
- package/src/mysql/datatypes/spec.ts +6 -176
- package/src/mysql/errors/normalize.ts +0 -1
- package/src/mysql/executor.ts +11 -11
- package/src/mysql/function/temporal.ts +1 -1
- package/src/mysql/internal/dialect.ts +9 -4
- package/src/mysql/internal/dsl.ts +334 -170
- package/src/mysql/internal/renderer.ts +6 -2
- package/src/mysql/json.ts +7 -2
- package/src/mysql/query-extension.ts +16 -0
- package/src/mysql/renderer.ts +37 -3
- package/src/mysql/type.ts +60 -0
- package/src/mysql.ts +7 -13
- package/src/postgres/check.ts +1 -0
- package/src/postgres/column-extension.ts +28 -0
- package/src/postgres/column.ts +13 -19
- package/src/postgres/datatypes/index.d.ts +2 -1
- package/src/postgres/datatypes/index.ts +4 -2
- package/src/postgres/datatypes/spec.ts +6 -260
- package/src/postgres/errors/normalize.ts +0 -1
- package/src/postgres/executor.ts +11 -11
- package/src/postgres/foreign-key.ts +24 -0
- package/src/postgres/function/core.ts +1 -3
- package/src/postgres/function/index.ts +1 -17
- package/src/postgres/function/temporal.ts +1 -1
- package/src/postgres/index.ts +1 -0
- package/src/postgres/internal/dialect.ts +9 -4
- package/src/postgres/internal/dsl.ts +328 -179
- package/src/postgres/internal/renderer.ts +6 -2
- package/src/postgres/internal/schema-ddl.ts +22 -10
- package/src/postgres/internal/schema-model.ts +238 -7
- package/src/postgres/json-extension.ts +7 -0
- package/src/postgres/json.ts +762 -173
- package/src/postgres/jsonb.ts +37 -0
- package/src/postgres/primary-key.ts +24 -0
- package/src/postgres/query-extension.ts +2 -0
- package/src/postgres/renderer.ts +37 -3
- package/src/postgres/schema-management.ts +13 -13
- package/src/postgres/schema.ts +106 -15
- package/src/postgres/table.ts +205 -538
- package/src/postgres/type.ts +93 -10
- package/src/postgres/unique.ts +32 -0
- package/src/postgres.ts +20 -16
- package/src/sqlite/column-extension.ts +3 -0
- package/src/sqlite/column.ts +14 -15
- package/src/sqlite/datatypes/index.ts +4 -2
- package/src/sqlite/datatypes/spec.ts +6 -94
- package/src/sqlite/errors/normalize.ts +0 -1
- package/src/sqlite/executor.ts +11 -11
- package/src/sqlite/function/temporal.ts +1 -1
- package/src/sqlite/internal/dialect.ts +9 -4
- package/src/sqlite/internal/dsl.ts +307 -159
- package/src/sqlite/internal/renderer.ts +6 -2
- package/src/sqlite/json.ts +8 -2
- package/src/sqlite/query-extension.ts +2 -0
- package/src/sqlite/renderer.ts +37 -3
- package/src/sqlite/type.ts +40 -0
- package/src/sqlite.ts +7 -13
- package/src/standard/cast.ts +113 -0
- package/src/standard/check.ts +17 -0
- package/src/standard/column.ts +163 -0
- package/src/standard/datatypes/index.ts +83 -0
- package/src/standard/datatypes/spec.ts +12 -0
- package/src/standard/dialect.ts +40 -0
- package/src/standard/foreign-key.ts +37 -0
- package/src/standard/function/aggregate.ts +2 -0
- package/src/standard/function/core.ts +2 -0
- package/src/standard/function/index.ts +18 -0
- package/src/standard/function/string.ts +2 -0
- package/src/standard/function/temporal.ts +78 -0
- package/src/standard/function/window.ts +2 -0
- package/src/standard/index.ts +17 -0
- package/src/standard/internal/renderer.ts +45 -0
- package/src/standard/json.ts +883 -0
- package/src/standard/primary-key.ts +17 -0
- package/src/standard/query.ts +152 -0
- package/src/standard/renderer.ts +49 -0
- package/src/standard/table.ts +151 -0
- package/src/standard/unique.ts +17 -0
- package/src/standard.ts +32 -0
- package/src/internal/aggregation-validation.ts +0 -57
- package/src/internal/table.d.ts +0 -173
- package/src/mysql/table.ts +0 -183
- package/src/postgres/cast.ts +0 -45
- package/src/sqlite/table.ts +0 -183
package/src/internal/table.ts
CHANGED
|
@@ -5,16 +5,15 @@ import * as Plan from "./row-set.js"
|
|
|
5
5
|
import type { Any as AnyExpression } from "./scalar.js"
|
|
6
6
|
import type { TrueFormula } from "./predicate/formula.js"
|
|
7
7
|
import type { BoundColumnFrom } from "./column-state.js"
|
|
8
|
-
import { bindColumn, type AnyColumnDefinition } from "./column-state.js"
|
|
8
|
+
import { bindColumn, BoundColumnTypeId, type AnyBoundColumn, type AnyColumnDefinition } from "./column-state.js"
|
|
9
9
|
import {
|
|
10
10
|
collectInlineOptions,
|
|
11
|
-
normalizeColumnList,
|
|
12
11
|
resolvePrimaryKeyColumns,
|
|
12
|
+
type ColumnList,
|
|
13
13
|
type DdlExpressionLike,
|
|
14
14
|
type IndexKeySpec,
|
|
15
|
-
type
|
|
16
|
-
type
|
|
17
|
-
type NormalizeColumns,
|
|
15
|
+
type LiteralStringInput,
|
|
16
|
+
type NonEmptyStringInput,
|
|
18
17
|
type ReferentialAction,
|
|
19
18
|
type TableOptionSpec,
|
|
20
19
|
type ValidateForeignKeyOptionColumns,
|
|
@@ -24,12 +23,16 @@ import {
|
|
|
24
23
|
validateOptions
|
|
25
24
|
} from "./table-options.js"
|
|
26
25
|
import {
|
|
27
|
-
|
|
26
|
+
deriveInsertSchema,
|
|
27
|
+
deriveSelectSchema,
|
|
28
|
+
deriveUpdateSchema,
|
|
28
29
|
type InsertRow,
|
|
29
30
|
type SelectRow,
|
|
30
31
|
type TableFieldMap,
|
|
32
|
+
type TableSchemaVariant,
|
|
31
33
|
type UpdateRow
|
|
32
34
|
} from "./schema-derivation.js"
|
|
35
|
+
import * as Casing from "./casing.js"
|
|
33
36
|
|
|
34
37
|
/** Symbol used to attach table-definition metadata. */
|
|
35
38
|
export const TypeId: unique symbol = Symbol.for("effect-qb/Table")
|
|
@@ -39,17 +42,62 @@ export const OptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/normaliz
|
|
|
39
42
|
export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOptions")
|
|
40
43
|
|
|
41
44
|
const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
|
|
45
|
+
const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
|
|
42
46
|
const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
|
|
47
|
+
const ResolveOptionSymbol: unique symbol = Symbol.for("effect-qb/Table/resolveOption")
|
|
43
48
|
|
|
44
49
|
type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
|
|
45
50
|
[K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never
|
|
46
51
|
}[keyof Fields], string>
|
|
47
52
|
|
|
48
|
-
type
|
|
53
|
+
type FieldDialects<Fields extends TableFieldMap> = Fields[keyof Fields][typeof import("./column-state.js").ColumnTypeId]["dbType"]["dialect"]
|
|
54
|
+
type ConcreteFieldDialects<Fields extends TableFieldMap> = Exclude<FieldDialects<Fields>, "standard">
|
|
55
|
+
type TableDialect<Fields extends TableFieldMap> = [ConcreteFieldDialects<Fields>] extends [never]
|
|
56
|
+
? "standard"
|
|
57
|
+
: ConcreteFieldDialects<Fields>
|
|
49
58
|
type TableKind = "schema" | "alias"
|
|
50
59
|
type DefaultSchemaName = "public"
|
|
60
|
+
type NonEmptyFieldMap<Fields extends TableFieldMap> =
|
|
61
|
+
string extends keyof Fields ? Fields : "" extends keyof Fields ? never : Fields
|
|
51
62
|
type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
|
|
52
63
|
type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
|
|
64
|
+
export type SchemaTableDefinition = TableDefinition<any, any, any, "schema", any, any>
|
|
65
|
+
type LooseTableSelection = any
|
|
66
|
+
type ConcreteSelector<
|
|
67
|
+
Table extends SchemaTableDefinition,
|
|
68
|
+
Selection extends AnyColumnSelection
|
|
69
|
+
> = SchemaTableDefinition extends Table ? never : (table: Table) => Selection
|
|
70
|
+
type ColumnNameOfBound<Column> = Column extends {
|
|
71
|
+
readonly [BoundColumnTypeId]: {
|
|
72
|
+
readonly columnName: infer ColumnName extends string
|
|
73
|
+
}
|
|
74
|
+
} ? ColumnName : never
|
|
75
|
+
type BoundColumnTupleNames<Columns extends readonly AnyBoundColumn[]> =
|
|
76
|
+
Columns extends readonly [infer Head extends AnyBoundColumn, ...infer Tail extends AnyBoundColumn[]]
|
|
77
|
+
? readonly [ColumnNameOfBound<Head>, ...BoundColumnTupleNames<Tail>]
|
|
78
|
+
: readonly []
|
|
79
|
+
type ColumnSelectionNames<Selection> =
|
|
80
|
+
Selection extends AnyBoundColumn
|
|
81
|
+
? readonly [ColumnNameOfBound<Selection>]
|
|
82
|
+
: Selection extends readonly [infer Head extends AnyBoundColumn, ...infer Tail extends AnyBoundColumn[]]
|
|
83
|
+
? readonly [ColumnNameOfBound<Head>, ...BoundColumnTupleNames<Tail>]
|
|
84
|
+
: never
|
|
85
|
+
export type TableColumnSelection<Table extends SchemaTableDefinition> =
|
|
86
|
+
TableColumn<Table> | readonly [TableColumn<Table>, ...TableColumn<Table>[]]
|
|
87
|
+
export type TableColumn<Table extends SchemaTableDefinition> =
|
|
88
|
+
SchemaTableDefinition extends Table ? AnyBoundColumn : Table extends TableDefinition<infer Name, infer Fields, any, "schema", any>
|
|
89
|
+
? BoundColumns<Name, Fields>[Extract<keyof Fields, string>]
|
|
90
|
+
: never
|
|
91
|
+
export type AnyColumnSelection = AnyBoundColumn | readonly [AnyBoundColumn, ...AnyBoundColumn[]]
|
|
92
|
+
export type SelectedColumns<Selection extends AnyColumnSelection> = ColumnSelectionNames<Selection>
|
|
93
|
+
type MatchingSelectionArityInput<
|
|
94
|
+
Left extends AnyColumnSelection,
|
|
95
|
+
Right extends AnyColumnSelection
|
|
96
|
+
> = SelectedColumns<Left>["length"] extends SelectedColumns<Right>["length"]
|
|
97
|
+
? SelectedColumns<Right>["length"] extends SelectedColumns<Left>["length"]
|
|
98
|
+
? unknown
|
|
99
|
+
: never
|
|
100
|
+
: never
|
|
53
101
|
type FieldIndexKeySpec<Fields extends TableFieldMap> =
|
|
54
102
|
| (Extract<IndexKeySpec, { readonly kind: "column" }> & { readonly column: FieldColumnName<Fields> })
|
|
55
103
|
| Extract<IndexKeySpec, { readonly kind: "expression" }>
|
|
@@ -67,53 +115,162 @@ type ClassOptionSpec<Fields extends TableFieldMap = TableFieldMap> =
|
|
|
67
115
|
})
|
|
68
116
|
| Extract<TableOptionSpec, { readonly kind: "check" }>
|
|
69
117
|
interface TableOptionBuilderLike<
|
|
70
|
-
Spec extends TableOptionSpec = TableOptionSpec
|
|
118
|
+
Spec extends TableOptionSpec = TableOptionSpec,
|
|
119
|
+
TableContext extends SchemaTableDefinition = SchemaTableDefinition
|
|
71
120
|
> {
|
|
72
121
|
readonly option: Spec
|
|
73
122
|
}
|
|
74
123
|
|
|
75
|
-
type ClassTableOption<Fields extends TableFieldMap> =
|
|
124
|
+
type ClassTableOption<Fields extends TableFieldMap> = TableOption<
|
|
125
|
+
ClassOptionSpec<Fields>,
|
|
126
|
+
TableDefinition<string, Fields, keyof Fields & string, "schema", any>
|
|
127
|
+
>
|
|
76
128
|
type ClassDeclaredTableOptions<Fields extends TableFieldMap> = readonly ClassTableOption<Fields>[]
|
|
129
|
+
type TableNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
|
|
130
|
+
Table extends TableDefinition<infer Name, any, any, "schema", any> ? Name : never
|
|
131
|
+
type TableFieldsOf<Table extends TableDefinition<any, any, any, "schema", any>> =
|
|
132
|
+
Table extends TableDefinition<any, infer Fields, any, "schema", any> ? Fields : never
|
|
133
|
+
type TablePrimaryKeyOf<Table extends TableDefinition<any, any, any, "schema", any>> =
|
|
134
|
+
Table extends TableDefinition<any, any, infer PrimaryKeyColumns, "schema", any> ? PrimaryKeyColumns : never
|
|
135
|
+
type TableSchemaNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
|
|
136
|
+
Table extends TableDefinition<any, any, any, "schema", infer SchemaName> ? SchemaName : never
|
|
137
|
+
type HasBroadColumns<Columns extends readonly string[]> = string extends Columns[number] ? true : false
|
|
138
|
+
|
|
139
|
+
export type ConflictArbiterScope = "unconditional" | "partial"
|
|
140
|
+
export type ConflictArbiter<
|
|
141
|
+
Columns extends ColumnList = ColumnList,
|
|
142
|
+
Scope extends ConflictArbiterScope = ConflictArbiterScope,
|
|
143
|
+
Name extends string | undefined = string | undefined,
|
|
144
|
+
Constraint extends boolean = boolean
|
|
145
|
+
> = {
|
|
146
|
+
readonly columns: Columns
|
|
147
|
+
readonly scope: Scope
|
|
148
|
+
readonly name?: Name
|
|
149
|
+
readonly constraint: Constraint
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
type InlineConflictArbiters<Fields extends TableFieldMap> = Extract<{
|
|
153
|
+
[K in keyof Fields]: Fields[K] extends AnyColumnDefinition
|
|
154
|
+
? Fields[K]["metadata"]["primaryKey"] extends true
|
|
155
|
+
? ConflictArbiter<readonly [Extract<K, string>], "unconditional", undefined, true>
|
|
156
|
+
: Fields[K]["metadata"]["unique"] extends true
|
|
157
|
+
? ConflictArbiter<
|
|
158
|
+
readonly [Extract<K, string>],
|
|
159
|
+
"unconditional",
|
|
160
|
+
Fields[K]["metadata"]["uniqueConstraint"] extends { readonly name?: infer Name extends string } ? Name : undefined,
|
|
161
|
+
true
|
|
162
|
+
>
|
|
163
|
+
: never
|
|
164
|
+
: never
|
|
165
|
+
}[keyof Fields], ConflictArbiter>
|
|
166
|
+
|
|
167
|
+
type TableConflictArbitersOf<Table extends TableDefinition<any, any, any, any, any, any>> =
|
|
168
|
+
Table extends TableDefinition<any, any, any, any, any, infer ConflictArbiters> ? ConflictArbiters : never
|
|
169
|
+
|
|
170
|
+
type NormalizeArbiterColumns<Columns> =
|
|
171
|
+
Columns extends readonly [infer Head extends string, ...infer Tail extends string[]]
|
|
172
|
+
? readonly [Head, ...Tail]
|
|
173
|
+
: Columns extends string
|
|
174
|
+
? readonly [Columns]
|
|
175
|
+
: never
|
|
176
|
+
|
|
177
|
+
type OptionColumns<Spec extends TableOptionSpec> =
|
|
178
|
+
Spec extends { readonly columns?: infer Columns } ? NormalizeArbiterColumns<Columns> : never
|
|
179
|
+
|
|
180
|
+
type OptionName<Spec extends TableOptionSpec> =
|
|
181
|
+
Spec extends { readonly name: infer Name extends string } ? Name : undefined
|
|
182
|
+
|
|
183
|
+
type ConflictArbiterFromOption<Spec extends TableOptionSpec> =
|
|
184
|
+
OptionColumns<Spec> extends infer Columns extends ColumnList
|
|
185
|
+
? HasBroadColumns<Columns> extends true
|
|
186
|
+
? never
|
|
187
|
+
: Spec extends { readonly kind: "primaryKey" | "unique" }
|
|
188
|
+
? ConflictArbiter<Columns, "unconditional", OptionName<Spec>, true>
|
|
189
|
+
: Spec extends { readonly kind: "index"; readonly unique: true }
|
|
190
|
+
? ConflictArbiter<Columns, Spec extends { readonly predicate: DdlExpressionLike } ? "partial" : "unconditional", OptionName<Spec>, false>
|
|
191
|
+
: never
|
|
192
|
+
: never
|
|
77
193
|
|
|
78
194
|
type BuildPrimaryKey<
|
|
79
|
-
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
195
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
80
196
|
Spec extends TableOptionSpec
|
|
81
197
|
> = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
|
|
82
|
-
? Columns
|
|
83
|
-
|
|
198
|
+
? HasBroadColumns<Columns> extends true
|
|
199
|
+
? TablePrimaryKeyOf<Table>
|
|
200
|
+
: Columns[number] & keyof TableFieldsOf<Table> & string
|
|
201
|
+
: TablePrimaryKeyOf<Table>
|
|
84
202
|
|
|
85
|
-
type
|
|
86
|
-
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
203
|
+
type OptionInputConstraint<
|
|
204
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
87
205
|
Spec extends TableOptionSpec
|
|
88
206
|
> = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
|
|
89
|
-
? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never :
|
|
207
|
+
? HasBroadColumns<Columns> extends true ? unknown : ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
|
|
90
208
|
: Spec extends { readonly kind: "index" }
|
|
91
|
-
?
|
|
209
|
+
? Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
210
|
+
? HasBroadColumns<Columns> extends true ? unknown : ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
|
|
211
|
+
: ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
|
|
92
212
|
: Spec extends { readonly kind: "foreignKey" }
|
|
93
|
-
?
|
|
213
|
+
? Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
214
|
+
? HasBroadColumns<Columns> extends true ? unknown : ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
|
|
215
|
+
: ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
|
|
94
216
|
: Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
95
|
-
? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never :
|
|
96
|
-
:
|
|
217
|
+
? HasBroadColumns<Columns> extends true ? unknown : ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
|
|
218
|
+
: unknown
|
|
219
|
+
|
|
220
|
+
type OptionInputTable<
|
|
221
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
222
|
+
Spec extends TableOptionSpec
|
|
223
|
+
> = Table & OptionInputConstraint<Table, Spec>
|
|
224
|
+
|
|
225
|
+
type OptionValidationArgs<
|
|
226
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
227
|
+
Spec extends TableOptionSpec
|
|
228
|
+
> = OptionInputConstraint<Table, Spec> extends never ? [never] : []
|
|
97
229
|
|
|
98
230
|
type ApplyOption<
|
|
99
|
-
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
231
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
100
232
|
Spec extends TableOptionSpec
|
|
101
233
|
> = Spec extends { readonly kind: "primaryKey" }
|
|
102
234
|
? TableDefinition<
|
|
103
|
-
Table
|
|
104
|
-
Table
|
|
235
|
+
TableNameOf<Table>,
|
|
236
|
+
TableFieldsOf<Table>,
|
|
105
237
|
BuildPrimaryKey<Table, Spec>,
|
|
106
|
-
"schema"
|
|
238
|
+
"schema",
|
|
239
|
+
TableSchemaNameOf<Table>,
|
|
240
|
+
TableConflictArbitersOf<Table> | ConflictArbiterFromOption<Spec>
|
|
107
241
|
>
|
|
108
242
|
: TableDefinition<
|
|
109
|
-
Table
|
|
110
|
-
Table
|
|
111
|
-
Table
|
|
112
|
-
"schema"
|
|
243
|
+
TableNameOf<Table>,
|
|
244
|
+
TableFieldsOf<Table>,
|
|
245
|
+
TablePrimaryKeyOf<Table>,
|
|
246
|
+
"schema",
|
|
247
|
+
TableSchemaNameOf<Table>,
|
|
248
|
+
TableConflictArbitersOf<Table> | ConflictArbiterFromOption<Spec>
|
|
113
249
|
>
|
|
114
250
|
|
|
251
|
+
type ApplyTableOption<
|
|
252
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
253
|
+
Spec extends TableOptionSpec
|
|
254
|
+
> = ApplyOption<Table, Spec>
|
|
255
|
+
|
|
256
|
+
type TableOptionPipe<
|
|
257
|
+
Name extends string,
|
|
258
|
+
Fields extends TableFieldMap,
|
|
259
|
+
PrimaryKeyColumns extends keyof Fields & string,
|
|
260
|
+
Kind extends TableKind,
|
|
261
|
+
SchemaName extends string | undefined,
|
|
262
|
+
ConflictArbiters extends ConflictArbiter
|
|
263
|
+
> = Kind extends "schema"
|
|
264
|
+
? {
|
|
265
|
+
pipe<Spec extends TableOptionSpec>(
|
|
266
|
+
option: TableOption<Spec, TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>>,
|
|
267
|
+
...validation: OptionValidationArgs<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>, Spec>
|
|
268
|
+
): ApplyTableOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>, Spec>
|
|
269
|
+
}
|
|
270
|
+
: {}
|
|
271
|
+
|
|
115
272
|
export type ValidateDeclaredOptions<
|
|
116
|
-
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
273
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
117
274
|
Options extends DeclaredTableOptions
|
|
118
275
|
> = {
|
|
119
276
|
readonly [K in keyof Options]: Options[K] extends TableOptionBuilderLike<infer Spec>
|
|
@@ -122,7 +279,7 @@ export type ValidateDeclaredOptions<
|
|
|
122
279
|
}
|
|
123
280
|
|
|
124
281
|
export type ApplyDeclaredOptions<
|
|
125
|
-
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
282
|
+
Table extends TableDefinition<any, any, any, "schema", any, any>,
|
|
126
283
|
Options extends DeclaredTableOptions
|
|
127
284
|
> = Options extends readonly [infer Head, ...infer Tail]
|
|
128
285
|
? Head extends TableOptionBuilderLike<infer Spec>
|
|
@@ -148,9 +305,23 @@ export interface TableSchemas<
|
|
|
148
305
|
Fields extends TableFieldMap,
|
|
149
306
|
PrimaryKeyColumns extends keyof Fields & string
|
|
150
307
|
> {
|
|
151
|
-
readonly select: Schema.
|
|
152
|
-
readonly insert: Schema.
|
|
153
|
-
readonly update: Schema.
|
|
308
|
+
readonly select: Schema.ConstraintDecoder<SelectRow<Name, Fields>, never>
|
|
309
|
+
readonly insert: Schema.ConstraintDecoder<InsertRow<Name, Fields>, never>
|
|
310
|
+
readonly update: Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
type AnyTableSchemas = {
|
|
314
|
+
readonly select: Schema.Schema<any>
|
|
315
|
+
readonly insert: Schema.Schema<any>
|
|
316
|
+
readonly update: Schema.Schema<any>
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
type TableSchemaCache<
|
|
320
|
+
Name extends string,
|
|
321
|
+
Fields extends TableFieldMap,
|
|
322
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
323
|
+
> = Partial<TableSchemas<Name, Fields, PrimaryKeyColumns>> & {
|
|
324
|
+
schemas?: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
154
325
|
}
|
|
155
326
|
|
|
156
327
|
interface TableState<
|
|
@@ -158,45 +329,37 @@ interface TableState<
|
|
|
158
329
|
Fields extends TableFieldMap,
|
|
159
330
|
PrimaryKeyColumns extends keyof Fields & string,
|
|
160
331
|
Kind extends TableKind = "schema",
|
|
161
|
-
SchemaName extends string | undefined = DefaultSchemaName
|
|
332
|
+
SchemaName extends string | undefined = DefaultSchemaName,
|
|
333
|
+
ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
|
|
162
334
|
> {
|
|
163
335
|
readonly name: Name
|
|
164
336
|
readonly baseName: string
|
|
165
337
|
readonly schemaName: SchemaName
|
|
166
338
|
readonly fields: Fields
|
|
167
339
|
readonly primaryKey: readonly PrimaryKeyColumns[]
|
|
340
|
+
readonly conflictArbiters: readonly ConflictArbiters[]
|
|
168
341
|
readonly kind: Kind
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
/** Namespace-scoped table builder. */
|
|
172
|
-
export interface TableSchemaNamespace<SchemaName extends string> {
|
|
173
|
-
readonly schemaName: SchemaName
|
|
174
|
-
readonly table: <
|
|
175
|
-
Name extends string,
|
|
176
|
-
Fields extends TableFieldMap,
|
|
177
|
-
const Options extends DeclaredTableOptions,
|
|
178
|
-
PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
|
|
179
|
-
>(
|
|
180
|
-
name: Name,
|
|
181
|
-
fields: Fields,
|
|
182
|
-
...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
183
|
-
) => ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
342
|
+
readonly casing?: Casing.Options
|
|
184
343
|
}
|
|
185
344
|
|
|
186
345
|
export type DeclaredTableOptions = readonly TableOptionBuilderLike[]
|
|
187
|
-
export type { DdlExpressionLike, IndexKeySpec, MatchingColumnArityInput, NonEmptyColumnInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
|
|
346
|
+
export type { DdlExpressionLike, IndexKeySpec, LiteralStringInput, MatchingColumnArityInput, NonEmptyColumnInput, NonEmptyStringInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
|
|
347
|
+
export type { NonEmptyFieldMap }
|
|
348
|
+
export type NonEmptySchemaNameInput<Value extends string | undefined> =
|
|
349
|
+
Value extends string ? NonEmptyStringInput<Value> : Value
|
|
188
350
|
|
|
189
351
|
export type TableDefinition<
|
|
190
352
|
Name extends string,
|
|
191
353
|
Fields extends TableFieldMap,
|
|
192
354
|
PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
|
|
193
355
|
Kind extends TableKind = "schema",
|
|
194
|
-
SchemaName extends string | undefined = DefaultSchemaName
|
|
195
|
-
|
|
356
|
+
SchemaName extends string | undefined = DefaultSchemaName,
|
|
357
|
+
ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
|
|
358
|
+
> = Pipeable & TableOptionPipe<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters> & {
|
|
196
359
|
readonly name: Name
|
|
197
360
|
readonly columns: BoundColumns<Name, Fields>
|
|
198
|
-
readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
199
|
-
readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName>
|
|
361
|
+
readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns> & AnyTableSchemas
|
|
362
|
+
readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters>
|
|
200
363
|
readonly [Plan.TypeId]: Plan.State<
|
|
201
364
|
BoundColumns<Name, Fields>,
|
|
202
365
|
never,
|
|
@@ -222,11 +385,12 @@ export type TableClassStatic<
|
|
|
222
385
|
Name extends string,
|
|
223
386
|
Fields extends TableFieldMap,
|
|
224
387
|
PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
|
|
225
|
-
SchemaName extends string | undefined = DefaultSchemaName
|
|
388
|
+
SchemaName extends string | undefined = DefaultSchemaName,
|
|
389
|
+
ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
|
|
226
390
|
> = (abstract new (...args: any[]) => any) & Pipeable & {
|
|
227
391
|
readonly columns: BoundColumns<Name, Fields>
|
|
228
392
|
readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
229
|
-
readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
|
|
393
|
+
readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>
|
|
230
394
|
readonly [Plan.TypeId]: Plan.State<
|
|
231
395
|
BoundColumns<Name, Fields>,
|
|
232
396
|
never,
|
|
@@ -245,32 +409,38 @@ export type TableClassStatic<
|
|
|
245
409
|
>
|
|
246
410
|
|
|
247
411
|
/** Minimal structural table-like contract used across helper APIs. */
|
|
248
|
-
export type AnyTable
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
: Table extends TableClassStatic<any, infer Fields extends TableFieldMap, any, any>
|
|
253
|
-
? Fields
|
|
254
|
-
: never
|
|
412
|
+
export type AnyTable<Dialect extends string = string> = {
|
|
413
|
+
readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined, ConflictArbiter>
|
|
414
|
+
readonly [OptionsSymbol]: readonly TableOptionSpec[]
|
|
415
|
+
} & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>
|
|
255
416
|
|
|
256
|
-
type
|
|
417
|
+
type CheckPredicateTable = any
|
|
418
|
+
type CheckPredicate = (table: CheckPredicateTable) => DdlExpressionLike
|
|
257
419
|
|
|
258
420
|
/** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
|
|
259
421
|
export type TableOption<
|
|
260
|
-
Spec extends TableOptionSpec = TableOptionSpec
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
Fields extends TableFieldMap,
|
|
265
|
-
PrimaryKeyColumns extends keyof Fields & string
|
|
266
|
-
>(
|
|
267
|
-
table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
|
|
268
|
-
): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>
|
|
422
|
+
Spec extends TableOptionSpec = TableOptionSpec,
|
|
423
|
+
TableContext extends SchemaTableDefinition = SchemaTableDefinition
|
|
424
|
+
> = Pipeable & {
|
|
425
|
+
readonly pipe: Pipeable["pipe"]
|
|
269
426
|
readonly option: Spec
|
|
270
|
-
|
|
427
|
+
readonly [ResolveOptionSymbol]?: (table: TableDefinition<any, any, any, "schema", any>) => Spec
|
|
428
|
+
} & (Spec extends { readonly kind: "primaryKey" }
|
|
429
|
+
? {
|
|
430
|
+
<Table extends TableContext>(
|
|
431
|
+
table: Table,
|
|
432
|
+
...validation: OptionValidationArgs<Table, Spec>
|
|
433
|
+
): ApplyOption<Table, Spec>
|
|
434
|
+
}
|
|
435
|
+
: {
|
|
436
|
+
<Table extends TableContext>(
|
|
437
|
+
table: Table,
|
|
438
|
+
...validation: OptionValidationArgs<Table, Spec>
|
|
439
|
+
): ApplyOption<Table, Spec>
|
|
440
|
+
})
|
|
271
441
|
|
|
272
442
|
const TableProto = {
|
|
273
|
-
pipe(this:
|
|
443
|
+
pipe(this: Pipeable) {
|
|
274
444
|
return pipeArguments(this, arguments)
|
|
275
445
|
}
|
|
276
446
|
}
|
|
@@ -279,7 +449,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
|
|
|
279
449
|
Object.defineProperty(value, "pipe", {
|
|
280
450
|
configurable: true,
|
|
281
451
|
writable: true,
|
|
282
|
-
value: function(this:
|
|
452
|
+
value: function(this: Value) {
|
|
283
453
|
return pipeArguments(value, arguments)
|
|
284
454
|
}
|
|
285
455
|
})
|
|
@@ -292,11 +462,44 @@ type BuildArtifacts<
|
|
|
292
462
|
PrimaryKeyColumns extends keyof Fields & string
|
|
293
463
|
> = {
|
|
294
464
|
readonly columns: BoundColumns<Name, Fields>
|
|
295
|
-
readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
296
465
|
readonly normalizedOptions: readonly TableOptionSpec[]
|
|
297
466
|
readonly primaryKey: readonly PrimaryKeyColumns[]
|
|
467
|
+
readonly conflictArbiters: readonly ConflictArbiter[]
|
|
298
468
|
}
|
|
299
469
|
|
|
470
|
+
const conflictArbitersFromOptions = (
|
|
471
|
+
options: readonly TableOptionSpec[]
|
|
472
|
+
): readonly ConflictArbiter[] =>
|
|
473
|
+
options.flatMap((option): readonly ConflictArbiter[] => {
|
|
474
|
+
if (typeof option !== "object" || option === null) {
|
|
475
|
+
return []
|
|
476
|
+
}
|
|
477
|
+
if (!("columns" in option) || !Array.isArray(option.columns) || option.columns.length === 0) {
|
|
478
|
+
return []
|
|
479
|
+
}
|
|
480
|
+
switch (option.kind) {
|
|
481
|
+
case "primaryKey":
|
|
482
|
+
case "unique":
|
|
483
|
+
return [{
|
|
484
|
+
columns: option.columns as ColumnList,
|
|
485
|
+
scope: "unconditional",
|
|
486
|
+
name: option.name,
|
|
487
|
+
constraint: true
|
|
488
|
+
}]
|
|
489
|
+
case "index":
|
|
490
|
+
return option.unique === true
|
|
491
|
+
? [{
|
|
492
|
+
columns: option.columns as ColumnList,
|
|
493
|
+
scope: option.predicate === undefined ? "unconditional" : "partial",
|
|
494
|
+
name: option.name,
|
|
495
|
+
constraint: false
|
|
496
|
+
}]
|
|
497
|
+
: []
|
|
498
|
+
default:
|
|
499
|
+
return []
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
|
|
300
503
|
const buildArtifacts = <
|
|
301
504
|
Name extends string,
|
|
302
505
|
Fields extends TableFieldMap,
|
|
@@ -305,22 +508,159 @@ const buildArtifacts = <
|
|
|
305
508
|
name: Name,
|
|
306
509
|
fields: Fields,
|
|
307
510
|
declaredOptions: readonly TableOptionSpec[],
|
|
308
|
-
schemaName: SchemaName
|
|
511
|
+
schemaName: SchemaName,
|
|
512
|
+
casing?: Casing.Options
|
|
309
513
|
): BuildArtifacts<Name, Fields, keyof Fields & string> => {
|
|
310
514
|
const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions]
|
|
311
515
|
validateFieldDialects(name, fields)
|
|
312
516
|
validateOptions(name, fields, declaredOptions)
|
|
313
517
|
const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions) as readonly (keyof Fields & string)[]
|
|
518
|
+
const conflictArbiters = conflictArbitersFromOptions(normalizedOptions)
|
|
314
519
|
const columns = Object.fromEntries(
|
|
315
|
-
Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)])
|
|
520
|
+
Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName, casing)])
|
|
316
521
|
) as BoundColumns<Name, Fields>
|
|
317
|
-
const schemas = deriveSchemas(name, fields, primaryKey)
|
|
318
522
|
return {
|
|
319
523
|
columns,
|
|
320
|
-
schemas,
|
|
321
524
|
normalizedOptions,
|
|
322
|
-
primaryKey
|
|
525
|
+
primaryKey,
|
|
526
|
+
conflictArbiters
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const getSchemaCache = <
|
|
531
|
+
Name extends string,
|
|
532
|
+
Fields extends TableFieldMap,
|
|
533
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
534
|
+
>(
|
|
535
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
536
|
+
): TableSchemaCache<Name, Fields, PrimaryKeyColumns> => {
|
|
537
|
+
const target = table as {
|
|
538
|
+
[SchemaCacheSymbol]?: TableSchemaCache<Name, Fields, PrimaryKeyColumns>
|
|
539
|
+
}
|
|
540
|
+
if (target[SchemaCacheSymbol] !== undefined) {
|
|
541
|
+
return target[SchemaCacheSymbol]
|
|
542
|
+
}
|
|
543
|
+
const cache: TableSchemaCache<Name, Fields, PrimaryKeyColumns> = {}
|
|
544
|
+
Object.defineProperty(table, SchemaCacheSymbol, {
|
|
545
|
+
configurable: true,
|
|
546
|
+
value: cache
|
|
547
|
+
})
|
|
548
|
+
return cache
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const deriveTableSchema = <
|
|
552
|
+
Variant extends TableSchemaVariant,
|
|
553
|
+
Name extends string,
|
|
554
|
+
Fields extends TableFieldMap,
|
|
555
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
556
|
+
>(
|
|
557
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
|
|
558
|
+
variant: Variant
|
|
559
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
|
|
560
|
+
const state = table[TypeId]
|
|
561
|
+
switch (variant) {
|
|
562
|
+
case "select":
|
|
563
|
+
return deriveSelectSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
564
|
+
case "insert":
|
|
565
|
+
return deriveInsertSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
566
|
+
case "update":
|
|
567
|
+
return deriveUpdateSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const schemaFor = <
|
|
572
|
+
Variant extends TableSchemaVariant,
|
|
573
|
+
Name extends string,
|
|
574
|
+
Fields extends TableFieldMap,
|
|
575
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
576
|
+
>(
|
|
577
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
|
|
578
|
+
variant: Variant
|
|
579
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
|
|
580
|
+
const cache = getSchemaCache(table)
|
|
581
|
+
const cached = cache[variant]
|
|
582
|
+
if (cached !== undefined) {
|
|
583
|
+
return cached as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
584
|
+
}
|
|
585
|
+
const schema = deriveTableSchema(table, variant)
|
|
586
|
+
cache[variant] = schema as any
|
|
587
|
+
return schema
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
export function selectSchema<
|
|
591
|
+
Name extends string,
|
|
592
|
+
Fields extends TableFieldMap,
|
|
593
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
594
|
+
>(
|
|
595
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
596
|
+
): Schema.ConstraintDecoder<SelectRow<Name, Fields>, never> {
|
|
597
|
+
return schemaFor(table, "select") as Schema.ConstraintDecoder<SelectRow<Name, Fields>, never>
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export function insertSchema<
|
|
601
|
+
Name extends string,
|
|
602
|
+
Fields extends TableFieldMap,
|
|
603
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
604
|
+
>(
|
|
605
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
606
|
+
): Schema.ConstraintDecoder<InsertRow<Name, Fields>, never> {
|
|
607
|
+
return schemaFor(table, "insert") as Schema.ConstraintDecoder<InsertRow<Name, Fields>, never>
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export function updateSchema<
|
|
611
|
+
Name extends string,
|
|
612
|
+
Fields extends TableFieldMap,
|
|
613
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
614
|
+
>(
|
|
615
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
616
|
+
): Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never> {
|
|
617
|
+
return schemaFor(table, "update") as Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const schemasFor = <
|
|
621
|
+
Name extends string,
|
|
622
|
+
Fields extends TableFieldMap,
|
|
623
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
624
|
+
>(
|
|
625
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
626
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns> => {
|
|
627
|
+
const cache = getSchemaCache(table)
|
|
628
|
+
if (cache.schemas !== undefined) {
|
|
629
|
+
return cache.schemas
|
|
323
630
|
}
|
|
631
|
+
const schemas = {} as TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
632
|
+
Object.defineProperties(schemas, {
|
|
633
|
+
select: {
|
|
634
|
+
enumerable: true,
|
|
635
|
+
get: () => selectSchema(table)
|
|
636
|
+
},
|
|
637
|
+
insert: {
|
|
638
|
+
enumerable: true,
|
|
639
|
+
get: () => insertSchema(table)
|
|
640
|
+
},
|
|
641
|
+
update: {
|
|
642
|
+
enumerable: true,
|
|
643
|
+
get: () => updateSchema(table)
|
|
644
|
+
}
|
|
645
|
+
})
|
|
646
|
+
cache.schemas = schemas
|
|
647
|
+
return schemas
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const defineSchemasGetter = <
|
|
651
|
+
Name extends string,
|
|
652
|
+
Fields extends TableFieldMap,
|
|
653
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
654
|
+
>(
|
|
655
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any>
|
|
656
|
+
): void => {
|
|
657
|
+
Object.defineProperty(table, "schemas", {
|
|
658
|
+
configurable: true,
|
|
659
|
+
enumerable: true,
|
|
660
|
+
get() {
|
|
661
|
+
return schemasFor(table)
|
|
662
|
+
}
|
|
663
|
+
})
|
|
324
664
|
}
|
|
325
665
|
|
|
326
666
|
const makeTable = <
|
|
@@ -328,7 +668,8 @@ const makeTable = <
|
|
|
328
668
|
Fields extends TableFieldMap,
|
|
329
669
|
PrimaryKeyColumns extends keyof Fields & string,
|
|
330
670
|
Kind extends TableKind = "schema",
|
|
331
|
-
SchemaName extends string | undefined = DefaultSchemaName
|
|
671
|
+
SchemaName extends string | undefined = DefaultSchemaName,
|
|
672
|
+
ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
|
|
332
673
|
>(
|
|
333
674
|
name: Name,
|
|
334
675
|
fields: Fields,
|
|
@@ -336,24 +677,27 @@ const makeTable = <
|
|
|
336
677
|
baseName: string = name,
|
|
337
678
|
kind: Kind = "schema" as Kind,
|
|
338
679
|
schemaName?: SchemaName,
|
|
339
|
-
schemaMode: "default" | "explicit" = "default"
|
|
340
|
-
|
|
680
|
+
schemaMode: "default" | "explicit" = "default",
|
|
681
|
+
casing?: Casing.Options
|
|
682
|
+
): TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters> => {
|
|
341
683
|
const resolvedSchemaName = schemaMode === "explicit"
|
|
342
684
|
? schemaName
|
|
343
685
|
: ("public" as SchemaName)
|
|
344
|
-
const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName)
|
|
686
|
+
const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName, casing)
|
|
345
687
|
const dialect = resolveFieldDialect(fields)
|
|
346
688
|
const table = attachPipe(Object.create(TableProto))
|
|
347
689
|
table.name = name
|
|
348
690
|
table.columns = artifacts.columns
|
|
349
|
-
table
|
|
691
|
+
defineSchemasGetter(table)
|
|
350
692
|
table[TypeId] = {
|
|
351
693
|
name,
|
|
352
694
|
baseName,
|
|
353
695
|
schemaName: resolvedSchemaName,
|
|
354
696
|
fields,
|
|
355
697
|
primaryKey: artifacts.primaryKey,
|
|
356
|
-
|
|
698
|
+
conflictArbiters: artifacts.conflictArbiters as readonly ConflictArbiters[],
|
|
699
|
+
kind,
|
|
700
|
+
casing
|
|
357
701
|
}
|
|
358
702
|
table[Plan.TypeId] = {
|
|
359
703
|
selection: artifacts.columns,
|
|
@@ -400,23 +744,17 @@ const applyDeclaredOptions = <
|
|
|
400
744
|
) as unknown as Table
|
|
401
745
|
}
|
|
402
746
|
|
|
403
|
-
const validateClassOptions = (declaredOptions: readonly TableOptionSpec[]): void => {
|
|
404
|
-
for (const option of declaredOptions) {
|
|
405
|
-
if (option.kind === "primaryKey") {
|
|
406
|
-
throw new Error("Table.Class does not support table-level primary keys; declare primary keys inline on columns")
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
747
|
const resolveFieldDialect = (fields: TableFieldMap): string => {
|
|
412
748
|
const dialects = [...new Set(Object.values(fields).map((field) => field.metadata.dbType.dialect))]
|
|
413
749
|
if (dialects.length === 0) {
|
|
414
750
|
throw new Error("Cannot infer table dialect from an empty field set")
|
|
415
751
|
}
|
|
416
|
-
|
|
752
|
+
const concreteDialects = dialects.filter((dialect) => dialect !== "standard")
|
|
753
|
+
const uniqueConcreteDialects = [...new Set(concreteDialects)]
|
|
754
|
+
if (uniqueConcreteDialects.length > 1) {
|
|
417
755
|
throw new Error(`Mixed table dialects are not supported: ${dialects.join(", ")}`)
|
|
418
756
|
}
|
|
419
|
-
return
|
|
757
|
+
return uniqueConcreteDialects[0] ?? "standard"
|
|
420
758
|
}
|
|
421
759
|
|
|
422
760
|
const validateFieldDialects = (tableName: string, fields: TableFieldMap): void => {
|
|
@@ -442,7 +780,6 @@ const ensureClassArtifacts = <
|
|
|
442
780
|
}
|
|
443
781
|
const state = self[TypeId]
|
|
444
782
|
const classOptions = self[options]
|
|
445
|
-
validateClassOptions(extractDeclaredOptions(classOptions))
|
|
446
783
|
const table = applyDeclaredOptions(
|
|
447
784
|
makeTable(
|
|
448
785
|
state.name,
|
|
@@ -451,15 +788,16 @@ const ensureClassArtifacts = <
|
|
|
451
788
|
state.name,
|
|
452
789
|
"schema",
|
|
453
790
|
state.schemaName,
|
|
454
|
-
state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"
|
|
791
|
+
state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit",
|
|
792
|
+
state.casing
|
|
455
793
|
) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", typeof state.schemaName>,
|
|
456
794
|
classOptions
|
|
457
795
|
)
|
|
458
796
|
const artifacts = {
|
|
459
797
|
columns: table.columns,
|
|
460
|
-
schemas: table.schemas,
|
|
461
798
|
normalizedOptions: table[OptionsSymbol],
|
|
462
|
-
primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
|
|
799
|
+
primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[],
|
|
800
|
+
conflictArbiters: table[TypeId].conflictArbiters
|
|
463
801
|
} satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
|
|
464
802
|
Object.defineProperty(self, CacheSymbol, {
|
|
465
803
|
configurable: true,
|
|
@@ -476,9 +814,6 @@ const appendOption = <
|
|
|
476
814
|
option: Spec
|
|
477
815
|
): ApplyOption<Table, Spec> => {
|
|
478
816
|
const state = table[TypeId]
|
|
479
|
-
if (state.kind !== "schema") {
|
|
480
|
-
throw new Error("Table options can only be applied to schema tables, not aliased query sources")
|
|
481
|
-
}
|
|
482
817
|
return makeTable(
|
|
483
818
|
state.name,
|
|
484
819
|
state.fields,
|
|
@@ -486,49 +821,113 @@ const appendOption = <
|
|
|
486
821
|
state.baseName,
|
|
487
822
|
state.kind,
|
|
488
823
|
state.schemaName,
|
|
489
|
-
"explicit"
|
|
824
|
+
"explicit",
|
|
825
|
+
state.casing
|
|
490
826
|
) as unknown as ApplyOption<Table, Spec>
|
|
491
827
|
}
|
|
492
828
|
|
|
493
|
-
const makeOption = <
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
return
|
|
829
|
+
const makeOption = <
|
|
830
|
+
Spec extends TableOptionSpec,
|
|
831
|
+
TableContext extends SchemaTableDefinition = SchemaTableDefinition
|
|
832
|
+
>(option: Spec): TableOption<Spec, TableContext> => {
|
|
833
|
+
return attachPipe(Object.assign(
|
|
834
|
+
<Table extends TableDefinition<any, any, any, "schema", any>>(
|
|
835
|
+
table: Table,
|
|
836
|
+
..._validation: OptionValidationArgs<Table, Spec>
|
|
837
|
+
): ApplyTableOption<Table, Spec> =>
|
|
838
|
+
appendOption(table, option) as unknown as ApplyTableOption<Table, Spec>,
|
|
839
|
+
{ option }
|
|
840
|
+
)) as unknown as TableOption<Spec, TableContext>
|
|
498
841
|
}
|
|
499
842
|
|
|
500
|
-
const makeResolvedOption = <
|
|
843
|
+
const makeResolvedOption = <
|
|
844
|
+
Spec extends TableOptionSpec,
|
|
845
|
+
TableContext extends SchemaTableDefinition = SchemaTableDefinition
|
|
846
|
+
>(
|
|
501
847
|
option: Spec,
|
|
502
848
|
resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
|
|
503
|
-
): TableOption<Spec> => {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
849
|
+
): TableOption<Spec, TableContext> => {
|
|
850
|
+
return attachPipe(Object.assign(
|
|
851
|
+
<Table extends TableDefinition<any, any, any, "schema", any>>(
|
|
852
|
+
table: Table,
|
|
853
|
+
..._validation: OptionValidationArgs<Table, Spec>
|
|
854
|
+
): ApplyTableOption<Table, Spec> =>
|
|
855
|
+
appendOption(
|
|
856
|
+
table,
|
|
857
|
+
resolve(table)
|
|
858
|
+
) as unknown as ApplyTableOption<Table, Spec>,
|
|
859
|
+
{
|
|
860
|
+
option,
|
|
861
|
+
[ResolveOptionSymbol]: resolve
|
|
862
|
+
}
|
|
863
|
+
)) as unknown as TableOption<Spec, TableContext>
|
|
508
864
|
}
|
|
509
865
|
|
|
510
866
|
export const option = <Spec extends TableOptionSpec>(spec: Spec): TableOption<Spec> =>
|
|
511
867
|
makeOption(spec)
|
|
512
868
|
|
|
513
|
-
export const optionFromTable = <
|
|
869
|
+
export const optionFromTable = <
|
|
870
|
+
Spec extends TableOptionSpec,
|
|
871
|
+
TableContext extends SchemaTableDefinition = SchemaTableDefinition
|
|
872
|
+
>(
|
|
514
873
|
spec: Spec,
|
|
515
874
|
resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
|
|
516
|
-
): TableOption<Spec> =>
|
|
875
|
+
): TableOption<Spec, TableContext> =>
|
|
517
876
|
makeResolvedOption(spec, resolve)
|
|
518
877
|
|
|
878
|
+
export const resolveOption = <
|
|
879
|
+
Spec extends TableOptionSpec,
|
|
880
|
+
TableContext extends SchemaTableDefinition
|
|
881
|
+
>(
|
|
882
|
+
option: TableOption<Spec, TableContext>,
|
|
883
|
+
table: TableContext
|
|
884
|
+
): Spec => {
|
|
885
|
+
const resolve = option[ResolveOptionSymbol]
|
|
886
|
+
return resolve === undefined ? option.option : resolve(table)
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
export const mapOption = <
|
|
890
|
+
Spec extends TableOptionSpec,
|
|
891
|
+
Next extends TableOptionSpec,
|
|
892
|
+
TableContext extends SchemaTableDefinition
|
|
893
|
+
>(
|
|
894
|
+
option: TableOption<Spec, TableContext>,
|
|
895
|
+
map: (spec: Spec) => Next
|
|
896
|
+
): TableOption<Next, TableContext> => {
|
|
897
|
+
const resolve = option[ResolveOptionSymbol]
|
|
898
|
+
return resolve === undefined
|
|
899
|
+
? makeOption<Next, TableContext>(map(option.option))
|
|
900
|
+
: makeResolvedOption<Next, TableContext>(
|
|
901
|
+
map(option.option),
|
|
902
|
+
(table) => map(resolve(table))
|
|
903
|
+
)
|
|
904
|
+
}
|
|
905
|
+
|
|
519
906
|
/** Creates a table definition from a name and field map. */
|
|
907
|
+
export function make<
|
|
908
|
+
Name extends string,
|
|
909
|
+
Fields extends TableFieldMap
|
|
910
|
+
>(
|
|
911
|
+
name: NonEmptyStringInput<Name>,
|
|
912
|
+
fields: Fields & NonEmptyFieldMap<Fields>
|
|
913
|
+
): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", DefaultSchemaName>
|
|
520
914
|
export function make<
|
|
521
915
|
Name extends string,
|
|
522
916
|
Fields extends TableFieldMap,
|
|
523
|
-
SchemaName extends string
|
|
917
|
+
const SchemaName extends string
|
|
524
918
|
>(
|
|
525
|
-
name: Name
|
|
526
|
-
fields: Fields
|
|
527
|
-
schemaName
|
|
528
|
-
): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", SchemaName>
|
|
919
|
+
name: NonEmptyStringInput<Name>,
|
|
920
|
+
fields: Fields & NonEmptyFieldMap<Fields>,
|
|
921
|
+
schemaName: NonEmptySchemaNameInput<SchemaName>
|
|
922
|
+
): TableDefinition<Name, Fields, InlinePrimaryKeyKeys<Fields>, "schema", SchemaName>
|
|
923
|
+
export function make(
|
|
924
|
+
name: string,
|
|
925
|
+
fields: TableFieldMap,
|
|
926
|
+
schemaName?: string
|
|
927
|
+
): any {
|
|
529
928
|
const resolvedSchemaName = arguments.length >= 3
|
|
530
929
|
? schemaName
|
|
531
|
-
:
|
|
930
|
+
: "public"
|
|
532
931
|
return makeTable(
|
|
533
932
|
name,
|
|
534
933
|
fields,
|
|
@@ -540,38 +939,58 @@ export function make<
|
|
|
540
939
|
)
|
|
541
940
|
}
|
|
542
941
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
):
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
942
|
+
export const withCasing = <
|
|
943
|
+
Table extends TableDefinition<any, any, any, any, any>
|
|
944
|
+
>(
|
|
945
|
+
table: Table,
|
|
946
|
+
casing: Casing.Options
|
|
947
|
+
): Table => {
|
|
948
|
+
const state = table[TypeId]
|
|
949
|
+
return makeTable(
|
|
950
|
+
state.name,
|
|
951
|
+
state.fields,
|
|
952
|
+
table[DeclaredOptionsSymbol],
|
|
953
|
+
state.baseName,
|
|
954
|
+
state.kind,
|
|
955
|
+
state.schemaName,
|
|
956
|
+
"explicit",
|
|
957
|
+
Casing.merge(state.casing, casing)
|
|
958
|
+
) as Table
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
export const withSchema = <
|
|
962
|
+
Table extends TableDefinition<any, any, any, any, any>,
|
|
963
|
+
SchemaName extends string
|
|
964
|
+
>(
|
|
965
|
+
table: Table,
|
|
966
|
+
schemaName: SchemaName,
|
|
967
|
+
schemaCasing?: Casing.Options
|
|
968
|
+
): TableDefinition<
|
|
969
|
+
Table[typeof TypeId]["name"],
|
|
970
|
+
Table[typeof TypeId]["fields"],
|
|
971
|
+
Table[typeof TypeId]["primaryKey"][number],
|
|
972
|
+
Table[typeof TypeId]["kind"],
|
|
973
|
+
SchemaName,
|
|
974
|
+
Table[typeof TypeId]["conflictArbiters"][number]
|
|
975
|
+
> => {
|
|
976
|
+
const state = table[TypeId]
|
|
977
|
+
return makeTable(
|
|
978
|
+
state.name,
|
|
979
|
+
state.fields,
|
|
980
|
+
table[DeclaredOptionsSymbol],
|
|
981
|
+
state.baseName,
|
|
982
|
+
state.kind,
|
|
572
983
|
schemaName,
|
|
573
|
-
|
|
574
|
-
|
|
984
|
+
"explicit",
|
|
985
|
+
Casing.merge(schemaCasing, state.casing)
|
|
986
|
+
) as TableDefinition<
|
|
987
|
+
Table[typeof TypeId]["name"],
|
|
988
|
+
Table[typeof TypeId]["fields"],
|
|
989
|
+
Table[typeof TypeId]["primaryKey"][number],
|
|
990
|
+
Table[typeof TypeId]["kind"],
|
|
991
|
+
SchemaName,
|
|
992
|
+
Table[typeof TypeId]["conflictArbiters"][number]
|
|
993
|
+
>
|
|
575
994
|
}
|
|
576
995
|
|
|
577
996
|
/**
|
|
@@ -586,39 +1005,43 @@ export const alias = <
|
|
|
586
1005
|
Fields extends TableFieldMap,
|
|
587
1006
|
PrimaryKeyColumns extends keyof Fields & string,
|
|
588
1007
|
SchemaName extends string,
|
|
1008
|
+
ConflictArbiters extends ConflictArbiter,
|
|
589
1009
|
AliasName extends string
|
|
590
1010
|
>(
|
|
591
|
-
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName>,
|
|
592
|
-
aliasName: AliasName
|
|
1011
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName, ConflictArbiters> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName, ConflictArbiters>,
|
|
1012
|
+
aliasName: LiteralStringInput<AliasName>
|
|
593
1013
|
): TableDefinition<
|
|
594
1014
|
AliasName,
|
|
595
1015
|
Fields,
|
|
596
1016
|
PrimaryKeyColumns,
|
|
597
1017
|
"alias",
|
|
598
|
-
SchemaName
|
|
1018
|
+
SchemaName,
|
|
1019
|
+
ConflictArbiters
|
|
599
1020
|
> => {
|
|
600
1021
|
const state = table[TypeId]
|
|
601
1022
|
const columns = Object.fromEntries(
|
|
602
|
-
Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column as AnyColumnDefinition, state.baseName, state.schemaName)])
|
|
1023
|
+
Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName as AliasName, key, column as AnyColumnDefinition, state.baseName, state.schemaName, state.casing)])
|
|
603
1024
|
) as BoundColumns<AliasName, Fields>
|
|
604
1025
|
const aliased = attachPipe(Object.create(TableProto))
|
|
605
|
-
aliased.name = aliasName
|
|
1026
|
+
aliased.name = aliasName as AliasName
|
|
606
1027
|
aliased.columns = columns
|
|
607
|
-
aliased
|
|
1028
|
+
defineSchemasGetter(aliased)
|
|
608
1029
|
aliased[TypeId] = {
|
|
609
|
-
name: aliasName,
|
|
1030
|
+
name: aliasName as AliasName,
|
|
610
1031
|
baseName: state.baseName,
|
|
611
1032
|
schemaName: state.schemaName,
|
|
612
1033
|
fields: state.fields,
|
|
613
1034
|
primaryKey: state.primaryKey,
|
|
614
|
-
|
|
1035
|
+
conflictArbiters: state.conflictArbiters,
|
|
1036
|
+
kind: "alias",
|
|
1037
|
+
casing: state.casing
|
|
615
1038
|
}
|
|
616
1039
|
aliased[Plan.TypeId] = {
|
|
617
1040
|
selection: columns,
|
|
618
1041
|
required: undefined as never,
|
|
619
1042
|
available: {
|
|
620
1043
|
[aliasName]: {
|
|
621
|
-
name: aliasName,
|
|
1044
|
+
name: aliasName as AliasName,
|
|
622
1045
|
mode: "required",
|
|
623
1046
|
baseName: state.baseName
|
|
624
1047
|
}
|
|
@@ -642,19 +1065,38 @@ export const alias = <
|
|
|
642
1065
|
* The returned base class can be extended and configured with
|
|
643
1066
|
* `static readonly [Table.options]`.
|
|
644
1067
|
*/
|
|
1068
|
+
export function Class<Self = never>(
|
|
1069
|
+
name: "",
|
|
1070
|
+
schemaName?: string | undefined
|
|
1071
|
+
): never
|
|
1072
|
+
export function Class<Self = never>(
|
|
1073
|
+
name: string,
|
|
1074
|
+
schemaName: ""
|
|
1075
|
+
): never
|
|
1076
|
+
export function Class<
|
|
1077
|
+
Self = never,
|
|
1078
|
+
const SchemaName extends string | undefined = DefaultSchemaName,
|
|
1079
|
+
const Name extends string = string
|
|
1080
|
+
>(
|
|
1081
|
+
name: NonEmptyStringInput<Name>,
|
|
1082
|
+
schemaName?: NonEmptySchemaNameInput<SchemaName>
|
|
1083
|
+
): <Fields extends TableFieldMap>(fields: Fields & NonEmptyFieldMap<Fields>) => [Self] extends [never]
|
|
1084
|
+
? MissingSelfGeneric
|
|
1085
|
+
: TableClassStatic<Name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName>
|
|
645
1086
|
export function Class<
|
|
646
1087
|
Self = never,
|
|
647
|
-
SchemaName extends string | undefined = DefaultSchemaName
|
|
1088
|
+
SchemaName extends string | undefined = DefaultSchemaName,
|
|
1089
|
+
Name extends string = string
|
|
648
1090
|
>(
|
|
649
1091
|
name: string,
|
|
650
1092
|
schemaName?: SchemaName
|
|
651
|
-
) {
|
|
1093
|
+
): any {
|
|
652
1094
|
const resolvedSchemaName = arguments.length >= 2
|
|
653
1095
|
? schemaName
|
|
654
1096
|
: ("public" as SchemaName)
|
|
655
|
-
return <Fields extends TableFieldMap>(fields: Fields): [Self] extends [never]
|
|
1097
|
+
return <Fields extends TableFieldMap>(fields: Fields & NonEmptyFieldMap<Fields>): [Self] extends [never]
|
|
656
1098
|
? MissingSelfGeneric
|
|
657
|
-
: TableClassStatic<
|
|
1099
|
+
: TableClassStatic<Name, Fields, InlinePrimaryKeyKeys<Fields>, SchemaName> => {
|
|
658
1100
|
abstract class TableClassBase {
|
|
659
1101
|
static readonly tableName = name
|
|
660
1102
|
|
|
@@ -663,18 +1105,19 @@ export function Class<
|
|
|
663
1105
|
}
|
|
664
1106
|
|
|
665
1107
|
static get schemas() {
|
|
666
|
-
return
|
|
1108
|
+
return schemasFor(this as any)
|
|
667
1109
|
}
|
|
668
1110
|
|
|
669
1111
|
static get [TypeId]() {
|
|
670
|
-
const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<
|
|
671
|
-
|
|
1112
|
+
const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<Name, Fields>)[options])
|
|
1113
|
+
const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions]
|
|
672
1114
|
return {
|
|
673
1115
|
name,
|
|
674
1116
|
baseName: name,
|
|
675
1117
|
schemaName: resolvedSchemaName,
|
|
676
1118
|
fields,
|
|
677
1119
|
primaryKey: resolvePrimaryKeyColumns(fields, collectInlineOptions(fields)),
|
|
1120
|
+
conflictArbiters: conflictArbitersFromOptions(normalizedOptions),
|
|
678
1121
|
kind: "schema"
|
|
679
1122
|
}
|
|
680
1123
|
}
|
|
@@ -699,7 +1142,7 @@ export function Class<
|
|
|
699
1142
|
return ensureClassArtifacts(this as any).normalizedOptions
|
|
700
1143
|
}
|
|
701
1144
|
|
|
702
|
-
static pipe(this:
|
|
1145
|
+
static pipe(this: Pipeable) {
|
|
703
1146
|
return pipeArguments(this, arguments)
|
|
704
1147
|
}
|
|
705
1148
|
}
|
|
@@ -718,97 +1161,236 @@ export function Class<
|
|
|
718
1161
|
}
|
|
719
1162
|
}
|
|
720
1163
|
|
|
1164
|
+
const selectionArray = (selection: AnyColumnSelection): readonly AnyBoundColumn[] =>
|
|
1165
|
+
(Array.isArray(selection) ? selection : [selection]) as readonly AnyBoundColumn[]
|
|
1166
|
+
|
|
1167
|
+
export const selectedColumnList = <Selection extends AnyColumnSelection>(
|
|
1168
|
+
selection: Selection
|
|
1169
|
+
): SelectedColumns<Selection> =>
|
|
1170
|
+
selectionArray(selection).map((column) => column[BoundColumnTypeId].columnName) as unknown as SelectedColumns<Selection>
|
|
1171
|
+
|
|
1172
|
+
const referenceFromSelection = <Selection extends AnyColumnSelection>(selection: Selection) => {
|
|
1173
|
+
const columns = selectionArray(selection)
|
|
1174
|
+
const first = columns[0]!
|
|
1175
|
+
const bound = first[BoundColumnTypeId]
|
|
1176
|
+
return {
|
|
1177
|
+
tableName: bound.baseTableName,
|
|
1178
|
+
schemaName: bound.schemaName,
|
|
1179
|
+
casing: bound.casing,
|
|
1180
|
+
columns: columns.map((column) => column[BoundColumnTypeId].columnName) as unknown as SelectedColumns<Selection>
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
721
1184
|
/** Declares a table-level primary key. */
|
|
722
|
-
export
|
|
723
|
-
|
|
1185
|
+
export function primaryKey<
|
|
1186
|
+
Table extends SchemaTableDefinition,
|
|
1187
|
+
Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
|
|
1188
|
+
>(
|
|
1189
|
+
columns: ConcreteSelector<Table, Selection>
|
|
1190
|
+
): TableOption<{
|
|
1191
|
+
readonly kind: "primaryKey"
|
|
1192
|
+
readonly columns: SelectedColumns<Selection>
|
|
1193
|
+
}, Table>
|
|
1194
|
+
export function primaryKey<
|
|
1195
|
+
Selection extends AnyColumnSelection
|
|
724
1196
|
>(
|
|
725
|
-
columns:
|
|
1197
|
+
columns: (table: LooseTableSelection) => Selection
|
|
1198
|
+
): TableOption<{
|
|
1199
|
+
readonly kind: "primaryKey"
|
|
1200
|
+
readonly columns: SelectedColumns<Selection>
|
|
1201
|
+
}>
|
|
1202
|
+
export function primaryKey(
|
|
1203
|
+
columns: (table: any) => AnyColumnSelection
|
|
726
1204
|
): TableOption<{
|
|
727
1205
|
readonly kind: "primaryKey"
|
|
728
|
-
readonly columns:
|
|
729
|
-
}>
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1206
|
+
readonly columns: readonly [string, ...string[]]
|
|
1207
|
+
}> {
|
|
1208
|
+
return makeResolvedOption({
|
|
1209
|
+
kind: "primaryKey",
|
|
1210
|
+
columns: [] as unknown as readonly [string, ...string[]]
|
|
1211
|
+
}, (table) => ({
|
|
1212
|
+
kind: "primaryKey",
|
|
1213
|
+
columns: selectedColumnList(columns(table))
|
|
1214
|
+
}))
|
|
1215
|
+
}
|
|
733
1216
|
|
|
734
1217
|
/** Declares a table-level unique constraint. */
|
|
735
|
-
export
|
|
736
|
-
|
|
1218
|
+
export function unique<
|
|
1219
|
+
Table extends SchemaTableDefinition,
|
|
1220
|
+
Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
|
|
1221
|
+
>(
|
|
1222
|
+
columns: ConcreteSelector<Table, Selection>
|
|
1223
|
+
): TableOption<{
|
|
1224
|
+
readonly kind: "unique"
|
|
1225
|
+
readonly columns: SelectedColumns<Selection>
|
|
1226
|
+
}, Table>
|
|
1227
|
+
export function unique<
|
|
1228
|
+
Selection extends AnyColumnSelection
|
|
737
1229
|
>(
|
|
738
|
-
columns:
|
|
1230
|
+
columns: (table: LooseTableSelection) => Selection
|
|
739
1231
|
): TableOption<{
|
|
740
1232
|
readonly kind: "unique"
|
|
741
|
-
readonly columns:
|
|
742
|
-
}>
|
|
743
|
-
|
|
744
|
-
columns:
|
|
745
|
-
|
|
1233
|
+
readonly columns: SelectedColumns<Selection>
|
|
1234
|
+
}>
|
|
1235
|
+
export function unique(
|
|
1236
|
+
columns: (table: any) => AnyColumnSelection
|
|
1237
|
+
): TableOption<{
|
|
1238
|
+
readonly kind: "unique"
|
|
1239
|
+
readonly columns: readonly [string, ...string[]]
|
|
1240
|
+
}> {
|
|
1241
|
+
return makeResolvedOption({
|
|
1242
|
+
kind: "unique",
|
|
1243
|
+
columns: [] as unknown as readonly [string, ...string[]]
|
|
1244
|
+
}, (table) => ({
|
|
1245
|
+
kind: "unique",
|
|
1246
|
+
columns: selectedColumnList(columns(table))
|
|
1247
|
+
}))
|
|
1248
|
+
}
|
|
746
1249
|
|
|
747
1250
|
/** Declares a table-level index. */
|
|
748
|
-
export
|
|
749
|
-
|
|
1251
|
+
export function index<
|
|
1252
|
+
Table extends SchemaTableDefinition,
|
|
1253
|
+
Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
|
|
750
1254
|
>(
|
|
751
|
-
columns:
|
|
1255
|
+
columns: ConcreteSelector<Table, Selection>
|
|
752
1256
|
): TableOption<{
|
|
753
1257
|
readonly kind: "index"
|
|
754
|
-
readonly columns:
|
|
755
|
-
}>
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1258
|
+
readonly columns: SelectedColumns<Selection>
|
|
1259
|
+
}, Table>
|
|
1260
|
+
export function index<
|
|
1261
|
+
Selection extends AnyColumnSelection
|
|
1262
|
+
>(
|
|
1263
|
+
columns: (table: LooseTableSelection) => Selection
|
|
1264
|
+
): TableOption<{
|
|
1265
|
+
readonly kind: "index"
|
|
1266
|
+
readonly columns: SelectedColumns<Selection>
|
|
1267
|
+
}>
|
|
1268
|
+
export function index(
|
|
1269
|
+
columns: (table: any) => AnyColumnSelection
|
|
1270
|
+
): TableOption<{
|
|
1271
|
+
readonly kind: "index"
|
|
1272
|
+
readonly columns: readonly [string, ...string[]]
|
|
1273
|
+
}> {
|
|
1274
|
+
return makeResolvedOption({
|
|
1275
|
+
kind: "index",
|
|
1276
|
+
columns: [] as unknown as readonly [string, ...string[]]
|
|
1277
|
+
}, (table) => ({
|
|
1278
|
+
kind: "index",
|
|
1279
|
+
columns: selectedColumnList(columns(table))
|
|
1280
|
+
}))
|
|
1281
|
+
}
|
|
759
1282
|
|
|
760
1283
|
/** Declares a table-level foreign key. */
|
|
761
|
-
export
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
>(
|
|
766
|
-
columns:
|
|
767
|
-
target: () =>
|
|
768
|
-
referencedColumns: TargetColumns & NonEmptyColumnInput<TargetColumns> & MatchingColumnArityInput<LocalColumns, TargetColumns>
|
|
1284
|
+
export function foreignKey<
|
|
1285
|
+
Table extends SchemaTableDefinition,
|
|
1286
|
+
LocalSelection extends TableColumnSelection<Table> = TableColumnSelection<Table>,
|
|
1287
|
+
TargetSelection extends AnyColumnSelection = AnyColumnSelection
|
|
1288
|
+
>(
|
|
1289
|
+
columns: ConcreteSelector<Table, LocalSelection>,
|
|
1290
|
+
target: () => TargetSelection & MatchingSelectionArityInput<LocalSelection, TargetSelection>
|
|
769
1291
|
): TableOption<{
|
|
770
1292
|
readonly kind: "foreignKey"
|
|
771
|
-
readonly columns:
|
|
1293
|
+
readonly columns: SelectedColumns<LocalSelection>
|
|
772
1294
|
readonly references: () => {
|
|
773
1295
|
readonly tableName: string
|
|
774
1296
|
readonly schemaName?: string
|
|
775
|
-
readonly
|
|
776
|
-
readonly
|
|
1297
|
+
readonly casing?: Casing.Options
|
|
1298
|
+
readonly columns: SelectedColumns<TargetSelection>
|
|
777
1299
|
}
|
|
778
|
-
}>
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1300
|
+
}, Table>
|
|
1301
|
+
export function foreignKey<
|
|
1302
|
+
LocalSelection extends AnyColumnSelection,
|
|
1303
|
+
TargetSelection extends AnyColumnSelection
|
|
1304
|
+
>(
|
|
1305
|
+
columns: (table: LooseTableSelection) => LocalSelection,
|
|
1306
|
+
target: () => TargetSelection
|
|
1307
|
+
): TableOption<{
|
|
1308
|
+
readonly kind: "foreignKey"
|
|
1309
|
+
readonly columns: SelectedColumns<LocalSelection>
|
|
1310
|
+
readonly references: () => {
|
|
1311
|
+
readonly tableName: string
|
|
1312
|
+
readonly schemaName?: string
|
|
1313
|
+
readonly casing?: Casing.Options
|
|
1314
|
+
readonly columns: SelectedColumns<TargetSelection>
|
|
1315
|
+
}
|
|
1316
|
+
}>
|
|
1317
|
+
export function foreignKey(
|
|
1318
|
+
columns: (table: any) => AnyColumnSelection,
|
|
1319
|
+
target: () => AnyColumnSelection
|
|
1320
|
+
): TableOption<{
|
|
1321
|
+
readonly kind: "foreignKey"
|
|
1322
|
+
readonly columns: readonly [string, ...string[]]
|
|
1323
|
+
readonly references: () => {
|
|
1324
|
+
readonly tableName: string
|
|
1325
|
+
readonly schemaName?: string
|
|
1326
|
+
readonly casing?: Casing.Options
|
|
1327
|
+
readonly columns: readonly [string, ...string[]]
|
|
1328
|
+
}
|
|
1329
|
+
}> {
|
|
1330
|
+
return makeResolvedOption({
|
|
1331
|
+
kind: "foreignKey",
|
|
1332
|
+
columns: [] as unknown as readonly [string, ...string[]],
|
|
1333
|
+
references: () => referenceFromSelection(target())
|
|
1334
|
+
}, (table) => ({
|
|
1335
|
+
kind: "foreignKey",
|
|
1336
|
+
columns: selectedColumnList(columns(table)),
|
|
1337
|
+
references: () => referenceFromSelection(target())
|
|
1338
|
+
}))
|
|
1339
|
+
}
|
|
788
1340
|
|
|
789
1341
|
/** Declares a check constraint expression. */
|
|
790
|
-
export
|
|
791
|
-
name: Name
|
|
1342
|
+
export function check<const Name extends string>(
|
|
1343
|
+
name: NonEmptyStringInput<Name>,
|
|
792
1344
|
predicate: DdlExpressionLike
|
|
793
1345
|
): TableOption<{
|
|
794
1346
|
readonly kind: "check"
|
|
795
1347
|
readonly name: Name
|
|
796
1348
|
readonly predicate: DdlExpressionLike
|
|
797
|
-
}>
|
|
798
|
-
|
|
799
|
-
name
|
|
800
|
-
predicate
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
1349
|
+
}>
|
|
1350
|
+
export function check<const Name extends string>(
|
|
1351
|
+
name: NonEmptyStringInput<Name>,
|
|
1352
|
+
predicate: CheckPredicate
|
|
1353
|
+
): TableOption<{
|
|
1354
|
+
readonly kind: "check"
|
|
1355
|
+
readonly name: Name
|
|
1356
|
+
readonly predicate: DdlExpressionLike
|
|
1357
|
+
}>
|
|
1358
|
+
export function check(
|
|
1359
|
+
name: string,
|
|
1360
|
+
predicate: DdlExpressionLike | CheckPredicate
|
|
1361
|
+
): TableOption<{
|
|
1362
|
+
readonly kind: "check"
|
|
1363
|
+
readonly name: string
|
|
1364
|
+
readonly predicate: DdlExpressionLike
|
|
1365
|
+
}> {
|
|
1366
|
+
const spec = {
|
|
1367
|
+
kind: "check",
|
|
1368
|
+
name,
|
|
1369
|
+
predicate: predicate as DdlExpressionLike
|
|
1370
|
+
} as const
|
|
1371
|
+
return typeof predicate === "function"
|
|
1372
|
+
? makeResolvedOption(spec, (table) => ({
|
|
1373
|
+
...spec,
|
|
1374
|
+
predicate: predicate(table as CheckPredicateTable)
|
|
1375
|
+
}))
|
|
1376
|
+
: makeOption(spec)
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/** Extracts the row type produced by `selectSchema(table)`. */
|
|
1380
|
+
export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
1381
|
+
readonly name: infer Name extends string
|
|
1382
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
1383
|
+
} ? SelectRow<Name, Fields> : never
|
|
1384
|
+
|
|
1385
|
+
/** Extracts the payload type produced by `insertSchema(table)`. */
|
|
1386
|
+
export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
1387
|
+
readonly name: infer Name extends string
|
|
1388
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
1389
|
+
} ? InsertRow<Name, Fields> : never
|
|
1390
|
+
|
|
1391
|
+
/** Extracts the payload type produced by `updateSchema(table)`. */
|
|
1392
|
+
export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
1393
|
+
readonly name: infer Name extends string
|
|
1394
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
1395
|
+
readonly primaryKey: readonly (infer PrimaryKeyColumns)[]
|
|
1396
|
+
} ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never
|