effect-qb 0.16.0 → 4.0.0-beta.66
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 +7 -0
- package/dist/mysql.js +1858 -715
- package/dist/postgres/metadata.js +2036 -172
- package/dist/postgres.js +8011 -6849
- package/dist/sqlite.js +8433 -0
- package/package.json +7 -4
- package/src/internal/column-state.d.ts +3 -3
- package/src/internal/column-state.ts +3 -3
- package/src/internal/column.ts +8 -8
- package/src/internal/derived-table.ts +29 -3
- package/src/internal/dialect.ts +3 -1
- package/src/internal/dsl-mutation-runtime.ts +173 -4
- package/src/internal/dsl-plan-runtime.ts +165 -20
- package/src/internal/dsl-query-runtime.ts +60 -6
- package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
- package/src/internal/executor.ts +100 -43
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +141 -1
- package/src/internal/implication-runtime.ts +2 -1
- 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 +27 -3
- package/src/internal/query.d.ts +1 -1
- package/src/internal/query.ts +253 -31
- package/src/internal/renderer.ts +35 -2
- package/src/internal/runtime/driver-value-mapping.ts +60 -2
- package/src/internal/runtime/normalize.ts +62 -38
- package/src/internal/runtime/schema.ts +32 -40
- package/src/internal/runtime/value.ts +159 -39
- package/src/internal/scalar.d.ts +1 -1
- package/src/internal/scalar.ts +1 -1
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +95 -43
- package/src/internal/table-options.ts +108 -1
- package/src/internal/table.d.ts +29 -22
- package/src/internal/table.ts +260 -53
- package/src/mysql/column.ts +24 -8
- package/src/mysql/datatypes/index.ts +21 -0
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +4 -4
- package/src/mysql/function/temporal.ts +1 -1
- package/src/mysql/internal/dsl.ts +759 -235
- package/src/mysql/internal/renderer.ts +2 -1
- package/src/mysql/internal/sql-expression-renderer.ts +486 -130
- package/src/mysql/query.ts +9 -2
- package/src/mysql/table.ts +64 -35
- package/src/postgres/column.ts +14 -12
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +52 -9
- package/src/postgres/function/core.ts +19 -1
- package/src/postgres/function/temporal.ts +1 -1
- package/src/postgres/internal/dsl.ts +705 -256
- package/src/postgres/internal/renderer.ts +2 -1
- package/src/postgres/internal/schema-ddl.ts +2 -1
- package/src/postgres/internal/schema-model.ts +6 -3
- package/src/postgres/internal/sql-expression-renderer.ts +420 -91
- package/src/postgres/json.ts +57 -17
- package/src/postgres/query.ts +9 -2
- package/src/postgres/schema-management.ts +92 -6
- package/src/postgres/schema.ts +1 -1
- package/src/postgres/table.ts +203 -75
- package/src/sqlite/column.ts +128 -0
- package/src/sqlite/datatypes/index.ts +79 -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 +227 -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 +37 -0
- package/src/sqlite/internal/dsl.ts +6927 -0
- package/src/sqlite/internal/renderer.ts +47 -0
- package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
- package/src/sqlite/json.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +24 -0
- package/src/sqlite/table.ts +175 -0
- package/src/sqlite.ts +22 -0
package/src/internal/table.ts
CHANGED
|
@@ -12,18 +12,25 @@ import {
|
|
|
12
12
|
resolvePrimaryKeyColumns,
|
|
13
13
|
type DdlExpressionLike,
|
|
14
14
|
type IndexKeySpec,
|
|
15
|
+
type MatchingColumnArityInput,
|
|
16
|
+
type NonEmptyColumnInput,
|
|
15
17
|
type NormalizeColumns,
|
|
16
18
|
type ReferentialAction,
|
|
17
19
|
type TableOptionSpec,
|
|
20
|
+
type ValidateForeignKeyOptionColumns,
|
|
21
|
+
type ValidateIndexOptionColumns,
|
|
18
22
|
type ValidateKnownColumns,
|
|
19
23
|
type ValidatePrimaryKeyColumns,
|
|
20
24
|
validateOptions
|
|
21
25
|
} from "./table-options.js"
|
|
22
26
|
import {
|
|
23
|
-
|
|
27
|
+
deriveInsertSchema,
|
|
28
|
+
deriveSelectSchema,
|
|
29
|
+
deriveUpdateSchema,
|
|
24
30
|
type InsertRow,
|
|
25
31
|
type SelectRow,
|
|
26
32
|
type TableFieldMap,
|
|
33
|
+
type TableSchemaVariant,
|
|
27
34
|
type UpdateRow
|
|
28
35
|
} from "./schema-derivation.js"
|
|
29
36
|
|
|
@@ -35,6 +42,7 @@ export const OptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/normaliz
|
|
|
35
42
|
export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOptions")
|
|
36
43
|
|
|
37
44
|
const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
|
|
45
|
+
const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
|
|
38
46
|
const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
|
|
39
47
|
|
|
40
48
|
type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
|
|
@@ -44,18 +52,32 @@ type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
|
|
|
44
52
|
type TableDialect<Fields extends TableFieldMap> = Fields[keyof Fields][typeof import("./column-state.js").ColumnTypeId]["dbType"]["dialect"]
|
|
45
53
|
type TableKind = "schema" | "alias"
|
|
46
54
|
type DefaultSchemaName = "public"
|
|
47
|
-
type
|
|
55
|
+
type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
|
|
56
|
+
type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
|
|
57
|
+
type FieldIndexKeySpec<Fields extends TableFieldMap> =
|
|
58
|
+
| (Extract<IndexKeySpec, { readonly kind: "column" }> & { readonly column: FieldColumnName<Fields> })
|
|
59
|
+
| Extract<IndexKeySpec, { readonly kind: "expression" }>
|
|
60
|
+
type ClassOptionSpec<Fields extends TableFieldMap = TableFieldMap> =
|
|
61
|
+
| (Omit<Extract<TableOptionSpec, { readonly kind: "index" }>, "columns" | "include" | "keys"> & {
|
|
62
|
+
readonly columns?: FieldColumnList<Fields>
|
|
63
|
+
readonly include?: readonly FieldColumnName<Fields>[]
|
|
64
|
+
readonly keys?: readonly [FieldIndexKeySpec<Fields>, ...FieldIndexKeySpec<Fields>[]]
|
|
65
|
+
})
|
|
66
|
+
| (Omit<Extract<TableOptionSpec, { readonly kind: "unique" }>, "columns"> & {
|
|
67
|
+
readonly columns: FieldColumnList<Fields>
|
|
68
|
+
})
|
|
69
|
+
| (Omit<Extract<TableOptionSpec, { readonly kind: "foreignKey" }>, "columns"> & {
|
|
70
|
+
readonly columns: FieldColumnList<Fields>
|
|
71
|
+
})
|
|
72
|
+
| Extract<TableOptionSpec, { readonly kind: "check" }>
|
|
48
73
|
interface TableOptionBuilderLike<
|
|
49
74
|
Spec extends TableOptionSpec = TableOptionSpec
|
|
50
75
|
> {
|
|
51
|
-
(
|
|
52
|
-
table: TableDefinition<any, any, any, "schema", any>
|
|
53
|
-
): TableDefinition<any, any, any, "schema", any>
|
|
54
76
|
readonly option: Spec
|
|
55
77
|
}
|
|
56
78
|
|
|
57
|
-
type ClassTableOption = TableOptionBuilderLike<ClassOptionSpec
|
|
58
|
-
type ClassDeclaredTableOptions = readonly ClassTableOption[]
|
|
79
|
+
type ClassTableOption<Fields extends TableFieldMap> = TableOptionBuilderLike<ClassOptionSpec<Fields>>
|
|
80
|
+
type ClassDeclaredTableOptions<Fields extends TableFieldMap> = readonly ClassTableOption<Fields>[]
|
|
59
81
|
|
|
60
82
|
type BuildPrimaryKey<
|
|
61
83
|
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
@@ -69,9 +91,13 @@ type OptionInputTable<
|
|
|
69
91
|
Spec extends TableOptionSpec
|
|
70
92
|
> = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
|
|
71
93
|
? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
|
|
72
|
-
: Spec extends { readonly
|
|
73
|
-
?
|
|
74
|
-
:
|
|
94
|
+
: Spec extends { readonly kind: "index" }
|
|
95
|
+
? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
|
|
96
|
+
: Spec extends { readonly kind: "foreignKey" }
|
|
97
|
+
? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : Table
|
|
98
|
+
: Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
99
|
+
? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : Table
|
|
100
|
+
: Table
|
|
75
101
|
|
|
76
102
|
type ApplyOption<
|
|
77
103
|
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
@@ -90,6 +116,26 @@ type ApplyOption<
|
|
|
90
116
|
"schema"
|
|
91
117
|
>
|
|
92
118
|
|
|
119
|
+
export type ValidateDeclaredOptions<
|
|
120
|
+
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
121
|
+
Options extends DeclaredTableOptions
|
|
122
|
+
> = {
|
|
123
|
+
readonly [K in keyof Options]: Options[K] extends TableOptionBuilderLike<infer Spec>
|
|
124
|
+
? OptionInputTable<Table, Spec> extends never ? never : Options[K]
|
|
125
|
+
: never
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type ApplyDeclaredOptions<
|
|
129
|
+
Table extends TableDefinition<any, any, any, "schema", any>,
|
|
130
|
+
Options extends DeclaredTableOptions
|
|
131
|
+
> = Options extends readonly [infer Head, ...infer Tail]
|
|
132
|
+
? Head extends TableOptionBuilderLike<infer Spec>
|
|
133
|
+
? Tail extends DeclaredTableOptions
|
|
134
|
+
? ApplyDeclaredOptions<ApplyOption<Table, Spec>, Tail>
|
|
135
|
+
: ApplyOption<Table, Spec>
|
|
136
|
+
: Table
|
|
137
|
+
: Table
|
|
138
|
+
|
|
93
139
|
export type MissingSelfGeneric = "Missing `Self` generic - use `class Self extends Table.Class<Self>(...) {}`"
|
|
94
140
|
|
|
95
141
|
/** Bound columns keyed by field name for a particular table. */
|
|
@@ -106,9 +152,17 @@ export interface TableSchemas<
|
|
|
106
152
|
Fields extends TableFieldMap,
|
|
107
153
|
PrimaryKeyColumns extends keyof Fields & string
|
|
108
154
|
> {
|
|
109
|
-
readonly select: Schema.
|
|
110
|
-
readonly insert: Schema.
|
|
111
|
-
readonly update: Schema.
|
|
155
|
+
readonly select: Schema.Decoder<SelectRow<Name, Fields>, never>
|
|
156
|
+
readonly insert: Schema.Decoder<InsertRow<Name, Fields>, never>
|
|
157
|
+
readonly update: Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
type TableSchemaCache<
|
|
161
|
+
Name extends string,
|
|
162
|
+
Fields extends TableFieldMap,
|
|
163
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
164
|
+
> = Partial<TableSchemas<Name, Fields, PrimaryKeyColumns>> & {
|
|
165
|
+
schemas?: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
112
166
|
}
|
|
113
167
|
|
|
114
168
|
interface TableState<
|
|
@@ -132,16 +186,17 @@ export interface TableSchemaNamespace<SchemaName extends string> {
|
|
|
132
186
|
readonly table: <
|
|
133
187
|
Name extends string,
|
|
134
188
|
Fields extends TableFieldMap,
|
|
189
|
+
const Options extends DeclaredTableOptions,
|
|
135
190
|
PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
|
|
136
191
|
>(
|
|
137
192
|
name: Name,
|
|
138
193
|
fields: Fields,
|
|
139
|
-
...options:
|
|
140
|
-
) => TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
|
|
194
|
+
...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
195
|
+
) => ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
141
196
|
}
|
|
142
197
|
|
|
143
198
|
export type DeclaredTableOptions = readonly TableOptionBuilderLike[]
|
|
144
|
-
export type { DdlExpressionLike, IndexKeySpec, NormalizeColumns, ReferentialAction } from "./table-options.js"
|
|
199
|
+
export type { DdlExpressionLike, IndexKeySpec, MatchingColumnArityInput, NonEmptyColumnInput, NormalizeColumns, ReferentialAction } from "./table-options.js"
|
|
145
200
|
|
|
146
201
|
export type TableDefinition<
|
|
147
202
|
Name extends string,
|
|
@@ -192,7 +247,7 @@ export type TableClassStatic<
|
|
|
192
247
|
>
|
|
193
248
|
readonly [OptionsSymbol]: readonly TableOptionSpec[]
|
|
194
249
|
readonly [DeclaredOptionsSymbol]?: readonly TableOptionSpec[]
|
|
195
|
-
readonly [options]?: ClassDeclaredTableOptions
|
|
250
|
+
readonly [options]?: ClassDeclaredTableOptions<Fields>
|
|
196
251
|
readonly tableName: Name
|
|
197
252
|
} & BoundColumns<Name, Fields> & Plan.RowSet<
|
|
198
253
|
BoundColumns<Name, Fields>,
|
|
@@ -202,7 +257,14 @@ export type TableClassStatic<
|
|
|
202
257
|
>
|
|
203
258
|
|
|
204
259
|
/** Minimal structural table-like contract used across helper APIs. */
|
|
205
|
-
export type AnyTable
|
|
260
|
+
export type AnyTable<Dialect extends string = string> = {
|
|
261
|
+
readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>
|
|
262
|
+
readonly [OptionsSymbol]: readonly TableOptionSpec[]
|
|
263
|
+
} & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>
|
|
264
|
+
|
|
265
|
+
type FieldsOfAnyTable<Table extends AnyTable> = Table[typeof TypeId]["fields"]
|
|
266
|
+
|
|
267
|
+
type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
|
|
206
268
|
|
|
207
269
|
/** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
|
|
208
270
|
export type TableOption<
|
|
@@ -241,7 +303,6 @@ type BuildArtifacts<
|
|
|
241
303
|
PrimaryKeyColumns extends keyof Fields & string
|
|
242
304
|
> = {
|
|
243
305
|
readonly columns: BoundColumns<Name, Fields>
|
|
244
|
-
readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
245
306
|
readonly normalizedOptions: readonly TableOptionSpec[]
|
|
246
307
|
readonly primaryKey: readonly PrimaryKeyColumns[]
|
|
247
308
|
}
|
|
@@ -263,15 +324,149 @@ const buildArtifacts = <
|
|
|
263
324
|
const columns = Object.fromEntries(
|
|
264
325
|
Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)])
|
|
265
326
|
) as BoundColumns<Name, Fields>
|
|
266
|
-
const schemas = deriveSchemas(name, fields, primaryKey)
|
|
267
327
|
return {
|
|
268
328
|
columns,
|
|
269
|
-
schemas,
|
|
270
329
|
normalizedOptions,
|
|
271
330
|
primaryKey
|
|
272
331
|
}
|
|
273
332
|
}
|
|
274
333
|
|
|
334
|
+
const getSchemaCache = <
|
|
335
|
+
Name extends string,
|
|
336
|
+
Fields extends TableFieldMap,
|
|
337
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
338
|
+
>(
|
|
339
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
340
|
+
): TableSchemaCache<Name, Fields, PrimaryKeyColumns> => {
|
|
341
|
+
const target = table as unknown as {
|
|
342
|
+
[SchemaCacheSymbol]?: TableSchemaCache<Name, Fields, PrimaryKeyColumns>
|
|
343
|
+
}
|
|
344
|
+
if (target[SchemaCacheSymbol] !== undefined) {
|
|
345
|
+
return target[SchemaCacheSymbol]
|
|
346
|
+
}
|
|
347
|
+
const cache: TableSchemaCache<Name, Fields, PrimaryKeyColumns> = {}
|
|
348
|
+
Object.defineProperty(table, SchemaCacheSymbol, {
|
|
349
|
+
configurable: true,
|
|
350
|
+
value: cache
|
|
351
|
+
})
|
|
352
|
+
return cache
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const deriveTableSchema = <
|
|
356
|
+
Variant extends TableSchemaVariant,
|
|
357
|
+
Name extends string,
|
|
358
|
+
Fields extends TableFieldMap,
|
|
359
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
360
|
+
>(
|
|
361
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
|
|
362
|
+
variant: Variant
|
|
363
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
|
|
364
|
+
const state = table[TypeId]
|
|
365
|
+
switch (variant) {
|
|
366
|
+
case "select":
|
|
367
|
+
return deriveSelectSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
368
|
+
case "insert":
|
|
369
|
+
return deriveInsertSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
370
|
+
case "update":
|
|
371
|
+
return deriveUpdateSchema(state.name, state.fields, state.primaryKey) as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const schemaFor = <
|
|
376
|
+
Variant extends TableSchemaVariant,
|
|
377
|
+
Name extends string,
|
|
378
|
+
Fields extends TableFieldMap,
|
|
379
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
380
|
+
>(
|
|
381
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>,
|
|
382
|
+
variant: Variant
|
|
383
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant] => {
|
|
384
|
+
const cache = getSchemaCache(table)
|
|
385
|
+
const cached = cache[variant]
|
|
386
|
+
if (cached !== undefined) {
|
|
387
|
+
return cached as TableSchemas<Name, Fields, PrimaryKeyColumns>[Variant]
|
|
388
|
+
}
|
|
389
|
+
const schema = deriveTableSchema(table, variant)
|
|
390
|
+
cache[variant] = schema as any
|
|
391
|
+
return schema
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function selectSchema<
|
|
395
|
+
Name extends string,
|
|
396
|
+
Fields extends TableFieldMap,
|
|
397
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
398
|
+
>(
|
|
399
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
400
|
+
): Schema.Decoder<SelectRow<Name, Fields>, never> {
|
|
401
|
+
return schemaFor(table, "select") as Schema.Decoder<SelectRow<Name, Fields>, never>
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export function insertSchema<
|
|
405
|
+
Name extends string,
|
|
406
|
+
Fields extends TableFieldMap,
|
|
407
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
408
|
+
>(
|
|
409
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
410
|
+
): Schema.Decoder<InsertRow<Name, Fields>, never> {
|
|
411
|
+
return schemaFor(table, "insert") as Schema.Decoder<InsertRow<Name, Fields>, never>
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function updateSchema<
|
|
415
|
+
Name extends string,
|
|
416
|
+
Fields extends TableFieldMap,
|
|
417
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
418
|
+
>(
|
|
419
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
420
|
+
): Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never> {
|
|
421
|
+
return schemaFor(table, "update") as Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const schemasFor = <
|
|
425
|
+
Name extends string,
|
|
426
|
+
Fields extends TableFieldMap,
|
|
427
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
428
|
+
>(
|
|
429
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
|
|
430
|
+
): TableSchemas<Name, Fields, PrimaryKeyColumns> => {
|
|
431
|
+
const cache = getSchemaCache(table)
|
|
432
|
+
if (cache.schemas !== undefined) {
|
|
433
|
+
return cache.schemas
|
|
434
|
+
}
|
|
435
|
+
const schemas = {} as TableSchemas<Name, Fields, PrimaryKeyColumns>
|
|
436
|
+
Object.defineProperties(schemas, {
|
|
437
|
+
select: {
|
|
438
|
+
enumerable: true,
|
|
439
|
+
get: () => selectSchema(table)
|
|
440
|
+
},
|
|
441
|
+
insert: {
|
|
442
|
+
enumerable: true,
|
|
443
|
+
get: () => insertSchema(table)
|
|
444
|
+
},
|
|
445
|
+
update: {
|
|
446
|
+
enumerable: true,
|
|
447
|
+
get: () => updateSchema(table)
|
|
448
|
+
}
|
|
449
|
+
})
|
|
450
|
+
cache.schemas = schemas
|
|
451
|
+
return schemas
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const defineSchemasGetter = <
|
|
455
|
+
Name extends string,
|
|
456
|
+
Fields extends TableFieldMap,
|
|
457
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
458
|
+
>(
|
|
459
|
+
table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any>
|
|
460
|
+
): void => {
|
|
461
|
+
Object.defineProperty(table, "schemas", {
|
|
462
|
+
configurable: true,
|
|
463
|
+
enumerable: true,
|
|
464
|
+
get() {
|
|
465
|
+
return schemasFor(table)
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
|
|
275
470
|
const makeTable = <
|
|
276
471
|
Name extends string,
|
|
277
472
|
Fields extends TableFieldMap,
|
|
@@ -295,7 +490,7 @@ const makeTable = <
|
|
|
295
490
|
const table = attachPipe(Object.create(TableProto))
|
|
296
491
|
table.name = name
|
|
297
492
|
table.columns = artifacts.columns
|
|
298
|
-
table
|
|
493
|
+
defineSchemasGetter(table)
|
|
299
494
|
table[TypeId] = {
|
|
300
495
|
name,
|
|
301
496
|
baseName,
|
|
@@ -341,7 +536,10 @@ const applyDeclaredOptions = <
|
|
|
341
536
|
return table
|
|
342
537
|
}
|
|
343
538
|
return declaredOptions.reduce<TableDefinition<any, any, any, "schema", any>>(
|
|
344
|
-
(current, option) =>
|
|
539
|
+
(current, option) =>
|
|
540
|
+
(option as unknown as (
|
|
541
|
+
table: TableDefinition<any, any, any, "schema", any>
|
|
542
|
+
) => TableDefinition<any, any, any, "schema", any>)(current),
|
|
345
543
|
table
|
|
346
544
|
) as unknown as Table
|
|
347
545
|
}
|
|
@@ -403,7 +601,6 @@ const ensureClassArtifacts = <
|
|
|
403
601
|
)
|
|
404
602
|
const artifacts = {
|
|
405
603
|
columns: table.columns,
|
|
406
|
-
schemas: table.schemas,
|
|
407
604
|
normalizedOptions: table[OptionsSymbol],
|
|
408
605
|
primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
|
|
409
606
|
} satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
|
|
@@ -491,17 +688,17 @@ export function make<
|
|
|
491
688
|
*/
|
|
492
689
|
export const schema = <SchemaName extends string>(
|
|
493
690
|
schemaName: SchemaName
|
|
494
|
-
): TableSchemaNamespace<SchemaName> =>
|
|
495
|
-
|
|
496
|
-
table: <
|
|
691
|
+
): TableSchemaNamespace<SchemaName> => {
|
|
692
|
+
const table = <
|
|
497
693
|
Name extends string,
|
|
498
694
|
Fields extends TableFieldMap,
|
|
695
|
+
const Options extends DeclaredTableOptions,
|
|
499
696
|
PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>
|
|
500
697
|
>(
|
|
501
698
|
name: Name,
|
|
502
699
|
fields: Fields,
|
|
503
|
-
...options:
|
|
504
|
-
): TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName> =>
|
|
700
|
+
...options: Options & ValidateDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
701
|
+
): ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options> =>
|
|
505
702
|
applyDeclaredOptions(
|
|
506
703
|
makeTable(
|
|
507
704
|
name,
|
|
@@ -512,9 +709,13 @@ export const schema = <SchemaName extends string>(
|
|
|
512
709
|
schemaName,
|
|
513
710
|
"explicit"
|
|
514
711
|
) as TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>,
|
|
515
|
-
options
|
|
516
|
-
)
|
|
517
|
-
|
|
712
|
+
options as unknown as Options
|
|
713
|
+
) as ApplyDeclaredOptions<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Options>
|
|
714
|
+
return {
|
|
715
|
+
schemaName,
|
|
716
|
+
table
|
|
717
|
+
} as unknown as TableSchemaNamespace<SchemaName>
|
|
718
|
+
}
|
|
518
719
|
|
|
519
720
|
/**
|
|
520
721
|
* Creates an aliased source from an existing table definition.
|
|
@@ -546,7 +747,7 @@ export const alias = <
|
|
|
546
747
|
const aliased = attachPipe(Object.create(TableProto))
|
|
547
748
|
aliased.name = aliasName
|
|
548
749
|
aliased.columns = columns
|
|
549
|
-
aliased
|
|
750
|
+
defineSchemasGetter(aliased)
|
|
550
751
|
aliased[TypeId] = {
|
|
551
752
|
name: aliasName,
|
|
552
753
|
baseName: state.baseName,
|
|
@@ -605,7 +806,7 @@ export function Class<
|
|
|
605
806
|
}
|
|
606
807
|
|
|
607
808
|
static get schemas() {
|
|
608
|
-
return
|
|
809
|
+
return schemasFor(this as any)
|
|
609
810
|
}
|
|
610
811
|
|
|
611
812
|
static get [TypeId]() {
|
|
@@ -664,7 +865,7 @@ export function Class<
|
|
|
664
865
|
export const primaryKey = <
|
|
665
866
|
const Columns extends string | readonly string[]
|
|
666
867
|
>(
|
|
667
|
-
columns: Columns
|
|
868
|
+
columns: Columns & NonEmptyColumnInput<Columns>
|
|
668
869
|
): TableOption<{
|
|
669
870
|
readonly kind: "primaryKey"
|
|
670
871
|
readonly columns: NormalizeColumns<Columns>
|
|
@@ -677,7 +878,7 @@ export const primaryKey = <
|
|
|
677
878
|
export const unique = <
|
|
678
879
|
const Columns extends string | readonly string[]
|
|
679
880
|
>(
|
|
680
|
-
columns: Columns
|
|
881
|
+
columns: Columns & NonEmptyColumnInput<Columns>
|
|
681
882
|
): TableOption<{
|
|
682
883
|
readonly kind: "unique"
|
|
683
884
|
readonly columns: NormalizeColumns<Columns>
|
|
@@ -690,7 +891,7 @@ export const unique = <
|
|
|
690
891
|
export const index = <
|
|
691
892
|
const Columns extends string | readonly string[]
|
|
692
893
|
>(
|
|
693
|
-
columns: Columns
|
|
894
|
+
columns: Columns & NonEmptyColumnInput<Columns>
|
|
694
895
|
): TableOption<{
|
|
695
896
|
readonly kind: "index"
|
|
696
897
|
readonly columns: NormalizeColumns<Columns>
|
|
@@ -705,9 +906,9 @@ export const foreignKey = <
|
|
|
705
906
|
TargetTable extends AnyTable,
|
|
706
907
|
const TargetColumns extends string | readonly string[]
|
|
707
908
|
>(
|
|
708
|
-
columns: LocalColumns
|
|
909
|
+
columns: LocalColumns & NonEmptyColumnInput<LocalColumns>,
|
|
709
910
|
target: () => TargetTable,
|
|
710
|
-
referencedColumns: TargetColumns
|
|
911
|
+
referencedColumns: TargetColumns & NonEmptyColumnInput<TargetColumns> & MatchingColumnArityInput<LocalColumns, TargetColumns>
|
|
711
912
|
): TableOption<{
|
|
712
913
|
readonly kind: "foreignKey"
|
|
713
914
|
readonly columns: NormalizeColumns<LocalColumns>
|
|
@@ -715,7 +916,7 @@ export const foreignKey = <
|
|
|
715
916
|
readonly tableName: string
|
|
716
917
|
readonly schemaName?: string
|
|
717
918
|
readonly columns: NormalizeColumns<TargetColumns>
|
|
718
|
-
readonly knownColumns: readonly
|
|
919
|
+
readonly knownColumns: readonly ColumnNamesOfAnyTable<TargetTable>[]
|
|
719
920
|
}
|
|
720
921
|
}> => makeOption({
|
|
721
922
|
kind: "foreignKey",
|
|
@@ -724,7 +925,7 @@ export const foreignKey = <
|
|
|
724
925
|
tableName: target()[TypeId].baseName,
|
|
725
926
|
schemaName: target()[TypeId].schemaName,
|
|
726
927
|
columns: normalizeColumnList(referencedColumns) as NormalizeColumns<TargetColumns>,
|
|
727
|
-
knownColumns: Object.keys(target()[TypeId].fields)
|
|
928
|
+
knownColumns: Object.keys(target()[TypeId].fields) as unknown as readonly ColumnNamesOfAnyTable<TargetTable>[]
|
|
728
929
|
})
|
|
729
930
|
})
|
|
730
931
|
|
|
@@ -742,15 +943,21 @@ export const check = <Name extends string>(
|
|
|
742
943
|
predicate
|
|
743
944
|
})
|
|
744
945
|
|
|
745
|
-
/** Extracts the row type
|
|
746
|
-
export type SelectOf<Table extends
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
>
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
946
|
+
/** Extracts the row type produced by `selectSchema(table)`. */
|
|
947
|
+
export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
948
|
+
readonly name: infer Name extends string
|
|
949
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
950
|
+
} ? SelectRow<Name, Fields> : never
|
|
951
|
+
|
|
952
|
+
/** Extracts the payload type produced by `insertSchema(table)`. */
|
|
953
|
+
export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
954
|
+
readonly name: infer Name extends string
|
|
955
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
956
|
+
} ? InsertRow<Name, Fields> : never
|
|
957
|
+
|
|
958
|
+
/** Extracts the payload type produced by `updateSchema(table)`. */
|
|
959
|
+
export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
960
|
+
readonly name: infer Name extends string
|
|
961
|
+
readonly fields: infer Fields extends TableFieldMap
|
|
962
|
+
readonly primaryKey: readonly (infer PrimaryKeyColumns)[]
|
|
963
|
+
} ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never
|
package/src/mysql/column.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Schema from "effect/Schema"
|
|
2
2
|
|
|
3
3
|
import * as BaseColumn from "../internal/column.js"
|
|
4
|
-
import { makeColumnDefinition, type ColumnDefinition } from "../internal/column-state.js"
|
|
4
|
+
import { makeColumnDefinition, type AnyColumnDefinition, type ColumnDefinition } from "../internal/column-state.js"
|
|
5
5
|
import type * as Expression from "../internal/scalar.js"
|
|
6
6
|
import {
|
|
7
7
|
DecimalStringSchema,
|
|
@@ -21,7 +21,7 @@ const enrichDbType = <Db extends Expression.DbType.Any>(dbType: Db): Db => {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const primitive = <Type, Db extends Expression.DbType.Any>(
|
|
24
|
-
schema: Schema.Schema<Type
|
|
24
|
+
schema: Schema.Schema<Type>,
|
|
25
25
|
dbType: Db
|
|
26
26
|
): ColumnDefinition<Type, Type, Type, Db, false, false, false, false, false, undefined> =>
|
|
27
27
|
makeColumnDefinition(schema as Schema.Schema<NonNullable<Type>>, {
|
|
@@ -46,11 +46,11 @@ const renderNumericDdlType = (
|
|
|
46
46
|
: `${kind}(${options.precision},${options.scale})`
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export const custom = <SchemaType extends Schema.
|
|
49
|
+
export const custom = <SchemaType extends Schema.Top, Db extends Expression.DbType.Any>(
|
|
50
50
|
schema: SchemaType,
|
|
51
51
|
dbType: Db
|
|
52
52
|
) =>
|
|
53
|
-
makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType
|
|
53
|
+
makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>>, {
|
|
54
54
|
dbType: enrichDbType(dbType),
|
|
55
55
|
nullable: false,
|
|
56
56
|
hasDefault: false,
|
|
@@ -62,7 +62,7 @@ export const custom = <SchemaType extends Schema.Schema.Any, Db extends Expressi
|
|
|
62
62
|
identity: undefined
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
-
export const uuid = () => primitive(Schema.
|
|
65
|
+
export const uuid = () => primitive(Schema.String.check(Schema.isUUID()), mysqlDatatypes.uuid())
|
|
66
66
|
export const text = () => primitive(Schema.String, mysqlDatatypes.text())
|
|
67
67
|
export const int = () => primitive(Schema.Int, mysqlDatatypes.int())
|
|
68
68
|
export const number = (options?: BaseColumn.NumericOptions) =>
|
|
@@ -81,8 +81,8 @@ export const boolean = () => primitive(Schema.Boolean, mysqlDatatypes.boolean())
|
|
|
81
81
|
export const date = () => primitive(LocalDateStringSchema, mysqlDatatypes.date())
|
|
82
82
|
export const datetime = () => primitive(LocalDateTimeStringSchema, mysqlDatatypes.datetime())
|
|
83
83
|
export const timestamp = () => primitive(LocalDateTimeStringSchema, mysqlDatatypes.timestamp())
|
|
84
|
-
export const json = <SchemaType extends Schema.
|
|
85
|
-
makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType
|
|
84
|
+
export const json = <SchemaType extends Schema.Top>(schema: SchemaType) =>
|
|
85
|
+
makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>>, {
|
|
86
86
|
dbType: { ...mysqlDatatypes.json(), variant: "json" } as Expression.DbType.Json<"mysql", "json">,
|
|
87
87
|
nullable: false,
|
|
88
88
|
hasDefault: false,
|
|
@@ -97,7 +97,23 @@ export const json = <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =
|
|
|
97
97
|
export const nullable = BaseColumn.nullable
|
|
98
98
|
export const brand = BaseColumn.brand
|
|
99
99
|
export const primaryKey = BaseColumn.primaryKey
|
|
100
|
-
|
|
100
|
+
type UniqueColumn<Column extends AnyColumnDefinition> = ReturnType<typeof BaseColumn.unique<Column>>
|
|
101
|
+
|
|
102
|
+
type MysqlUniqueOptions = {
|
|
103
|
+
readonly name?: string
|
|
104
|
+
readonly nullsNotDistinct?: never
|
|
105
|
+
readonly deferrable?: never
|
|
106
|
+
readonly initiallyDeferred?: never
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
type UniqueModifier = {
|
|
110
|
+
<Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
|
|
111
|
+
readonly options: <const Options extends MysqlUniqueOptions>(
|
|
112
|
+
options: Options
|
|
113
|
+
) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const unique = BaseColumn.unique as UniqueModifier
|
|
101
117
|
const default_ = BaseColumn.default_
|
|
102
118
|
export const generated = BaseColumn.generated
|
|
103
119
|
export const driverValueMapping = BaseColumn.driverValueMapping
|
|
@@ -50,12 +50,33 @@ type MysqlUuidWitness = Expression.DbType.Base<"mysql", "uuid"> & {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
type MysqlJsonWitness = Expression.DbType.Base<"mysql", "json"> & {
|
|
54
|
+
readonly family: "json"
|
|
55
|
+
readonly runtime: "json"
|
|
56
|
+
readonly compareGroup: "json"
|
|
57
|
+
readonly castTargets: readonly ["json", "text"]
|
|
58
|
+
readonly driverValueMapping: {
|
|
59
|
+
readonly toDriver: (value: unknown) => unknown
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
mysqlDatatypeModule.json = () => ({
|
|
64
|
+
...withMetadata("json"),
|
|
65
|
+
driverValueMapping: {
|
|
66
|
+
toDriver: (value: unknown) =>
|
|
67
|
+
value !== null && typeof value === "object"
|
|
68
|
+
? JSON.stringify(value)
|
|
69
|
+
: value
|
|
70
|
+
}
|
|
71
|
+
}) as MysqlJsonWitness
|
|
72
|
+
|
|
53
73
|
export const mysqlDatatypes = mysqlDatatypeModule as DatatypeModule<
|
|
54
74
|
"mysql",
|
|
55
75
|
typeof mysqlDatatypeKinds,
|
|
56
76
|
typeof mysqlDatatypeFamilies
|
|
57
77
|
> & {
|
|
58
78
|
readonly uuid: () => MysqlUuidWitness
|
|
79
|
+
readonly json: () => MysqlJsonWitness
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
export type MysqlDatatypeModule = typeof mysqlDatatypes
|
|
@@ -51636,17 +51636,17 @@ export const mysqlErrorCatalogByNumber = {
|
|
|
51636
51636
|
"MY-015153": [mysqlErrorCatalogBySymbol["ER_WARN_AUDIT_LOG_FILTER_RECOVERY_LOGGING_DISABLED_LOG"]!],
|
|
51637
51637
|
} as const
|
|
51638
51638
|
|
|
51639
|
-
const mysqlSymbolPattern = /^(?:[A-Z][A-Z0-9_]*|MY-\d+)$/
|
|
51640
|
-
const mysqlNumberPattern = /^(?:\d+|MY-\d+)$/
|
|
51641
|
-
|
|
51642
51639
|
export type MysqlErrorSymbol = keyof typeof mysqlErrorCatalogBySymbol
|
|
51643
51640
|
export type MysqlErrorDescriptor<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = (typeof mysqlErrorCatalogBySymbol)[Symbol]
|
|
51644
51641
|
export type MysqlErrorNumber = keyof typeof mysqlErrorCatalogByNumber
|
|
51645
51642
|
export type MysqlErrorTag<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = MysqlErrorDescriptor<Symbol>["tag"]
|
|
51646
51643
|
export type MysqlErrorDescriptorsByNumber<Number extends MysqlErrorNumber = MysqlErrorNumber> = (typeof mysqlErrorCatalogByNumber)[Number]
|
|
51647
51644
|
|
|
51648
|
-
export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol =>
|
|
51649
|
-
|
|
51645
|
+
export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol =>
|
|
51646
|
+
value in mysqlErrorCatalogBySymbol
|
|
51647
|
+
|
|
51648
|
+
export const isMysqlErrorNumber = (value: string): value is MysqlErrorNumber =>
|
|
51649
|
+
value in mysqlErrorCatalogByNumber
|
|
51650
51650
|
|
|
51651
51651
|
export const getMysqlErrorDescriptor = <Symbol extends MysqlErrorSymbol>(symbol: Symbol): MysqlErrorDescriptor<Symbol> =>
|
|
51652
51652
|
mysqlErrorCatalogBySymbol[symbol]
|
|
@@ -48,8 +48,8 @@ const asNumber = (value: unknown): number | undefined => {
|
|
|
48
48
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
49
49
|
return value
|
|
50
50
|
}
|
|
51
|
-
if (typeof value === "string" && value.trim()
|
|
52
|
-
const parsed = Number(value)
|
|
51
|
+
if (typeof value === "string" && /^[+-]?\d+$/.test(value.trim())) {
|
|
52
|
+
const parsed = Number(value.trim())
|
|
53
53
|
return Number.isFinite(parsed) ? parsed : undefined
|
|
54
54
|
}
|
|
55
55
|
return undefined
|