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
|
@@ -1,64 +1,7 @@
|
|
|
1
|
-
import * as VariantSchema from "@effect/experimental/VariantSchema";
|
|
2
1
|
import type * as Brand from "effect/Brand";
|
|
3
2
|
import * as Schema from "effect/Schema";
|
|
4
3
|
import { type AnyColumnDefinition, type HasDefault, type InsertType, type IsGenerated, type IsNullable, type SelectType, type UpdateType } from "./column-state.js";
|
|
5
|
-
|
|
6
|
-
export declare const TableSchema: {
|
|
7
|
-
readonly Struct: <const A extends VariantSchema.Struct.Fields>(fields: A & VariantSchema.Struct.Validate<A, "insert" | "select" | "update">) => VariantSchema.Struct<A>;
|
|
8
|
-
readonly Field: <const A extends VariantSchema.Field.ConfigWithKeys<"insert" | "select" | "update">>(config: A & { readonly [K in Exclude<keyof A, "insert" | "select" | "update">]: never; }) => VariantSchema.Field<A>;
|
|
9
|
-
readonly FieldOnly: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Keys[number]]: S; }>;
|
|
10
|
-
readonly FieldExcept: <const Keys extends readonly ("insert" | "select" | "update")[]>(...keys: Keys) => <S extends Schema.Schema.All | Schema.PropertySignature.All<PropertyKey>>(schema: S) => VariantSchema.Field<{ readonly [K in Exclude<"insert", Keys[number]> | Exclude<"select", Keys[number]> | Exclude<"update", Keys[number]>]: S; }>;
|
|
11
|
-
readonly fieldEvolve: {
|
|
12
|
-
<Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
|
|
13
|
-
readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
14
|
-
readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
15
|
-
readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
16
|
-
}>(f: Mapping): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping ? Mapping[K] extends (arg: any) => any ? ReturnType<Mapping[K]> : S_1[K] : S_1[K]; } : {
|
|
17
|
-
readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping ? Mapping[T] extends (arg: any) => any ? ReturnType<Mapping[T]> : Self : Self : never : never;
|
|
18
|
-
readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping ? Mapping[T_1] extends (arg: any) => any ? ReturnType<Mapping[T_1]> : Self : Self : never : never;
|
|
19
|
-
readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping ? Mapping[T_2] extends (arg: any) => any ? ReturnType<Mapping[T_2]> : Self : Self : never : never;
|
|
20
|
-
}>;
|
|
21
|
-
<Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_1 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: ((variant: S[K]) => VariantSchema.Field.ValueAny) | undefined; } : {
|
|
22
|
-
readonly insert?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
23
|
-
readonly select?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
24
|
-
readonly update?: ((variant: Self) => VariantSchema.Field.ValueAny) | undefined;
|
|
25
|
-
}>(self: Self, f: Mapping_1): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_1 ? Mapping_1[K] extends (arg: any) => any ? ReturnType<Mapping_1[K]> : S_1[K] : S_1[K]; } : {
|
|
26
|
-
readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_1 ? Mapping_1[T] extends (arg: any) => any ? ReturnType<Mapping_1[T]> : Self : Self : never : never;
|
|
27
|
-
readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_1 ? Mapping_1[T_1] extends (arg: any) => any ? ReturnType<Mapping_1[T_1]> : Self : Self : never : never;
|
|
28
|
-
readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_1 ? Mapping_1[T_2] extends (arg: any) => any ? ReturnType<Mapping_1[T_2]> : Self : Self : never : never;
|
|
29
|
-
}>;
|
|
30
|
-
};
|
|
31
|
-
readonly fieldFromKey: {
|
|
32
|
-
<Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_2 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
|
|
33
|
-
readonly insert?: string | undefined;
|
|
34
|
-
readonly select?: string | undefined;
|
|
35
|
-
readonly update?: string | undefined;
|
|
36
|
-
}>(mapping: Mapping_2): (self: Self) => VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_2 ? Mapping_2[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_2[K]> : S_1[K] : S_1[K]; } : {
|
|
37
|
-
readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_2 ? Mapping_2[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T]> : Self : Self : never : never;
|
|
38
|
-
readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_2 ? Mapping_2[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_1]> : Self : Self : never : never;
|
|
39
|
-
readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_2 ? Mapping_2[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_2[T_2]> : Self : Self : never : never;
|
|
40
|
-
}>;
|
|
41
|
-
<Self extends VariantSchema.Field<any> | VariantSchema.Field.ValueAny, const Mapping_3 extends Self extends VariantSchema.Field<infer S extends VariantSchema.Field.Config> ? { readonly [K in keyof S]?: string | undefined; } : {
|
|
42
|
-
readonly insert?: string | undefined;
|
|
43
|
-
readonly select?: string | undefined;
|
|
44
|
-
readonly update?: string | undefined;
|
|
45
|
-
}>(self: Self, mapping: Mapping_3): VariantSchema.Field<Self extends VariantSchema.Field<infer S_1 extends VariantSchema.Field.Config> ? { readonly [K in keyof S_1]: K extends keyof Mapping_3 ? Mapping_3[K] extends string ? VariantSchema.fromKey.Rename<S_1[K], Mapping_3[K]> : S_1[K] : S_1[K]; } : {
|
|
46
|
-
readonly insert: "insert" extends infer T ? T extends "insert" ? T extends keyof Mapping_3 ? Mapping_3[T] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T]> : Self : Self : never : never;
|
|
47
|
-
readonly select: "select" extends infer T_1 ? T_1 extends "select" ? T_1 extends keyof Mapping_3 ? Mapping_3[T_1] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_1]> : Self : Self : never : never;
|
|
48
|
-
readonly update: "update" extends infer T_2 ? T_2 extends "update" ? T_2 extends keyof Mapping_3 ? Mapping_3[T_2] extends string ? VariantSchema.fromKey.Rename<Self, Mapping_3[T_2]> : Self : Self : never : never;
|
|
49
|
-
}>;
|
|
50
|
-
};
|
|
51
|
-
readonly Class: <Self = never>(identifier: string) => <const Fields extends VariantSchema.Struct.Fields>(fields: Fields & VariantSchema.Struct.Validate<Fields, "insert" | "select" | "update">, annotations?: Schema.Annotations.Schema<Self, readonly []> | undefined) => [Self] extends [never] ? "Missing `Self` generic - use `class Self extends Class<Self>()({ ... })`" : VariantSchema.Class<Self, Fields, VariantSchema.ExtractFields<"select", Fields, true>, Schema.Struct.Type<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Struct.Encoded<VariantSchema.ExtractFields<"select", Fields, true>>, Schema.Schema.Context<VariantSchema.ExtractFields<"select", Fields, true>[keyof VariantSchema.ExtractFields<"select", Fields, true>]>, Schema.Struct.Constructor<VariantSchema.ExtractFields<"select", Fields, true>>> & {
|
|
52
|
-
readonly insert: Schema.Struct<VariantSchema.ExtractFields<"insert", Fields, false> extends infer T ? { [K in keyof T]: T[K]; } : never>;
|
|
53
|
-
readonly select: Schema.Struct<VariantSchema.ExtractFields<"select", Fields, false> extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never>;
|
|
54
|
-
readonly update: Schema.Struct<VariantSchema.ExtractFields<"update", Fields, false> extends infer T_2 ? { [K in keyof T_2]: T_2[K]; } : never>;
|
|
55
|
-
};
|
|
56
|
-
readonly Union: <const Members extends readonly VariantSchema.Struct<any>[]>(...members: Members) => VariantSchema.Union<Members> & VariantSchema.Union.Variants<Members, "insert" | "select" | "update">;
|
|
57
|
-
readonly extract: {
|
|
58
|
-
<V extends "insert" | "select" | "update">(variant: V): <A extends VariantSchema.Struct<any>>(self: A) => VariantSchema.Extract<V, A, V extends "select" ? true : false>;
|
|
59
|
-
<V extends "insert" | "select" | "update", A extends VariantSchema.Struct<any>>(self: A, variant: V): VariantSchema.Extract<V, A, V extends "select" ? true : false>;
|
|
60
|
-
};
|
|
61
|
-
};
|
|
4
|
+
export type TableSchemaVariant = "select" | "insert" | "update";
|
|
62
5
|
/** Normalized field map used by table definitions. */
|
|
63
6
|
export type TableFieldMap = Record<string, AnyColumnDefinition>;
|
|
64
7
|
type GeneratedKeys<Fields extends TableFieldMap> = {
|
|
@@ -91,15 +34,23 @@ export type InsertRow<TableName extends string, Fields extends TableFieldMap> =
|
|
|
91
34
|
export type UpdateRow<TableName extends string, Fields extends TableFieldMap, PrimaryKey extends keyof Fields> = Simplify<Partial<{
|
|
92
35
|
[K in UpdateKeys<Fields, PrimaryKey>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>;
|
|
93
36
|
}>>;
|
|
37
|
+
type SchemaOfVariant<Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> = Variant extends "select" ? Schema.Decoder<SelectRow<TableName, Fields>, never> : Variant extends "insert" ? Schema.Decoder<InsertRow<TableName, Fields>, never> : Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
|
|
38
|
+
export declare const deriveSchema: <Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(variant: Variant, tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns>;
|
|
39
|
+
export declare const deriveSelectSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<SelectRow<TableName, Fields>, never>;
|
|
40
|
+
export declare const deriveInsertSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<InsertRow<TableName, Fields>, never>;
|
|
41
|
+
export declare const deriveUpdateSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
|
|
94
42
|
/**
|
|
95
43
|
* Derives the `select`, `insert`, and `update` schemas for a table.
|
|
96
44
|
*
|
|
97
45
|
* This is the central place where the column capability flags are turned into
|
|
98
46
|
* real runtime schemas.
|
|
47
|
+
*
|
|
48
|
+
* @deprecated Prefer `deriveSelectSchema`, `deriveInsertSchema`, and
|
|
49
|
+
* `deriveUpdateSchema` so individual variants are derived lazily.
|
|
99
50
|
*/
|
|
100
51
|
export declare const deriveSchemas: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => {
|
|
101
|
-
readonly select: Schema.
|
|
102
|
-
readonly insert: Schema.
|
|
103
|
-
readonly update: Schema.
|
|
52
|
+
readonly select: Schema.Decoder<SelectRow<TableName, Fields>, never>;
|
|
53
|
+
readonly insert: Schema.Decoder<InsertRow<TableName, Fields>, never>;
|
|
54
|
+
readonly update: Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
|
|
104
55
|
};
|
|
105
56
|
export {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as VariantSchema from "@effect/experimental/VariantSchema"
|
|
2
1
|
import type * as Brand from "effect/Brand"
|
|
3
2
|
import * as Schema from "effect/Schema"
|
|
4
3
|
|
|
@@ -12,13 +11,7 @@ import {
|
|
|
12
11
|
type UpdateType
|
|
13
12
|
} from "./column-state.js"
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
export const TableSchema = VariantSchema.make({
|
|
17
|
-
variants: ["select", "insert", "update"] as const,
|
|
18
|
-
defaultVariant: "select"
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
type Variants = "select" | "insert" | "update"
|
|
14
|
+
export type TableSchemaVariant = "select" | "insert" | "update"
|
|
22
15
|
|
|
23
16
|
/** Normalized field map used by table definitions. */
|
|
24
17
|
export type TableFieldMap = Record<string, AnyColumnDefinition>
|
|
@@ -112,7 +105,7 @@ const maybeBrandSchema = (
|
|
|
112
105
|
column: AnyColumnDefinition,
|
|
113
106
|
tableName: string,
|
|
114
107
|
columnName: string
|
|
115
|
-
): Schema.
|
|
108
|
+
): Schema.Top =>
|
|
116
109
|
column.metadata.brand === true
|
|
117
110
|
? Schema.brand(`${tableName}.${columnName}`)(column.schema)
|
|
118
111
|
: column.schema
|
|
@@ -121,7 +114,7 @@ const selectSchema = (
|
|
|
121
114
|
column: AnyColumnDefinition,
|
|
122
115
|
tableName: string,
|
|
123
116
|
columnName: string
|
|
124
|
-
): Schema.
|
|
117
|
+
): Schema.Top =>
|
|
125
118
|
column.metadata.nullable ? Schema.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName)
|
|
126
119
|
|
|
127
120
|
const insertSchema = (
|
|
@@ -153,11 +146,95 @@ const updateSchema = (
|
|
|
153
146
|
return Schema.optional(base)
|
|
154
147
|
}
|
|
155
148
|
|
|
149
|
+
type SchemaOfVariant<
|
|
150
|
+
Variant extends TableSchemaVariant,
|
|
151
|
+
TableName extends string,
|
|
152
|
+
Fields extends TableFieldMap,
|
|
153
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
154
|
+
> = Variant extends "select" ? Schema.Decoder<SelectRow<TableName, Fields>, never>
|
|
155
|
+
: Variant extends "insert" ? Schema.Decoder<InsertRow<TableName, Fields>, never>
|
|
156
|
+
: Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
|
|
157
|
+
|
|
158
|
+
const fieldSchemaForVariant = (
|
|
159
|
+
variant: TableSchemaVariant,
|
|
160
|
+
column: AnyColumnDefinition,
|
|
161
|
+
tableName: string,
|
|
162
|
+
columnName: string,
|
|
163
|
+
primaryKeySet: ReadonlySet<string>
|
|
164
|
+
): any | undefined => {
|
|
165
|
+
switch (variant) {
|
|
166
|
+
case "select":
|
|
167
|
+
return selectSchema(column, tableName, columnName)
|
|
168
|
+
case "insert":
|
|
169
|
+
return insertSchema(column, tableName, columnName)
|
|
170
|
+
case "update":
|
|
171
|
+
return updateSchema(column, tableName, columnName, primaryKeySet.has(columnName))
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const deriveSchema = <
|
|
176
|
+
Variant extends TableSchemaVariant,
|
|
177
|
+
TableName extends string,
|
|
178
|
+
Fields extends TableFieldMap,
|
|
179
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
180
|
+
>(
|
|
181
|
+
variant: Variant,
|
|
182
|
+
tableName: TableName,
|
|
183
|
+
fields: Fields,
|
|
184
|
+
primaryKeyColumns: readonly PrimaryKeyColumns[]
|
|
185
|
+
): SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns> => {
|
|
186
|
+
const primaryKeySet = new Set<string>(primaryKeyColumns)
|
|
187
|
+
const structFields: Record<string, any> = {}
|
|
188
|
+
for (const [key, column] of Object.entries(fields)) {
|
|
189
|
+
const schema = fieldSchemaForVariant(variant, column, tableName, key, primaryKeySet)
|
|
190
|
+
if (schema !== undefined) {
|
|
191
|
+
structFields[key] = schema
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return Schema.Struct(structFields) as unknown as SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns>
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export const deriveSelectSchema = <
|
|
198
|
+
TableName extends string,
|
|
199
|
+
Fields extends TableFieldMap,
|
|
200
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
201
|
+
>(
|
|
202
|
+
tableName: TableName,
|
|
203
|
+
fields: Fields,
|
|
204
|
+
primaryKeyColumns: readonly PrimaryKeyColumns[]
|
|
205
|
+
): Schema.Decoder<SelectRow<TableName, Fields>, never> =>
|
|
206
|
+
deriveSchema("select", tableName, fields, primaryKeyColumns)
|
|
207
|
+
|
|
208
|
+
export const deriveInsertSchema = <
|
|
209
|
+
TableName extends string,
|
|
210
|
+
Fields extends TableFieldMap,
|
|
211
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
212
|
+
>(
|
|
213
|
+
tableName: TableName,
|
|
214
|
+
fields: Fields,
|
|
215
|
+
primaryKeyColumns: readonly PrimaryKeyColumns[]
|
|
216
|
+
): Schema.Decoder<InsertRow<TableName, Fields>, never> =>
|
|
217
|
+
deriveSchema("insert", tableName, fields, primaryKeyColumns)
|
|
218
|
+
|
|
219
|
+
export const deriveUpdateSchema = <
|
|
220
|
+
TableName extends string,
|
|
221
|
+
Fields extends TableFieldMap,
|
|
222
|
+
PrimaryKeyColumns extends keyof Fields & string
|
|
223
|
+
>(
|
|
224
|
+
tableName: TableName,
|
|
225
|
+
fields: Fields,
|
|
226
|
+
primaryKeyColumns: readonly PrimaryKeyColumns[]
|
|
227
|
+
): Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never> =>
|
|
228
|
+
deriveSchema("update", tableName, fields, primaryKeyColumns)
|
|
229
|
+
|
|
156
230
|
/**
|
|
157
231
|
* Derives the `select`, `insert`, and `update` schemas for a table.
|
|
158
232
|
*
|
|
159
233
|
* This is the central place where the column capability flags are turned into
|
|
160
234
|
* real runtime schemas.
|
|
235
|
+
*
|
|
236
|
+
* @deprecated Prefer `deriveSelectSchema`, `deriveInsertSchema`, and
|
|
237
|
+
* `deriveUpdateSchema` so individual variants are derived lazily.
|
|
161
238
|
*/
|
|
162
239
|
export const deriveSchemas = <
|
|
163
240
|
TableName extends string,
|
|
@@ -168,36 +245,11 @@ export const deriveSchemas = <
|
|
|
168
245
|
fields: Fields,
|
|
169
246
|
primaryKeyColumns: readonly PrimaryKeyColumns[]
|
|
170
247
|
): {
|
|
171
|
-
readonly select: Schema.
|
|
172
|
-
readonly insert: Schema.
|
|
173
|
-
readonly update: Schema.
|
|
174
|
-
} => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
select: selectSchema(column, tableName, key),
|
|
180
|
-
insert: undefined,
|
|
181
|
-
update: undefined
|
|
182
|
-
}
|
|
183
|
-
const insert = insertSchema(column, tableName, key)
|
|
184
|
-
const update = updateSchema(column, tableName, key, primaryKeySet.has(key))
|
|
185
|
-
if (insert !== undefined) {
|
|
186
|
-
config.insert = insert
|
|
187
|
-
} else {
|
|
188
|
-
delete config.insert
|
|
189
|
-
}
|
|
190
|
-
if (update !== undefined) {
|
|
191
|
-
config.update = update
|
|
192
|
-
} else {
|
|
193
|
-
delete config.update
|
|
194
|
-
}
|
|
195
|
-
variants[key] = TableSchema.Field(config)
|
|
196
|
-
}
|
|
197
|
-
const struct = TableSchema.Struct(variants as any)
|
|
198
|
-
return {
|
|
199
|
-
select: TableSchema.extract(struct, "select") as unknown as Schema.Schema<SelectRow<TableName, Fields>>,
|
|
200
|
-
insert: TableSchema.extract(struct, "insert") as unknown as Schema.Schema<InsertRow<TableName, Fields>>,
|
|
201
|
-
update: TableSchema.extract(struct, "update") as unknown as Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>
|
|
202
|
-
}
|
|
203
|
-
}
|
|
248
|
+
readonly select: Schema.Decoder<SelectRow<TableName, Fields>, never>
|
|
249
|
+
readonly insert: Schema.Decoder<InsertRow<TableName, Fields>, never>
|
|
250
|
+
readonly update: Schema.Decoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
|
|
251
|
+
} => ({
|
|
252
|
+
select: deriveSelectSchema(tableName, fields, primaryKeyColumns),
|
|
253
|
+
insert: deriveInsertSchema(tableName, fields, primaryKeyColumns),
|
|
254
|
+
update: deriveUpdateSchema(tableName, fields, primaryKeyColumns)
|
|
255
|
+
})
|
|
@@ -15,6 +15,30 @@ export type DdlExpressionLike = AnyExpression | AnySchemaExpression
|
|
|
15
15
|
|
|
16
16
|
export type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
|
|
17
17
|
|
|
18
|
+
const referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault"
|
|
19
|
+
|
|
20
|
+
export const renderReferentialAction = (action: unknown): string => {
|
|
21
|
+
switch (action) {
|
|
22
|
+
case "noAction":
|
|
23
|
+
return "no action"
|
|
24
|
+
case "restrict":
|
|
25
|
+
return "restrict"
|
|
26
|
+
case "cascade":
|
|
27
|
+
return "cascade"
|
|
28
|
+
case "setNull":
|
|
29
|
+
return "set null"
|
|
30
|
+
case "setDefault":
|
|
31
|
+
return "set default"
|
|
32
|
+
}
|
|
33
|
+
throw new Error(referentialActionError)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const validateReferentialAction = (action: unknown): void => {
|
|
37
|
+
if (action !== undefined) {
|
|
38
|
+
renderReferentialAction(action)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
18
42
|
export type IndexKeySpec =
|
|
19
43
|
| {
|
|
20
44
|
readonly kind: "column"
|
|
@@ -107,6 +131,18 @@ type TupleFromColumns<Columns> = Columns extends readonly [infer Head extends st
|
|
|
107
131
|
? readonly [Columns]
|
|
108
132
|
: never
|
|
109
133
|
|
|
134
|
+
export type NonEmptyColumnInput<Columns extends string | readonly string[]> =
|
|
135
|
+
TupleFromColumns<Columns> extends never ? never : Columns
|
|
136
|
+
|
|
137
|
+
export type MatchingColumnArityInput<
|
|
138
|
+
Left extends string | readonly string[],
|
|
139
|
+
Right extends string | readonly string[]
|
|
140
|
+
> = TupleFromColumns<Left>["length"] extends TupleFromColumns<Right>["length"]
|
|
141
|
+
? TupleFromColumns<Right>["length"] extends TupleFromColumns<Left>["length"]
|
|
142
|
+
? unknown
|
|
143
|
+
: never
|
|
144
|
+
: never
|
|
145
|
+
|
|
110
146
|
type AssertKnownColumns<Fields extends TableFieldMap, Columns extends readonly string[]> = Exclude<
|
|
111
147
|
Columns[number],
|
|
112
148
|
ColumnNameUnion<Fields>
|
|
@@ -114,6 +150,47 @@ type AssertKnownColumns<Fields extends TableFieldMap, Columns extends readonly s
|
|
|
114
150
|
? Columns
|
|
115
151
|
: never
|
|
116
152
|
|
|
153
|
+
type IndexKeyColumnNames<Keys> = Keys extends readonly (infer Key)[]
|
|
154
|
+
? Key extends { readonly kind: "column"; readonly column: infer Column extends string }
|
|
155
|
+
? Column
|
|
156
|
+
: never
|
|
157
|
+
: never
|
|
158
|
+
|
|
159
|
+
type IndexOptionColumnNames<Spec> =
|
|
160
|
+
| (Spec extends { readonly columns: infer Columns extends readonly string[] } ? Columns[number] : never)
|
|
161
|
+
| (Spec extends { readonly include: infer Include extends readonly string[] } ? Include[number] : never)
|
|
162
|
+
| (Spec extends { readonly keys: infer Keys } ? IndexKeyColumnNames<Keys> : never)
|
|
163
|
+
|
|
164
|
+
type ForeignKeyReferencedColumnNames<Spec> = Spec extends { readonly references: () => infer Reference }
|
|
165
|
+
? Reference extends { readonly columns: infer Columns extends readonly string[] }
|
|
166
|
+
? Columns[number]
|
|
167
|
+
: never
|
|
168
|
+
: never
|
|
169
|
+
|
|
170
|
+
type ForeignKeyKnownReferencedColumnNames<Spec> = Spec extends { readonly references: () => infer Reference }
|
|
171
|
+
? Reference extends { readonly knownColumns: infer KnownColumns extends readonly string[] }
|
|
172
|
+
? KnownColumns[number]
|
|
173
|
+
: string
|
|
174
|
+
: string
|
|
175
|
+
|
|
176
|
+
type AssertKnownColumnNames<Fields extends TableFieldMap, Columns extends string> = [Columns] extends [never]
|
|
177
|
+
? true
|
|
178
|
+
: string extends Columns
|
|
179
|
+
? true
|
|
180
|
+
: Exclude<Columns, ColumnNameUnion<Fields>> extends never
|
|
181
|
+
? true
|
|
182
|
+
: false
|
|
183
|
+
|
|
184
|
+
type AssertKnownReferenceColumnNames<KnownColumns extends string, Columns extends string> = [Columns] extends [never]
|
|
185
|
+
? true
|
|
186
|
+
: string extends Columns
|
|
187
|
+
? true
|
|
188
|
+
: string extends KnownColumns
|
|
189
|
+
? true
|
|
190
|
+
: Exclude<Columns, KnownColumns> extends never
|
|
191
|
+
? true
|
|
192
|
+
: false
|
|
193
|
+
|
|
117
194
|
type AssertPrimaryKeyColumns<
|
|
118
195
|
Fields extends TableFieldMap,
|
|
119
196
|
Columns extends readonly string[]
|
|
@@ -159,6 +236,8 @@ export const collectInlineOptions = <Fields extends TableFieldMap>(
|
|
|
159
236
|
})
|
|
160
237
|
}
|
|
161
238
|
if (column.metadata.references) {
|
|
239
|
+
validateReferentialAction(column.metadata.references.onUpdate)
|
|
240
|
+
validateReferentialAction(column.metadata.references.onDelete)
|
|
162
241
|
const local = [columnName] as ColumnList
|
|
163
242
|
options.push({
|
|
164
243
|
kind: "foreignKey",
|
|
@@ -254,6 +333,8 @@ export const validateOptions = <Fields extends TableFieldMap>(
|
|
|
254
333
|
}
|
|
255
334
|
}
|
|
256
335
|
if (option.kind === "foreignKey") {
|
|
336
|
+
validateReferentialAction(option.onUpdate)
|
|
337
|
+
validateReferentialAction(option.onDelete)
|
|
257
338
|
const reference = option.references()
|
|
258
339
|
if (reference.columns.length !== columns.length) {
|
|
259
340
|
throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`)
|
|
@@ -278,7 +359,7 @@ export const validateOptions = <Fields extends TableFieldMap>(
|
|
|
278
359
|
throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`)
|
|
279
360
|
}
|
|
280
361
|
}
|
|
281
|
-
if (
|
|
362
|
+
if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
|
|
282
363
|
throw new Error(`Index on table '${tableName}' requires at least one column or key`)
|
|
283
364
|
}
|
|
284
365
|
}
|
|
@@ -308,5 +389,31 @@ export type ValidatePrimaryKeyColumns<
|
|
|
308
389
|
Columns extends readonly string[]
|
|
309
390
|
> = AssertPrimaryKeyColumns<Fields, AssertKnownColumns<Fields, Columns>>
|
|
310
391
|
|
|
392
|
+
/** Compile-time validation that index columns, included columns, and column keys exist on the table. */
|
|
393
|
+
export type ValidateIndexOptionColumns<
|
|
394
|
+
Fields extends TableFieldMap,
|
|
395
|
+
Spec
|
|
396
|
+
> = AssertKnownColumnNames<Fields, IndexOptionColumnNames<Spec>> extends true ? Spec : never
|
|
397
|
+
|
|
398
|
+
/** Compile-time validation that foreign keys reference known local and target columns. */
|
|
399
|
+
export type ValidateForeignKeyOptionColumns<
|
|
400
|
+
Fields extends TableFieldMap,
|
|
401
|
+
Spec
|
|
402
|
+
> = Spec extends { readonly columns: infer Columns extends readonly string[] }
|
|
403
|
+
? AssertKnownColumns<Fields, Columns> extends never
|
|
404
|
+
? never
|
|
405
|
+
: AssertKnownReferenceColumnNames<
|
|
406
|
+
ForeignKeyKnownReferencedColumnNames<Spec>,
|
|
407
|
+
ForeignKeyReferencedColumnNames<Spec>
|
|
408
|
+
> extends true
|
|
409
|
+
? Spec
|
|
410
|
+
: never
|
|
411
|
+
: AssertKnownReferenceColumnNames<
|
|
412
|
+
ForeignKeyKnownReferencedColumnNames<Spec>,
|
|
413
|
+
ForeignKeyReferencedColumnNames<Spec>
|
|
414
|
+
> extends true
|
|
415
|
+
? Spec
|
|
416
|
+
: never
|
|
417
|
+
|
|
311
418
|
/** Normalizes a public column input into the internal tuple form. */
|
|
312
419
|
export type NormalizeColumns<Columns extends string | readonly string[]> = TupleFromColumns<Columns>
|
package/src/internal/table.d.ts
CHANGED
|
@@ -47,9 +47,9 @@ export type BoundColumns<Name extends string, Fields extends TableFieldMap> = {
|
|
|
47
47
|
};
|
|
48
48
|
/** Derived runtime schemas exposed by a table definition. */
|
|
49
49
|
export interface TableSchemas<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> {
|
|
50
|
-
readonly select: Schema.
|
|
51
|
-
readonly insert: Schema.
|
|
52
|
-
readonly update: Schema.
|
|
50
|
+
readonly select: Schema.Decoder<SelectRow<Name, Fields>, never>;
|
|
51
|
+
readonly insert: Schema.Decoder<InsertRow<Name, Fields>, never>;
|
|
52
|
+
readonly update: Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>;
|
|
53
53
|
}
|
|
54
54
|
interface TableState<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string, Kind extends TableKind = "schema", SchemaName extends string | undefined = DefaultSchemaName> {
|
|
55
55
|
readonly name: Name;
|
|
@@ -92,7 +92,10 @@ export type TableClassStatic<Name extends string, Fields extends TableFieldMap,
|
|
|
92
92
|
readonly tableName: Name;
|
|
93
93
|
} & BoundColumns<Name, Fields> & Plan.RowSet<BoundColumns<Name, Fields>, never, Record<Name, Plan.Source<Name, "required", TrueFormula>>, TableDialect<Fields>>;
|
|
94
94
|
/** Minimal structural table-like contract used across helper APIs. */
|
|
95
|
-
export type AnyTable
|
|
95
|
+
export type AnyTable<Dialect extends string = string> = {
|
|
96
|
+
readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>;
|
|
97
|
+
readonly [OptionsSymbol]: readonly TableOptionSpec[];
|
|
98
|
+
} & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>;
|
|
96
99
|
/** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
|
|
97
100
|
export type TableOption<Spec extends TableOptionSpec = TableOptionSpec> = {
|
|
98
101
|
<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: OptionInputTable<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>): ApplyOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", any>, Spec>;
|
|
@@ -114,6 +117,12 @@ export declare const schema: <SchemaName extends string>(schemaName: SchemaName)
|
|
|
114
117
|
* downstream SQL rendering work.
|
|
115
118
|
*/
|
|
116
119
|
export declare const alias: <Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string, SchemaName extends string, AliasName extends string>(table: TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName> | TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName>, aliasName: AliasName) => TableDefinition<AliasName, Fields, PrimaryKeyColumns, "alias", SchemaName>;
|
|
120
|
+
/** Returns the lazily derived select schema for a table. */
|
|
121
|
+
export declare function selectSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<SelectRow<Name, Fields>, never>;
|
|
122
|
+
/** Returns the lazily derived insert schema for a table. */
|
|
123
|
+
export declare function insertSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<InsertRow<Name, Fields>, never>;
|
|
124
|
+
/** Returns the lazily derived update schema for a table. */
|
|
125
|
+
export declare function updateSchema<Name extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>): Schema.Decoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>;
|
|
117
126
|
/**
|
|
118
127
|
* Class-based table constructor mirroring `Schema.Class`.
|
|
119
128
|
*
|
|
@@ -153,21 +162,19 @@ export declare const check: <Name extends string>(name: Name, predicate: DdlExpr
|
|
|
153
162
|
readonly name: Name;
|
|
154
163
|
readonly predicate: DdlExpressionLike;
|
|
155
164
|
}>;
|
|
156
|
-
/** Extracts the row type
|
|
157
|
-
export type SelectOf<Table extends {
|
|
158
|
-
readonly
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
readonly
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
readonly
|
|
171
|
-
|
|
172
|
-
};
|
|
173
|
-
}> = Schema.Schema.Type<Table["schemas"]["update"]>;
|
|
165
|
+
/** Extracts the row type produced by `selectSchema(table)`. */
|
|
166
|
+
export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
167
|
+
readonly name: infer Name extends string;
|
|
168
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
169
|
+
} ? SelectRow<Name, Fields> : never;
|
|
170
|
+
/** Extracts the payload type produced by `insertSchema(table)`. */
|
|
171
|
+
export type InsertOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
172
|
+
readonly name: infer Name extends string;
|
|
173
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
174
|
+
} ? InsertRow<Name, Fields> : never;
|
|
175
|
+
/** Extracts the payload type produced by `updateSchema(table)`. */
|
|
176
|
+
export type UpdateOf<Table extends AnyTable> = Table[typeof TypeId] extends {
|
|
177
|
+
readonly name: infer Name extends string;
|
|
178
|
+
readonly fields: infer Fields extends TableFieldMap;
|
|
179
|
+
readonly primaryKey: readonly (infer PrimaryKeyColumns)[];
|
|
180
|
+
} ? UpdateRow<Name, Fields, Extract<PrimaryKeyColumns, keyof Fields & string>> : never;
|