effect-qb 0.17.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/index.js +9376 -0
- package/dist/mysql.js +4092 -2671
- package/dist/postgres/metadata.js +2589 -1402
- package/dist/postgres.js +3953 -3583
- package/dist/sqlite.js +5527 -4088
- package/dist/standard.js +9330 -0
- package/package.json +9 -4
- package/src/casing.ts +71 -0
- package/src/index.ts +2 -0
- package/src/internal/casing.ts +89 -0
- package/src/internal/coercion/rules.ts +13 -1
- package/src/internal/column-state.d.ts +3 -3
- package/src/internal/column-state.ts +24 -18
- package/src/internal/column.ts +52 -15
- package/src/internal/datatypes/define.ts +7 -1
- package/src/internal/datatypes/enrich.ts +23 -0
- package/src/internal/datatypes/lookup.ts +81 -25
- package/src/internal/datatypes/matrix.ts +903 -0
- package/src/internal/datatypes/shape.ts +2 -0
- package/src/internal/derived-table.ts +4 -36
- package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +552 -361
- package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +657 -400
- package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +505 -347
- package/src/internal/dialect.ts +36 -1
- package/src/internal/dsl-mutation-runtime.ts +12 -162
- package/src/internal/dsl-plan-runtime.ts +10 -138
- package/src/internal/dsl-query-runtime.ts +5 -79
- package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
- package/src/internal/executor.ts +66 -49
- package/src/internal/grouping-key.ts +87 -20
- package/src/internal/implication-runtime.ts +1 -1
- package/src/internal/json/path-access.ts +351 -0
- package/src/internal/predicate/runtime.ts +3 -0
- package/src/internal/query.d.ts +39 -12
- package/src/internal/query.ts +65 -26
- package/src/internal/renderer.ts +26 -14
- package/src/internal/runtime/driver-value-mapping.ts +3 -3
- package/src/internal/runtime/normalize.ts +12 -5
- package/src/internal/runtime/schema.ts +28 -38
- package/src/internal/runtime/value.ts +20 -23
- package/src/internal/scalar.d.ts +1 -1
- package/src/internal/scalar.ts +8 -2
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +95 -43
- package/src/internal/schema-expression.ts +2 -2
- package/src/internal/sql-expression-renderer.ts +19 -0
- package/src/internal/standard-dsl.ts +6978 -0
- package/src/internal/table-options.ts +126 -66
- package/src/internal/table.ts +819 -237
- package/src/mysql/column-extension.ts +3 -0
- package/src/mysql/column.ts +14 -15
- package/src/mysql/datatypes/index.ts +4 -2
- package/src/mysql/datatypes/spec.ts +6 -176
- package/src/mysql/errors/normalize.ts +0 -1
- package/src/mysql/executor.ts +11 -11
- package/src/mysql/function/temporal.ts +1 -1
- package/src/mysql/internal/dialect.ts +9 -4
- package/src/mysql/internal/dsl.ts +334 -170
- package/src/mysql/internal/renderer.ts +6 -2
- package/src/mysql/json.ts +7 -2
- package/src/mysql/query-extension.ts +16 -0
- package/src/mysql/renderer.ts +37 -3
- package/src/mysql/type.ts +60 -0
- package/src/mysql.ts +7 -13
- package/src/postgres/check.ts +1 -0
- package/src/postgres/column-extension.ts +28 -0
- package/src/postgres/column.ts +13 -19
- package/src/postgres/datatypes/index.d.ts +2 -1
- package/src/postgres/datatypes/index.ts +4 -2
- package/src/postgres/datatypes/spec.ts +6 -260
- package/src/postgres/errors/normalize.ts +0 -1
- package/src/postgres/executor.ts +11 -11
- package/src/postgres/foreign-key.ts +24 -0
- package/src/postgres/function/core.ts +1 -3
- package/src/postgres/function/index.ts +1 -17
- package/src/postgres/function/temporal.ts +1 -1
- package/src/postgres/index.ts +1 -0
- package/src/postgres/internal/dialect.ts +9 -4
- package/src/postgres/internal/dsl.ts +328 -179
- package/src/postgres/internal/renderer.ts +6 -2
- package/src/postgres/internal/schema-ddl.ts +22 -10
- package/src/postgres/internal/schema-model.ts +238 -7
- package/src/postgres/json-extension.ts +7 -0
- package/src/postgres/json.ts +762 -173
- package/src/postgres/jsonb.ts +37 -0
- package/src/postgres/primary-key.ts +24 -0
- package/src/postgres/query-extension.ts +2 -0
- package/src/postgres/renderer.ts +37 -3
- package/src/postgres/schema-management.ts +13 -13
- package/src/postgres/schema.ts +106 -15
- package/src/postgres/table.ts +205 -538
- package/src/postgres/type.ts +93 -10
- package/src/postgres/unique.ts +32 -0
- package/src/postgres.ts +20 -16
- package/src/sqlite/column-extension.ts +3 -0
- package/src/sqlite/column.ts +14 -15
- package/src/sqlite/datatypes/index.ts +4 -2
- package/src/sqlite/datatypes/spec.ts +6 -94
- package/src/sqlite/errors/normalize.ts +0 -1
- package/src/sqlite/executor.ts +11 -11
- package/src/sqlite/function/temporal.ts +1 -1
- package/src/sqlite/internal/dialect.ts +9 -4
- package/src/sqlite/internal/dsl.ts +307 -159
- package/src/sqlite/internal/renderer.ts +6 -2
- package/src/sqlite/json.ts +8 -2
- package/src/sqlite/query-extension.ts +2 -0
- package/src/sqlite/renderer.ts +37 -3
- package/src/sqlite/type.ts +40 -0
- package/src/sqlite.ts +7 -13
- package/src/standard/cast.ts +113 -0
- package/src/standard/check.ts +17 -0
- package/src/standard/column.ts +163 -0
- package/src/standard/datatypes/index.ts +83 -0
- package/src/standard/datatypes/spec.ts +12 -0
- package/src/standard/dialect.ts +40 -0
- package/src/standard/foreign-key.ts +37 -0
- package/src/standard/function/aggregate.ts +2 -0
- package/src/standard/function/core.ts +2 -0
- package/src/standard/function/index.ts +18 -0
- package/src/standard/function/string.ts +2 -0
- package/src/standard/function/temporal.ts +78 -0
- package/src/standard/function/window.ts +2 -0
- package/src/standard/index.ts +17 -0
- package/src/standard/internal/renderer.ts +45 -0
- package/src/standard/json.ts +883 -0
- package/src/standard/primary-key.ts +17 -0
- package/src/standard/query.ts +152 -0
- package/src/standard/renderer.ts +49 -0
- package/src/standard/table.ts +151 -0
- package/src/standard/unique.ts +17 -0
- package/src/standard.ts +32 -0
- package/src/internal/aggregation-validation.ts +0 -57
- package/src/internal/table.d.ts +0 -173
- package/src/mysql/table.ts +0 -183
- package/src/postgres/cast.ts +0 -45
- package/src/sqlite/table.ts +0 -183
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-qb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"README.md"
|
|
22
22
|
],
|
|
23
23
|
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./src/index.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
},
|
|
24
28
|
"./postgres": {
|
|
25
29
|
"types": "./src/postgres.ts",
|
|
26
30
|
"import": "./dist/postgres.js"
|
|
@@ -40,6 +44,7 @@
|
|
|
40
44
|
"./package.json": "./package.json"
|
|
41
45
|
},
|
|
42
46
|
"imports": {
|
|
47
|
+
"#standard": "./src/standard.ts",
|
|
43
48
|
"#postgres": "./src/postgres.ts",
|
|
44
49
|
"#mysql": "./src/mysql.ts",
|
|
45
50
|
"#sqlite": "./src/sqlite.ts",
|
|
@@ -57,9 +62,9 @@
|
|
|
57
62
|
"@typescript/native-preview": "beta"
|
|
58
63
|
},
|
|
59
64
|
"dependencies": {
|
|
60
|
-
"@effect/experimental": "^0.57.0",
|
|
61
|
-
"@effect/sql": "^0.48.0",
|
|
62
|
-
"effect": "^3.19.3",
|
|
63
65
|
"pgsql-ast-parser": "^12.0.2"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"effect": "4.0.0-beta.98"
|
|
64
69
|
}
|
|
65
70
|
}
|
package/src/casing.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as InternalCasing from "./internal/casing.js"
|
|
2
|
+
import * as BaseTable from "./internal/table.js"
|
|
3
|
+
import * as Table from "./standard/table.js"
|
|
4
|
+
|
|
5
|
+
export type Style = InternalCasing.Style
|
|
6
|
+
export type Options = InternalCasing.Options
|
|
7
|
+
export type Input = Options | Style
|
|
8
|
+
|
|
9
|
+
export interface TableFactory {
|
|
10
|
+
readonly table: typeof Table.make
|
|
11
|
+
readonly [InternalCasing.TypeId]: InternalCasing.State
|
|
12
|
+
readonly withCasing: (options: Input) => TableFactory
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type CasingTarget =
|
|
16
|
+
| BaseTable.TableDefinition<any, any, any, any, any>
|
|
17
|
+
| {
|
|
18
|
+
readonly [InternalCasing.TypeId]: InternalCasing.State
|
|
19
|
+
readonly withCasing: (options: Options) => CasingTarget
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isTable = (value: unknown): value is BaseTable.TableDefinition<any, any, any, any, any> =>
|
|
23
|
+
typeof value === "object" && value !== null && BaseTable.TypeId in value
|
|
24
|
+
|
|
25
|
+
const allCategories = (style: Style): Options => ({
|
|
26
|
+
tables: style,
|
|
27
|
+
columns: style,
|
|
28
|
+
schemas: style,
|
|
29
|
+
indexes: style,
|
|
30
|
+
constraints: style,
|
|
31
|
+
types: style,
|
|
32
|
+
sequences: style
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const normalize = (input: Input): Options =>
|
|
36
|
+
typeof input === "string" || typeof input === "function" ? allCategories(input) : input
|
|
37
|
+
|
|
38
|
+
export function withCasing(options: Style): <Value extends CasingTarget>(value: Value) => Value
|
|
39
|
+
export function withCasing(options: Options): <Value extends CasingTarget>(value: Value) => Value
|
|
40
|
+
export function withCasing(options: Input) {
|
|
41
|
+
return <Value extends CasingTarget>(value: Value): Value => {
|
|
42
|
+
const normalized = normalize(options)
|
|
43
|
+
if (isTable(value)) {
|
|
44
|
+
return BaseTable.withCasing(value, normalized) as Value
|
|
45
|
+
}
|
|
46
|
+
return (value as Exclude<CasingTarget, BaseTable.TableDefinition<any, any, any, any, any>>).withCasing(normalized) as Value
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function make(options: Style): TableFactory
|
|
51
|
+
export function make(options: Options): TableFactory
|
|
52
|
+
export function make(options: Input): TableFactory {
|
|
53
|
+
const normalized = normalize(options)
|
|
54
|
+
const withFactoryCasing = withCasing(normalized)
|
|
55
|
+
const table = ((name: string, fields: any, schemaName?: string) =>
|
|
56
|
+
schemaName === undefined
|
|
57
|
+
? Table.make(name, fields).pipe(withFactoryCasing)
|
|
58
|
+
: Table.make(name, fields, schemaName).pipe(withFactoryCasing)) as typeof Table.make
|
|
59
|
+
const factory = {
|
|
60
|
+
table,
|
|
61
|
+
[InternalCasing.TypeId]: {
|
|
62
|
+
casing: normalized
|
|
63
|
+
},
|
|
64
|
+
withCasing: (override: Input) => make(InternalCasing.merge(normalized, normalize(override)) ?? {})
|
|
65
|
+
}
|
|
66
|
+
return factory
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const apply = InternalCasing.apply
|
|
70
|
+
export const applyCategory = InternalCasing.applyCategory
|
|
71
|
+
export const merge = InternalCasing.merge
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const TypeId: unique symbol = Symbol.for("effect-qb/Casing")
|
|
2
|
+
|
|
3
|
+
export type Style =
|
|
4
|
+
| "preserve"
|
|
5
|
+
| "snake_case"
|
|
6
|
+
| "camelCase"
|
|
7
|
+
| "PascalCase"
|
|
8
|
+
| "kebab-case"
|
|
9
|
+
| "SCREAMING_SNAKE_CASE"
|
|
10
|
+
| ((name: string) => string)
|
|
11
|
+
|
|
12
|
+
export interface Options {
|
|
13
|
+
readonly tables?: Style
|
|
14
|
+
readonly columns?: Style
|
|
15
|
+
readonly schemas?: Style
|
|
16
|
+
readonly indexes?: Style
|
|
17
|
+
readonly constraints?: Style
|
|
18
|
+
readonly types?: Style
|
|
19
|
+
readonly sequences?: Style
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type Category = keyof Options
|
|
23
|
+
|
|
24
|
+
export interface State {
|
|
25
|
+
readonly casing?: Options
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const merge = (
|
|
29
|
+
base: Options | undefined,
|
|
30
|
+
override: Options | undefined
|
|
31
|
+
): Options | undefined => {
|
|
32
|
+
if (base === undefined) {
|
|
33
|
+
return override
|
|
34
|
+
}
|
|
35
|
+
if (override === undefined) {
|
|
36
|
+
return base
|
|
37
|
+
}
|
|
38
|
+
return { ...base, ...override }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const words = (name: string): readonly string[] =>
|
|
42
|
+
name
|
|
43
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
44
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
45
|
+
.split(/[^A-Za-z0-9]+/)
|
|
46
|
+
.filter((part) => part.length > 0)
|
|
47
|
+
|
|
48
|
+
const capitalize = (value: string): string =>
|
|
49
|
+
value.length === 0 ? value : `${value[0]!.toUpperCase()}${value.slice(1)}`
|
|
50
|
+
|
|
51
|
+
const lowerWords = (name: string): readonly string[] =>
|
|
52
|
+
words(name).map((part) => part.toLowerCase())
|
|
53
|
+
|
|
54
|
+
const applyNamedStyle = (style: Exclude<Style, (name: string) => string>, name: string): string => {
|
|
55
|
+
switch (style) {
|
|
56
|
+
case "preserve":
|
|
57
|
+
return name
|
|
58
|
+
case "snake_case":
|
|
59
|
+
return lowerWords(name).join("_")
|
|
60
|
+
case "camelCase": {
|
|
61
|
+
const parts = lowerWords(name)
|
|
62
|
+
const [head, ...tail] = parts
|
|
63
|
+
return head === undefined ? "" : `${head}${tail.map(capitalize).join("")}`
|
|
64
|
+
}
|
|
65
|
+
case "PascalCase":
|
|
66
|
+
return lowerWords(name).map(capitalize).join("")
|
|
67
|
+
case "kebab-case":
|
|
68
|
+
return lowerWords(name).join("-")
|
|
69
|
+
case "SCREAMING_SNAKE_CASE":
|
|
70
|
+
return lowerWords(name).join("_").toUpperCase()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const apply = (
|
|
75
|
+
style: Style | undefined,
|
|
76
|
+
name: string
|
|
77
|
+
): string => {
|
|
78
|
+
if (style === undefined) {
|
|
79
|
+
return name
|
|
80
|
+
}
|
|
81
|
+
return typeof style === "function" ? style(name) : applyNamedStyle(style, name)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const applyCategory = (
|
|
85
|
+
options: Options | undefined,
|
|
86
|
+
category: Category,
|
|
87
|
+
name: string
|
|
88
|
+
): string => apply(options?.[category], name)
|
|
89
|
+
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type * as Expression from "../scalar.js"
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CanCastDbType as LookupCanCastDbType,
|
|
4
|
+
CanCompareDbTypes as LookupCanCompareDbTypes,
|
|
5
|
+
CanContainDbTypes as LookupCanContainDbTypes,
|
|
6
|
+
CanImplicitlyConvertDbType as LookupCanImplicitlyConvertDbType,
|
|
7
|
+
CanTextuallyCoerceDbType as LookupCanTextuallyCoerceDbType
|
|
8
|
+
} from "../datatypes/lookup.js"
|
|
3
9
|
|
|
4
10
|
export type CanCompareDbTypes<
|
|
5
11
|
Left extends Expression.DbType.Any,
|
|
@@ -18,6 +24,12 @@ export type CanTextuallyCoerceDbType<
|
|
|
18
24
|
Dialect extends string
|
|
19
25
|
> = LookupCanTextuallyCoerceDbType<Db, Dialect>
|
|
20
26
|
|
|
27
|
+
export type CanImplicitlyConvertDbType<
|
|
28
|
+
Source extends Expression.DbType.Any,
|
|
29
|
+
Target extends Expression.DbType.Any,
|
|
30
|
+
Dialect extends string
|
|
31
|
+
> = LookupCanImplicitlyConvertDbType<Source, Target, Dialect>
|
|
32
|
+
|
|
21
33
|
export type CanCastDbType<
|
|
22
34
|
Source extends Expression.DbType.Any,
|
|
23
35
|
Target extends Expression.DbType.Any,
|
|
@@ -70,7 +70,7 @@ export interface ColumnState<Select, Insert, Update, Db extends Expression.DbTyp
|
|
|
70
70
|
export interface ColumnDefinition<Select, Insert, Update, Db extends Expression.DbType.Any, Nullable extends boolean, HasDefault extends boolean, Generated extends boolean, PrimaryKey extends boolean, Unique extends boolean, Ref, Dependencies extends Expression.BindingId = never> extends Pipeable, Expression.Scalar<Select, Db, Nullable extends true ? "maybe" : "never", Db["dialect"], "scalar", Dependencies> {
|
|
71
71
|
readonly pipe: Pipeable["pipe"];
|
|
72
72
|
readonly [ColumnTypeId]: ColumnState<Select, Insert, Update, Db, Nullable, HasDefault, Generated, PrimaryKey, Unique, Ref, Dependencies>;
|
|
73
|
-
readonly schema: Schema.Schema<NonNullable<Select
|
|
73
|
+
readonly schema: Schema.Schema<NonNullable<Select>>;
|
|
74
74
|
readonly metadata: {
|
|
75
75
|
readonly dbType: Db;
|
|
76
76
|
readonly nullable: Nullable;
|
|
@@ -111,7 +111,7 @@ export type AnyColumnDefinition = ColumnDefinition<any, any, any, Expression.DbT
|
|
|
111
111
|
/** Convenience alias for any bound column. */
|
|
112
112
|
export type AnyBoundColumn = BoundColumn<any, any, any, Expression.DbType.Any, boolean, boolean, boolean, boolean, boolean, any, string, string, string>;
|
|
113
113
|
/** Constructs a runtime column-definition object from schema and metadata. */
|
|
114
|
-
export declare const makeColumnDefinition: <Select, Insert, Update, Db extends Expression.DbType.Any, Nullable extends boolean, HasDefault extends boolean, Generated extends boolean, PrimaryKey extends boolean, Unique extends boolean, Ref, Dependencies extends string = never>(schema: Schema.Schema<NonNullable<Select
|
|
114
|
+
export declare const makeColumnDefinition: <Select, Insert, Update, Db extends Expression.DbType.Any, Nullable extends boolean, HasDefault extends boolean, Generated extends boolean, PrimaryKey extends boolean, Unique extends boolean, Ref, Dependencies extends string = never>(schema: Schema.Schema<NonNullable<Select>>, metadata: {
|
|
115
115
|
readonly dbType: Db;
|
|
116
116
|
readonly nullable: Nullable;
|
|
117
117
|
readonly hasDefault: HasDefault;
|
|
@@ -135,7 +135,7 @@ export declare const makeColumnDefinition: <Select, Insert, Update, Db extends E
|
|
|
135
135
|
} | undefined;
|
|
136
136
|
}) => ColumnDefinition<Select, Insert, Update, Db, Nullable, HasDefault, Generated, PrimaryKey, Unique, Ref, Dependencies>;
|
|
137
137
|
export declare const remapColumnDefinition: <Select, Insert, Update, Db extends Expression.DbType.Any, Nullable extends boolean, HasDefault extends boolean, Generated extends boolean, PrimaryKey extends boolean, Unique extends boolean, Ref, Dependencies extends string = never>(column: ColumnDefinition<Select, Insert, Update, Db, Nullable, HasDefault, Generated, PrimaryKey, Unique, Ref, Dependencies>, options?: {
|
|
138
|
-
readonly schema?: Schema.
|
|
138
|
+
readonly schema?: Schema.Top | undefined;
|
|
139
139
|
readonly metadata?: {
|
|
140
140
|
readonly dbType: Db;
|
|
141
141
|
readonly nullable: Nullable;
|
|
@@ -4,6 +4,8 @@ import * as Schema from "effect/Schema"
|
|
|
4
4
|
|
|
5
5
|
import * as Expression from "./scalar.js"
|
|
6
6
|
import * as ExpressionAst from "./expression-ast.js"
|
|
7
|
+
import { withJsonPathAccess, type WithJsonPathAccess } from "./json/path-access.js"
|
|
8
|
+
import type * as Casing from "./casing.js"
|
|
7
9
|
import type * as SchemaExpression from "./schema-expression.js"
|
|
8
10
|
|
|
9
11
|
/** Symbol used to attach column-definition metadata. */
|
|
@@ -123,7 +125,7 @@ export interface ColumnDefinition<
|
|
|
123
125
|
Ref,
|
|
124
126
|
Dependencies
|
|
125
127
|
>
|
|
126
|
-
readonly schema: Schema.Schema<NonNullable<Select
|
|
128
|
+
readonly schema: Schema.Schema<NonNullable<Select>>
|
|
127
129
|
readonly metadata: {
|
|
128
130
|
readonly dbType: Db
|
|
129
131
|
readonly nullable: Nullable
|
|
@@ -183,6 +185,7 @@ export interface BoundColumn<
|
|
|
183
185
|
readonly columnName: ColumnName
|
|
184
186
|
readonly baseTableName: BaseTableName
|
|
185
187
|
readonly schemaName?: string
|
|
188
|
+
readonly casing?: Casing.Options
|
|
186
189
|
}
|
|
187
190
|
readonly [Expression.TypeId]: Expression.State<
|
|
188
191
|
Select,
|
|
@@ -227,7 +230,7 @@ export type AnyBoundColumn = BoundColumn<
|
|
|
227
230
|
>
|
|
228
231
|
|
|
229
232
|
const ColumnProto = {
|
|
230
|
-
pipe(this:
|
|
233
|
+
pipe(this: Pipeable) {
|
|
231
234
|
return pipeArguments(this, arguments)
|
|
232
235
|
}
|
|
233
236
|
}
|
|
@@ -236,7 +239,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
|
|
|
236
239
|
Object.defineProperty(value, "pipe", {
|
|
237
240
|
configurable: true,
|
|
238
241
|
writable: true,
|
|
239
|
-
value: function(this:
|
|
242
|
+
value: function(this: Value) {
|
|
240
243
|
return pipeArguments(value, arguments)
|
|
241
244
|
}
|
|
242
245
|
})
|
|
@@ -257,7 +260,7 @@ export const makeColumnDefinition = <
|
|
|
257
260
|
Ref,
|
|
258
261
|
Dependencies extends Expression.BindingId = never
|
|
259
262
|
>(
|
|
260
|
-
schema: Schema.Schema<NonNullable<Select
|
|
263
|
+
schema: Schema.Schema<NonNullable<Select>>,
|
|
261
264
|
metadata: ColumnDefinition<
|
|
262
265
|
Select,
|
|
263
266
|
Insert,
|
|
@@ -271,7 +274,7 @@ export const makeColumnDefinition = <
|
|
|
271
274
|
Ref,
|
|
272
275
|
Dependencies
|
|
273
276
|
>["metadata"]
|
|
274
|
-
): ColumnDefinition<
|
|
277
|
+
): WithJsonPathAccess<ColumnDefinition<
|
|
275
278
|
Select,
|
|
276
279
|
Insert,
|
|
277
280
|
Update,
|
|
@@ -283,7 +286,7 @@ export const makeColumnDefinition = <
|
|
|
283
286
|
Unique,
|
|
284
287
|
Ref,
|
|
285
288
|
Dependencies
|
|
286
|
-
|
|
289
|
+
>> => {
|
|
287
290
|
const column = attachPipe(Object.create(ColumnProto))
|
|
288
291
|
column.schema = schema
|
|
289
292
|
column.metadata = metadata
|
|
@@ -315,7 +318,7 @@ export const makeColumnDefinition = <
|
|
|
315
318
|
identity: metadata.identity,
|
|
316
319
|
enum: metadata.enum
|
|
317
320
|
}
|
|
318
|
-
return column
|
|
321
|
+
return withJsonPathAccess(column)
|
|
319
322
|
}
|
|
320
323
|
|
|
321
324
|
export const remapColumnDefinition = <
|
|
@@ -345,7 +348,7 @@ export const remapColumnDefinition = <
|
|
|
345
348
|
Dependencies
|
|
346
349
|
>,
|
|
347
350
|
options: {
|
|
348
|
-
readonly schema?: Schema.
|
|
351
|
+
readonly schema?: Schema.Top
|
|
349
352
|
readonly metadata?: ColumnDefinition<
|
|
350
353
|
Select,
|
|
351
354
|
Insert,
|
|
@@ -360,7 +363,7 @@ export const remapColumnDefinition = <
|
|
|
360
363
|
Dependencies
|
|
361
364
|
>["metadata"]
|
|
362
365
|
} = {}
|
|
363
|
-
): ColumnDefinition<
|
|
366
|
+
): WithJsonPathAccess<ColumnDefinition<
|
|
364
367
|
Select,
|
|
365
368
|
Insert,
|
|
366
369
|
Update,
|
|
@@ -372,7 +375,7 @@ export const remapColumnDefinition = <
|
|
|
372
375
|
Unique,
|
|
373
376
|
Ref,
|
|
374
377
|
Dependencies
|
|
375
|
-
|
|
378
|
+
>> => {
|
|
376
379
|
const schema = options.schema ?? column.schema
|
|
377
380
|
const metadata = options.metadata ?? column.metadata
|
|
378
381
|
const next = attachPipe(Object.create(ColumnProto))
|
|
@@ -407,21 +410,22 @@ export const remapColumnDefinition = <
|
|
|
407
410
|
enum: metadata.enum
|
|
408
411
|
}
|
|
409
412
|
if (ExpressionAst.TypeId in column) {
|
|
410
|
-
next[ExpressionAst.TypeId] = (column as
|
|
413
|
+
next[ExpressionAst.TypeId] = (column as {
|
|
411
414
|
readonly [ExpressionAst.TypeId]: ExpressionAst.Any
|
|
412
415
|
})[ExpressionAst.TypeId]
|
|
413
416
|
}
|
|
414
417
|
if (BoundColumnTypeId in column) {
|
|
415
|
-
next[BoundColumnTypeId] = (column as
|
|
418
|
+
next[BoundColumnTypeId] = (column as {
|
|
416
419
|
readonly [BoundColumnTypeId]: {
|
|
417
420
|
readonly tableName: string
|
|
418
421
|
readonly columnName: string
|
|
419
422
|
readonly baseTableName: string
|
|
420
423
|
readonly schemaName?: string
|
|
424
|
+
readonly casing?: Casing.Options
|
|
421
425
|
}
|
|
422
426
|
})[BoundColumnTypeId]
|
|
423
427
|
}
|
|
424
|
-
return next
|
|
428
|
+
return withJsonPathAccess(next)
|
|
425
429
|
}
|
|
426
430
|
|
|
427
431
|
/** Attaches table/column provenance to an existing column definition. */
|
|
@@ -436,7 +440,8 @@ export const bindColumn = <
|
|
|
436
440
|
columnName: ColumnName,
|
|
437
441
|
column: Column,
|
|
438
442
|
baseTableName: BaseTableName,
|
|
439
|
-
schemaName?: SchemaName
|
|
443
|
+
schemaName?: SchemaName,
|
|
444
|
+
casing?: Casing.Options
|
|
440
445
|
): BoundColumnFrom<Column, TableName, ColumnName, BaseTableName> => {
|
|
441
446
|
const brandName = `${tableName}.${columnName}`
|
|
442
447
|
const schema = column.metadata.brand === true
|
|
@@ -467,9 +472,10 @@ export const bindColumn = <
|
|
|
467
472
|
tableName,
|
|
468
473
|
columnName,
|
|
469
474
|
baseTableName,
|
|
470
|
-
schemaName
|
|
475
|
+
schemaName,
|
|
476
|
+
casing
|
|
471
477
|
}
|
|
472
|
-
return bound
|
|
478
|
+
return withJsonPathAccess(bound) as BoundColumnFrom<Column, TableName, ColumnName, BaseTableName>
|
|
473
479
|
}
|
|
474
480
|
|
|
475
481
|
/** Extracts the internal state record for a column. */
|
|
@@ -508,7 +514,7 @@ export type BoundColumnFrom<
|
|
|
508
514
|
TableName extends string,
|
|
509
515
|
ColumnName extends string,
|
|
510
516
|
BaseTableName extends string = TableName
|
|
511
|
-
> = BoundColumn<
|
|
517
|
+
> = WithJsonPathAccess<BoundColumn<
|
|
512
518
|
Column["metadata"]["brand"] extends true
|
|
513
519
|
? BrandedValue<SelectType<Column>, `${TableName}.${ColumnName}`>
|
|
514
520
|
: SelectType<Column>,
|
|
@@ -528,4 +534,4 @@ export type BoundColumnFrom<
|
|
|
528
534
|
TableName,
|
|
529
535
|
ColumnName,
|
|
530
536
|
BaseTableName
|
|
531
|
-
|
|
537
|
+
>>
|
package/src/internal/column.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
type SelectType,
|
|
43
43
|
type UpdateType
|
|
44
44
|
} from "./column-state.js"
|
|
45
|
+
import type { NonEmptyStringInput } from "./table-options.js"
|
|
45
46
|
|
|
46
47
|
type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
|
|
47
48
|
|
|
@@ -223,23 +224,53 @@ type ForeignKeyOptions<Target extends AnyBoundColumn> = {
|
|
|
223
224
|
readonly initiallyDeferred?: boolean
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
type NonEmptyOptionNameInput<Options> = Options extends { readonly name: infer Name extends string }
|
|
228
|
+
? NonEmptyStringInput<Name> extends never ? never : unknown
|
|
229
|
+
: unknown
|
|
230
|
+
|
|
231
|
+
type NonEmptyStringArrayInput<Values extends readonly string[]> =
|
|
232
|
+
[Extract<Values[number], "">] extends [never] ? unknown : never
|
|
233
|
+
|
|
234
|
+
type NonEmptyIndexMethodInput<Options> = Options extends { readonly method: infer Method extends string }
|
|
235
|
+
? NonEmptyStringInput<Method> extends never ? never : unknown
|
|
236
|
+
: unknown
|
|
237
|
+
|
|
238
|
+
type NonEmptyIndexIncludeInput<Options> = Options extends { readonly include: infer Include extends readonly string[] }
|
|
239
|
+
? NonEmptyStringArrayInput<Include>
|
|
240
|
+
: unknown
|
|
241
|
+
|
|
242
|
+
type NonEmptyIndexOperatorClassInput<Options> = Options extends { readonly operatorClass: infer OperatorClass extends string }
|
|
243
|
+
? NonEmptyStringInput<OperatorClass> extends never ? never : unknown
|
|
244
|
+
: unknown
|
|
245
|
+
|
|
246
|
+
type NonEmptyIndexCollationInput<Options> = Options extends { readonly collation: infer Collation extends string }
|
|
247
|
+
? NonEmptyStringInput<Collation> extends never ? never : unknown
|
|
248
|
+
: unknown
|
|
249
|
+
|
|
250
|
+
type NonEmptyIndexMetadataInput<Options> =
|
|
251
|
+
& NonEmptyOptionNameInput<Options>
|
|
252
|
+
& NonEmptyIndexMethodInput<Options>
|
|
253
|
+
& NonEmptyIndexIncludeInput<Options>
|
|
254
|
+
& NonEmptyIndexOperatorClassInput<Options>
|
|
255
|
+
& NonEmptyIndexCollationInput<Options>
|
|
256
|
+
|
|
226
257
|
type SchemaCompatibleColumn<
|
|
227
258
|
Column extends AnyColumnDefinition,
|
|
228
|
-
SchemaType extends Schema.
|
|
229
|
-
> = [BaseSelectType<Column>] extends [Schema.
|
|
259
|
+
SchemaType extends Schema.Top
|
|
260
|
+
> = [BaseSelectType<Column>] extends [Schema.Codec.Encoded<SchemaType>]
|
|
230
261
|
? Column
|
|
231
262
|
: never
|
|
232
263
|
|
|
233
264
|
type ColumnSchemaOutput<
|
|
234
265
|
Column extends AnyColumnDefinition,
|
|
235
|
-
SchemaType extends Schema.
|
|
266
|
+
SchemaType extends Schema.Top
|
|
236
267
|
> = IsNullable<Column> extends true
|
|
237
268
|
? Schema.Schema.Type<SchemaType> | null
|
|
238
269
|
: Schema.Schema.Type<SchemaType>
|
|
239
270
|
|
|
240
271
|
type ColumnWithSchema<
|
|
241
272
|
Column extends AnyColumnDefinition,
|
|
242
|
-
SchemaType extends Schema.
|
|
273
|
+
SchemaType extends Schema.Top
|
|
243
274
|
> = ColumnDefinition<
|
|
244
275
|
ColumnSchemaOutput<Column, SchemaType>,
|
|
245
276
|
ColumnSchemaOutput<Column, SchemaType>,
|
|
@@ -376,7 +407,7 @@ const isColumnDefinitionValue = (value: unknown): value is AnyColumnDefinition =
|
|
|
376
407
|
typeof value === "object" && value !== null && ColumnTypeId in value
|
|
377
408
|
|
|
378
409
|
const primitive = <Type, Db extends Expression.DbType.Any>(
|
|
379
|
-
schema: Schema.Schema<Type
|
|
410
|
+
schema: Schema.Schema<Type>,
|
|
380
411
|
dbType: Db
|
|
381
412
|
): ColumnDefinition<Type, Type, Type, Db, false, false, false, false, false, undefined> =>
|
|
382
413
|
makeColumnDefinition(schema as Schema.Schema<NonNullable<Type>>, {
|
|
@@ -401,7 +432,7 @@ type ColumnModule<
|
|
|
401
432
|
JsonKind extends string
|
|
402
433
|
> = {
|
|
403
434
|
readonly custom: <
|
|
404
|
-
SchemaType extends Schema.
|
|
435
|
+
SchemaType extends Schema.Top,
|
|
405
436
|
Db extends Expression.DbType.Any
|
|
406
437
|
>(
|
|
407
438
|
schema: SchemaType,
|
|
@@ -425,7 +456,7 @@ type ColumnModule<
|
|
|
425
456
|
readonly boolean: () => ColumnDefinition<boolean, boolean, boolean, Expression.DbType.Base<Dialect, BooleanKind>, false, false, false, false, false, undefined>
|
|
426
457
|
readonly date: () => ColumnDefinition<LocalDateString, LocalDateString, LocalDateString, Expression.DbType.Base<Dialect, DateKind>, false, false, false, false, false, undefined>
|
|
427
458
|
readonly timestamp: () => ColumnDefinition<LocalDateTimeString, LocalDateTimeString, LocalDateTimeString, Expression.DbType.Base<Dialect, TimestampKind>, false, false, false, false, false, undefined>
|
|
428
|
-
readonly json: <SchemaType extends Schema.
|
|
459
|
+
readonly json: <SchemaType extends Schema.Top>(
|
|
429
460
|
schema: SchemaType
|
|
430
461
|
) => ColumnDefinition<
|
|
431
462
|
Schema.Schema.Type<SchemaType>,
|
|
@@ -442,7 +473,7 @@ type ColumnModule<
|
|
|
442
473
|
}
|
|
443
474
|
|
|
444
475
|
/** Replaces a column's runtime schema while preserving its SQL type metadata. */
|
|
445
|
-
export const schema = <SchemaType extends Schema.
|
|
476
|
+
export const schema = <SchemaType extends Schema.Top>(nextSchema: SchemaType) =>
|
|
446
477
|
<Column extends AnyColumnDefinition>(
|
|
447
478
|
column: SchemaCompatibleColumn<Column, SchemaType>
|
|
448
479
|
): ColumnWithSchema<Column, SchemaType> =>
|
|
@@ -500,7 +531,7 @@ export const primaryKey = <Column extends AnyColumnDefinition>(
|
|
|
500
531
|
type UniqueModifier = {
|
|
501
532
|
<Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
|
|
502
533
|
readonly options: <const Options extends ColumnUniqueOptions>(
|
|
503
|
-
options: Options
|
|
534
|
+
options: Options & NonEmptyOptionNameInput<Options>
|
|
504
535
|
) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
|
|
505
536
|
}
|
|
506
537
|
|
|
@@ -550,11 +581,11 @@ export const generated = <Value extends DdlExpression>(value: Value) =>
|
|
|
550
581
|
}) as GeneratedColumn<Column>
|
|
551
582
|
|
|
552
583
|
/** Preserves the exact SQL type used for DDL rendering. */
|
|
553
|
-
export const ddlType = <SqlType extends string>(sqlType: SqlType) =>
|
|
584
|
+
export const ddlType = <SqlType extends string>(sqlType: NonEmptyStringInput<SqlType>) =>
|
|
554
585
|
<Column extends AnyColumnDefinition>(column: Column): DdlTypedColumn<Column> =>
|
|
555
586
|
mapColumn(column, {
|
|
556
587
|
...column.metadata,
|
|
557
|
-
ddlType: sqlType
|
|
588
|
+
ddlType: sqlType as SqlType
|
|
558
589
|
}) as DdlTypedColumn<Column>
|
|
559
590
|
|
|
560
591
|
/** Overrides how a column crosses the SQL driver boundary. */
|
|
@@ -590,13 +621,15 @@ export const array = <Options extends ArrayOptions | undefined = undefined>(
|
|
|
590
621
|
}) as ArrayColumn<Column, Options>
|
|
591
622
|
|
|
592
623
|
/** Marks a column as indexed. */
|
|
624
|
+
type IndexPipe = <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
|
|
625
|
+
|
|
593
626
|
export function index<Column extends AnyColumnDefinition>(
|
|
594
627
|
column: Column
|
|
595
628
|
): IndexedColumn<Column>
|
|
596
629
|
export function index<const Options extends ColumnIndexOptions>(
|
|
597
|
-
options: Options
|
|
630
|
+
options: Options & NonEmptyIndexMetadataInput<Options>
|
|
598
631
|
): <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
|
|
599
|
-
export function index(arg:
|
|
632
|
+
export function index(arg: AnyColumnDefinition | ColumnIndexOptions): IndexedColumn<AnyColumnDefinition> | IndexPipe {
|
|
600
633
|
if (isColumnDefinitionValue(arg)) {
|
|
601
634
|
return mapColumn(arg, {
|
|
602
635
|
...arg.metadata,
|
|
@@ -648,17 +681,21 @@ export const identityAlways = <Column extends AnyColumnDefinition>(
|
|
|
648
681
|
*
|
|
649
682
|
* The base, non-null select types must match.
|
|
650
683
|
*/
|
|
684
|
+
type ForeignKeyPipe<Target extends AnyBoundColumn = AnyBoundColumn> = <Column extends AnyColumnDefinition>(
|
|
685
|
+
column: CompatibleReference<Column, Target>
|
|
686
|
+
) => ReferencingColumn<Column, Target>
|
|
687
|
+
|
|
651
688
|
export function foreignKey<Target extends AnyBoundColumn>(
|
|
652
689
|
target: () => Target
|
|
653
690
|
): <Column extends AnyColumnDefinition>(
|
|
654
691
|
column: CompatibleReference<Column, Target>
|
|
655
692
|
) => ReferencingColumn<Column, Target>
|
|
656
693
|
export function foreignKey<const Options extends ForeignKeyOptions<AnyBoundColumn>>(
|
|
657
|
-
options: Options
|
|
694
|
+
options: Options & NonEmptyOptionNameInput<Options>
|
|
658
695
|
): <Column extends AnyColumnDefinition>(
|
|
659
696
|
column: CompatibleReference<Column, ReturnType<Options["target"]>>
|
|
660
697
|
) => ReferencingColumn<Column, ReturnType<Options["target"]>>
|
|
661
|
-
export function foreignKey(arg:
|
|
698
|
+
export function foreignKey(arg: (() => AnyBoundColumn) | ForeignKeyOptions<AnyBoundColumn>): ForeignKeyPipe {
|
|
662
699
|
if (typeof arg === "function") {
|
|
663
700
|
const target = arg as () => AnyBoundColumn
|
|
664
701
|
return <Column extends AnyColumnDefinition>(
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type * as Expression from "../scalar.js"
|
|
2
|
+
import type { NonEmptyStringInput } from "../table-options.js"
|
|
2
3
|
import type { DatatypeFamilySpec, DatatypeKindSpec } from "./shape.js"
|
|
3
4
|
|
|
5
|
+
type ImplicitTargetsOf<Family> = Family extends { readonly implicitTargets: infer Targets extends readonly string[] }
|
|
6
|
+
? Targets
|
|
7
|
+
: readonly []
|
|
8
|
+
|
|
4
9
|
type DatatypeWitness<
|
|
5
10
|
Dialect extends string,
|
|
6
11
|
Kinds extends Record<string, DatatypeKindSpec>,
|
|
@@ -11,6 +16,7 @@ type DatatypeWitness<
|
|
|
11
16
|
readonly runtime: Kinds[Kind]["runtime"]
|
|
12
17
|
readonly compareGroup: Families[Kinds[Kind]["family"]]["compareGroup"]
|
|
13
18
|
readonly castTargets: Families[Kinds[Kind]["family"]]["castTargets"]
|
|
19
|
+
readonly implicitTargets: ImplicitTargetsOf<Families[Kinds[Kind]["family"]]>
|
|
14
20
|
readonly traits: Families[Kinds[Kind]["family"]]["traits"]
|
|
15
21
|
}
|
|
16
22
|
|
|
@@ -20,7 +26,7 @@ export type DatatypeModule<
|
|
|
20
26
|
Families extends Record<string, DatatypeFamilySpec>,
|
|
21
27
|
Aliases extends Record<string, string> = Record<never, never>
|
|
22
28
|
> = {
|
|
23
|
-
readonly custom: <Kind extends string>(kind: Kind) => Expression.DbType.Base<Dialect, Kind>
|
|
29
|
+
readonly custom: <Kind extends string>(kind: NonEmptyStringInput<Kind>) => Expression.DbType.Base<Dialect, Kind>
|
|
24
30
|
} & {
|
|
25
31
|
readonly [Kind in keyof Kinds]: () => DatatypeWitness<Dialect, Kinds, Families, Kind & string>
|
|
26
32
|
} & {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type * as Expression from "../scalar.js"
|
|
2
|
+
|
|
3
|
+
type DatatypeLookup = Readonly<Record<string, (() => Expression.DbType.Any) | undefined>>
|
|
4
|
+
|
|
5
|
+
export const enrichDbType = <
|
|
6
|
+
Module extends object,
|
|
7
|
+
Db extends Expression.DbType.Any
|
|
8
|
+
>(
|
|
9
|
+
datatypes: Module,
|
|
10
|
+
dbType: Db
|
|
11
|
+
): Db => {
|
|
12
|
+
if (dbType.kind === "custom") {
|
|
13
|
+
return dbType
|
|
14
|
+
}
|
|
15
|
+
const lookup = datatypes as DatatypeLookup
|
|
16
|
+
if (!(dbType.kind in lookup)) {
|
|
17
|
+
return dbType
|
|
18
|
+
}
|
|
19
|
+
const candidate = lookup[dbType.kind]
|
|
20
|
+
return typeof candidate === "function"
|
|
21
|
+
? { ...candidate(), ...dbType } as Db
|
|
22
|
+
: dbType
|
|
23
|
+
}
|