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