pqb 0.0.1
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/dist/index.d.ts +3630 -0
- package/dist/index.esm.js +4587 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +4691 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
- package/rollup.config.js +35 -0
- package/src/adapter.test.ts +10 -0
- package/src/adapter.ts +171 -0
- package/src/columnSchema/array.ts +21 -0
- package/src/columnSchema/boolean.ts +10 -0
- package/src/columnSchema/columnType.test.ts +129 -0
- package/src/columnSchema/columnType.ts +77 -0
- package/src/columnSchema/columnTypes.ts +145 -0
- package/src/columnSchema/columnsSchema.test.ts +32 -0
- package/src/columnSchema/columnsSchema.ts +100 -0
- package/src/columnSchema/commonMethods.ts +130 -0
- package/src/columnSchema/dateTime.ts +104 -0
- package/src/columnSchema/enum.ts +13 -0
- package/src/columnSchema/index.ts +11 -0
- package/src/columnSchema/json/array.ts +55 -0
- package/src/columnSchema/json/discriminatedUnion.ts +91 -0
- package/src/columnSchema/json/enum.ts +29 -0
- package/src/columnSchema/json/instanceOf.ts +16 -0
- package/src/columnSchema/json/intersection.ts +23 -0
- package/src/columnSchema/json/lazy.ts +22 -0
- package/src/columnSchema/json/literal.ts +12 -0
- package/src/columnSchema/json/map.ts +29 -0
- package/src/columnSchema/json/nativeEnum.ts +30 -0
- package/src/columnSchema/json/nullable.ts +33 -0
- package/src/columnSchema/json/nullish.ts +30 -0
- package/src/columnSchema/json/object.ts +206 -0
- package/src/columnSchema/json/optional.ts +28 -0
- package/src/columnSchema/json/record.ts +40 -0
- package/src/columnSchema/json/scalarTypes.ts +117 -0
- package/src/columnSchema/json/set.ts +34 -0
- package/src/columnSchema/json/tuple.ts +40 -0
- package/src/columnSchema/json/typeBase.ts +202 -0
- package/src/columnSchema/json/union.ts +16 -0
- package/src/columnSchema/json.ts +64 -0
- package/src/columnSchema/number.ts +122 -0
- package/src/columnSchema/string.ts +222 -0
- package/src/columnSchema/utils.ts +27 -0
- package/src/common.ts +86 -0
- package/src/db.test.ts +67 -0
- package/src/db.ts +212 -0
- package/src/errors.ts +7 -0
- package/src/index.ts +18 -0
- package/src/operators.test.ts +608 -0
- package/src/operators.ts +177 -0
- package/src/query.ts +292 -0
- package/src/queryDataUtils.ts +50 -0
- package/src/queryMethods/aggregate.test.ts +583 -0
- package/src/queryMethods/aggregate.ts +878 -0
- package/src/queryMethods/callbacks.test.ts +69 -0
- package/src/queryMethods/callbacks.ts +55 -0
- package/src/queryMethods/clear.test.ts +64 -0
- package/src/queryMethods/clear.ts +58 -0
- package/src/queryMethods/columnInfo.test.ts +45 -0
- package/src/queryMethods/columnInfo.ts +67 -0
- package/src/queryMethods/delete.test.ts +135 -0
- package/src/queryMethods/delete.ts +50 -0
- package/src/queryMethods/for.test.ts +57 -0
- package/src/queryMethods/for.ts +99 -0
- package/src/queryMethods/from.test.ts +66 -0
- package/src/queryMethods/from.ts +58 -0
- package/src/queryMethods/get.test.ts +66 -0
- package/src/queryMethods/get.ts +88 -0
- package/src/queryMethods/having.test.ts +247 -0
- package/src/queryMethods/having.ts +99 -0
- package/src/queryMethods/insert.test.ts +555 -0
- package/src/queryMethods/insert.ts +453 -0
- package/src/queryMethods/join.test.ts +150 -0
- package/src/queryMethods/join.ts +508 -0
- package/src/queryMethods/json.test.ts +398 -0
- package/src/queryMethods/json.ts +259 -0
- package/src/queryMethods/log.test.ts +172 -0
- package/src/queryMethods/log.ts +123 -0
- package/src/queryMethods/queryMethods.test.ts +629 -0
- package/src/queryMethods/queryMethods.ts +428 -0
- package/src/queryMethods/select.test.ts +479 -0
- package/src/queryMethods/select.ts +249 -0
- package/src/queryMethods/then.ts +236 -0
- package/src/queryMethods/transaction.test.ts +66 -0
- package/src/queryMethods/transaction.ts +66 -0
- package/src/queryMethods/union.test.ts +59 -0
- package/src/queryMethods/union.ts +89 -0
- package/src/queryMethods/update.test.ts +417 -0
- package/src/queryMethods/update.ts +350 -0
- package/src/queryMethods/upsert.test.ts +56 -0
- package/src/queryMethods/upsert.ts +43 -0
- package/src/queryMethods/where.test.ts +1594 -0
- package/src/queryMethods/where.ts +450 -0
- package/src/queryMethods/window.test.ts +66 -0
- package/src/queryMethods/window.ts +108 -0
- package/src/queryMethods/with.test.ts +191 -0
- package/src/queryMethods/with.ts +92 -0
- package/src/quote.ts +36 -0
- package/src/relations.ts +194 -0
- package/src/sql/aggregate.ts +80 -0
- package/src/sql/columnInfo.ts +22 -0
- package/src/sql/common.ts +42 -0
- package/src/sql/delete.ts +41 -0
- package/src/sql/distinct.ts +19 -0
- package/src/sql/fromAndAs.ts +51 -0
- package/src/sql/having.ts +140 -0
- package/src/sql/index.ts +2 -0
- package/src/sql/insert.ts +102 -0
- package/src/sql/join.ts +242 -0
- package/src/sql/orderBy.ts +41 -0
- package/src/sql/select.ts +153 -0
- package/src/sql/toSql.ts +153 -0
- package/src/sql/truncate.ts +13 -0
- package/src/sql/types.ts +355 -0
- package/src/sql/update.ts +62 -0
- package/src/sql/where.ts +314 -0
- package/src/sql/window.ts +38 -0
- package/src/sql/with.ts +32 -0
- package/src/test-utils.ts +172 -0
- package/src/utils.ts +140 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ColumnInput, ColumnOutput, ColumnType } from './columnType';
|
|
2
|
+
import { Operators } from '../operators';
|
|
3
|
+
import { UnionToIntersection } from '../utils';
|
|
4
|
+
|
|
5
|
+
export type ColumnsShape = Record<string, ColumnType>;
|
|
6
|
+
|
|
7
|
+
export type ColumnShapeOutput<Shape extends ColumnsShape> = {
|
|
8
|
+
[K in keyof Shape]: ColumnOutput<Shape[K]>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type ColumnShapeInput<Shape extends ColumnsShape> = {
|
|
12
|
+
[K in keyof Shape]: ColumnInput<Shape[K]>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class ColumnsObject<Shape extends ColumnsShape> extends ColumnType<
|
|
16
|
+
{ [K in keyof Shape]: Shape[K]['type'] },
|
|
17
|
+
typeof Operators.any
|
|
18
|
+
> {
|
|
19
|
+
dataType = 'object';
|
|
20
|
+
operators = Operators.any;
|
|
21
|
+
|
|
22
|
+
constructor(public shape: Shape) {
|
|
23
|
+
super();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class ArrayOfColumnsObjects<
|
|
28
|
+
Shape extends ColumnsShape,
|
|
29
|
+
> extends ColumnType<
|
|
30
|
+
{ [K in keyof Shape]: Shape[K]['type'] }[],
|
|
31
|
+
typeof Operators.any
|
|
32
|
+
> {
|
|
33
|
+
dataType = 'array';
|
|
34
|
+
operators = Operators.any;
|
|
35
|
+
|
|
36
|
+
constructor(public shape: Shape) {
|
|
37
|
+
super();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type UnionKeyofToOvlds<S, U> = UnionToIntersection<
|
|
42
|
+
U extends keyof S ? (f: U) => void : never
|
|
43
|
+
>;
|
|
44
|
+
|
|
45
|
+
type PopKeyofColumnShapeUnion<
|
|
46
|
+
S extends ColumnsShape,
|
|
47
|
+
U extends keyof S,
|
|
48
|
+
> = UnionKeyofToOvlds<S, U> extends (a: infer A extends keyof S) => void
|
|
49
|
+
? A
|
|
50
|
+
: never;
|
|
51
|
+
|
|
52
|
+
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
|
|
53
|
+
|
|
54
|
+
export type UnionToArray<
|
|
55
|
+
S extends ColumnsShape,
|
|
56
|
+
T extends keyof S,
|
|
57
|
+
A extends [...(keyof S)[]] = [],
|
|
58
|
+
> = IsUnion<T> extends true
|
|
59
|
+
? UnionToArray<
|
|
60
|
+
S,
|
|
61
|
+
Exclude<T, PopKeyofColumnShapeUnion<S, T>>,
|
|
62
|
+
[PopKeyofColumnShapeUnion<S, T>, ...A]
|
|
63
|
+
>
|
|
64
|
+
: [T, ...A];
|
|
65
|
+
|
|
66
|
+
type GetPrimaryKeys<S extends ColumnsShape> = UnionToArray<
|
|
67
|
+
S,
|
|
68
|
+
{ [K in keyof S]: S[K] extends { isPrimaryKey: true } ? K : never }[keyof S]
|
|
69
|
+
>;
|
|
70
|
+
|
|
71
|
+
type GetPrimaryTypes<
|
|
72
|
+
S extends ColumnsShape,
|
|
73
|
+
Keys extends [...(keyof S | string)[]] = GetPrimaryKeys<S>,
|
|
74
|
+
> = GetTypesFromKeys<S, Keys>;
|
|
75
|
+
|
|
76
|
+
type GetTypesFromKeys<
|
|
77
|
+
S extends ColumnsShape,
|
|
78
|
+
T extends [...(keyof S)[]],
|
|
79
|
+
> = T extends [
|
|
80
|
+
infer Head extends keyof S,
|
|
81
|
+
...infer Tail extends [...(keyof S)[]],
|
|
82
|
+
]
|
|
83
|
+
? [GetTypeFromKey<S, Head>, ...GetTypesFromKeys<S, Tail>]
|
|
84
|
+
: [];
|
|
85
|
+
|
|
86
|
+
type GetTypeFromKey<S extends ColumnsShape, T extends keyof S> = S[T]['type'];
|
|
87
|
+
|
|
88
|
+
export class TableSchema<Shape extends ColumnsShape> {
|
|
89
|
+
primaryKeys: string extends keyof Shape ? string[] : GetPrimaryKeys<Shape>;
|
|
90
|
+
primaryTypes!: GetPrimaryTypes<Shape>;
|
|
91
|
+
|
|
92
|
+
constructor(public shape: Shape) {
|
|
93
|
+
this.primaryKeys = Object.entries(this.shape)
|
|
94
|
+
.filter(([, column]) => {
|
|
95
|
+
return column.isPrimaryKey;
|
|
96
|
+
})
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
+
.map(([key]) => key) as any;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { BaseStringData } from './string';
|
|
2
|
+
import { BaseNumberData } from './number';
|
|
3
|
+
|
|
4
|
+
export type ArrayMethods = typeof arrayMethods;
|
|
5
|
+
|
|
6
|
+
export const arrayMethods = {
|
|
7
|
+
min<T extends { data: { min?: number } }, Value extends number>(
|
|
8
|
+
this: T,
|
|
9
|
+
value: Value,
|
|
10
|
+
) {
|
|
11
|
+
this.data.min = value;
|
|
12
|
+
return this as T & { data: Omit<T['data'], 'min'> & { min: Value } };
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
max<T extends { data: { max?: number } }, Value extends number>(
|
|
16
|
+
this: T,
|
|
17
|
+
value: Value,
|
|
18
|
+
) {
|
|
19
|
+
this.data.max = value;
|
|
20
|
+
return this as T & { data: Omit<T['data'], 'max'> & { max: Value } };
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
length<T extends { data: { length?: number } }, Value extends number>(
|
|
24
|
+
this: T,
|
|
25
|
+
value: Value,
|
|
26
|
+
) {
|
|
27
|
+
this.data.length = value;
|
|
28
|
+
return this as T & { data: Omit<T['data'], 'length'> & { length: Value } };
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const stringTypeMethods = <Base extends { data: BaseStringData }>() => ({
|
|
33
|
+
...arrayMethods,
|
|
34
|
+
|
|
35
|
+
email<T extends Base>(this: T) {
|
|
36
|
+
this.data.email = true;
|
|
37
|
+
return this as T & { data: Omit<T['data'], 'email'> & { email: true } };
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
url<T extends Base>(this: T) {
|
|
41
|
+
this.data.url = true;
|
|
42
|
+
return this as T & { data: Omit<T['data'], 'url'> & { url: true } };
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
uuid<T extends Base>(this: T) {
|
|
46
|
+
this.data.uuid = true;
|
|
47
|
+
return this as T & { data: Omit<T['data'], 'uuid'> & { uuid: true } };
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
cuid<T extends Base>(this: T) {
|
|
51
|
+
this.data.cuid = true;
|
|
52
|
+
return this as T & { data: Omit<T['data'], 'cuid'> & { cuid: true } };
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
regex<T extends Base, Value extends RegExp>(this: T, value: Value) {
|
|
56
|
+
this.data.regex = value;
|
|
57
|
+
return this as T & { data: Omit<T['data'], 'regex'> & { regex: Value } };
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
trim<T extends Base>(this: T) {
|
|
61
|
+
this.data.trim = true;
|
|
62
|
+
return this as T & { data: Omit<T['data'], 'cuid'> & { trim: true } };
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export const numberTypeMethods = <Base extends { data: BaseNumberData }>() => ({
|
|
67
|
+
lt<T extends Base, Value extends number>(this: T, value: Value) {
|
|
68
|
+
this.data.lt = value;
|
|
69
|
+
return this as T & { data: Omit<T['data'], 'lt'> & { lt: Value } };
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
lte<T extends Base, Value extends number>(this: T, value: Value) {
|
|
73
|
+
this.data.lte = value;
|
|
74
|
+
return this as T & { data: Omit<T['data'], 'lte'> & { lte: Value } };
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
max<T extends Base, Value extends number>(this: T, value: Value) {
|
|
78
|
+
this.data.lte = value;
|
|
79
|
+
return this as T & { data: Omit<T['data'], 'lte'> & { lte: Value } };
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
gt<T extends Base, Value extends number>(this: T, value: Value) {
|
|
83
|
+
this.data.gt = value;
|
|
84
|
+
return this as T & { data: Omit<T['data'], 'gt'> & { gt: Value } };
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
gte<T extends Base, Value extends number>(this: T, value: Value) {
|
|
88
|
+
this.data.gte = value;
|
|
89
|
+
return this as T & { data: Omit<T['data'], 'gte'> & { gte: Value } };
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
min<T extends Base, Value extends number>(this: T, value: Value) {
|
|
93
|
+
this.data.gte = value;
|
|
94
|
+
return this as T & { data: Omit<T['data'], 'gte'> & { gte: Value } };
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
positive<T extends Base>(this: T) {
|
|
98
|
+
this.data.gt = 0;
|
|
99
|
+
return this as T & { data: Omit<T['data'], 'gt'> & { gt: 0 } };
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
nonNegative<T extends Base>(this: T) {
|
|
103
|
+
this.data.gte = 0;
|
|
104
|
+
return this as T & { data: Omit<T['data'], 'gte'> & { gte: 0 } };
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
negative<T extends Base>(this: T) {
|
|
108
|
+
this.data.lt = 0;
|
|
109
|
+
return this as T & { data: Omit<T['data'], 'lt'> & { lt: 0 } };
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
nonPositive<T extends Base>(this: T) {
|
|
113
|
+
this.data.lte = 0;
|
|
114
|
+
return this as T & { data: Omit<T['data'], 'lte'> & { lte: 0 } };
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
multipleOf<T extends Base, Value extends number>(this: T, value: Value) {
|
|
118
|
+
this.data.multipleOf = value;
|
|
119
|
+
return this as T & {
|
|
120
|
+
data: Omit<T['data'], 'multipleOf'> & { multipleOf: Value };
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
step<T extends Base, Value extends number>(this: T, value: Value) {
|
|
125
|
+
this.data.multipleOf = value;
|
|
126
|
+
return this as T & {
|
|
127
|
+
data: Omit<T['data'], 'multipleOf'> & { multipleOf: Value };
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ColumnType } from './columnType';
|
|
2
|
+
import { Operators } from '../operators';
|
|
3
|
+
import { joinTruthy } from '../utils';
|
|
4
|
+
|
|
5
|
+
// date 4 bytes date (no time of day) 4713 BC 5874897 AD 1 day
|
|
6
|
+
export class DateColumn extends ColumnType<string, typeof Operators.date> {
|
|
7
|
+
dataType = 'date' as const;
|
|
8
|
+
operators = Operators.date;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface DateTimeColumnData {
|
|
12
|
+
precision?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export abstract class DateTimeBaseClass<
|
|
16
|
+
Precision extends number | undefined = undefined,
|
|
17
|
+
> extends ColumnType<string, typeof Operators.date, string | number | Date> {
|
|
18
|
+
data: DateTimeColumnData & { precision: Precision };
|
|
19
|
+
operators = Operators.date;
|
|
20
|
+
|
|
21
|
+
constructor(precision?: Precision) {
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
this.data = { precision } as DateTimeColumnData & { precision: Precision };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
toSQL() {
|
|
28
|
+
return joinTruthy(
|
|
29
|
+
this.dataType,
|
|
30
|
+
this.data.precision !== undefined && `(${this.data.precision})`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export abstract class DateTimeWithTimeZoneBaseClass<
|
|
36
|
+
Precision extends number | undefined = undefined,
|
|
37
|
+
> extends DateTimeBaseClass<Precision> {
|
|
38
|
+
abstract baseDataType: string;
|
|
39
|
+
|
|
40
|
+
toSQL() {
|
|
41
|
+
return joinTruthy(
|
|
42
|
+
this.baseDataType,
|
|
43
|
+
this.data.precision !== undefined && `(${this.data.precision})`,
|
|
44
|
+
' with time zone',
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// timestamp [ (p) ] [ without time zone ] 8 bytes both date and time (no time zone) 4713 BC 294276 AD 1 microsecond
|
|
50
|
+
export class TimestampColumn<
|
|
51
|
+
Precision extends number | undefined = undefined,
|
|
52
|
+
> extends DateTimeBaseClass<Precision> {
|
|
53
|
+
dataType = 'timestamp' as const;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// timestamp [ (p) ] with time zone 8 bytes both date and time, with time zone 4713 BC 294276 AD 1 microsecond
|
|
57
|
+
export class TimestampWithTimeZoneColumn<
|
|
58
|
+
Precision extends number | undefined = undefined,
|
|
59
|
+
> extends DateTimeWithTimeZoneBaseClass<Precision> {
|
|
60
|
+
dataType = 'timestamp with time zone' as const;
|
|
61
|
+
baseDataType = 'timestamp' as const;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// time [ (p) ] [ without time zone ] 8 bytes time of day (no date) 00:00:00 24:00:00 1 microsecond
|
|
65
|
+
export class TimeColumn<
|
|
66
|
+
Precision extends number | undefined = undefined,
|
|
67
|
+
> extends DateTimeBaseClass<Precision> {
|
|
68
|
+
dataType = 'time' as const;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// time [ (p) ] with time zone 12 bytes time of day (no date), with time zone 00:00:00+1559 24:00:00-1559 1 microsecond
|
|
72
|
+
export class TimeWithTimeZoneColumn<
|
|
73
|
+
Precision extends number | undefined = undefined,
|
|
74
|
+
> extends DateTimeWithTimeZoneBaseClass<Precision> {
|
|
75
|
+
dataType = 'time with time zone' as const;
|
|
76
|
+
baseDataType = 'time' as const;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// interval [ fields ] [ (p) ] 16 bytes time interval -178000000 years 178000000 years 1 microsecond
|
|
80
|
+
export class IntervalColumn<
|
|
81
|
+
Fields extends string | undefined = undefined,
|
|
82
|
+
Precision extends number | undefined = undefined,
|
|
83
|
+
> extends ColumnType<string, typeof Operators.date> {
|
|
84
|
+
dataType = 'interval' as const;
|
|
85
|
+
data: DateTimeColumnData & { fields: Fields; precision: Precision };
|
|
86
|
+
operators = Operators.date;
|
|
87
|
+
|
|
88
|
+
constructor(fields?: Fields, precision?: Precision) {
|
|
89
|
+
super();
|
|
90
|
+
|
|
91
|
+
this.data = { fields, precision } as DateTimeColumnData & {
|
|
92
|
+
fields: Fields;
|
|
93
|
+
precision: Precision;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
toSQL() {
|
|
98
|
+
return joinTruthy(
|
|
99
|
+
this.dataType,
|
|
100
|
+
this.data.fields && ` ${this.data.fields}`,
|
|
101
|
+
this.data.precision !== undefined && ` (${this.data.precision})`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ColumnType } from './columnType';
|
|
2
|
+
import { Operators } from '../operators';
|
|
3
|
+
|
|
4
|
+
export class EnumColumn<DataType extends string, Type> extends ColumnType<
|
|
5
|
+
Type,
|
|
6
|
+
typeof Operators.any
|
|
7
|
+
> {
|
|
8
|
+
operators = Operators.any;
|
|
9
|
+
|
|
10
|
+
constructor(public dataType: DataType) {
|
|
11
|
+
super();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './columnType';
|
|
2
|
+
export * from './columnTypes';
|
|
3
|
+
export * from './columnsSchema';
|
|
4
|
+
export * as columnUtils from './utils';
|
|
5
|
+
export * from './number';
|
|
6
|
+
export * from './string';
|
|
7
|
+
export * from './dateTime';
|
|
8
|
+
export * from './boolean';
|
|
9
|
+
export * from './enum';
|
|
10
|
+
export * from './json';
|
|
11
|
+
export * from './array';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
constructType,
|
|
3
|
+
DeepPartial,
|
|
4
|
+
JSONType,
|
|
5
|
+
JSONTypeAny,
|
|
6
|
+
JSONTypeData,
|
|
7
|
+
} from './typeBase';
|
|
8
|
+
import { arrayMethods, ArrayMethods } from '../commonMethods';
|
|
9
|
+
|
|
10
|
+
export type ArrayCardinality = 'many' | 'atLeastOne';
|
|
11
|
+
|
|
12
|
+
type arrayOutputType<
|
|
13
|
+
T extends JSONTypeAny,
|
|
14
|
+
Cardinality extends ArrayCardinality = 'many',
|
|
15
|
+
> = Cardinality extends 'atLeastOne'
|
|
16
|
+
? [T['type'], ...T['type'][]]
|
|
17
|
+
: T['type'][];
|
|
18
|
+
|
|
19
|
+
export interface JSONArray<
|
|
20
|
+
Type extends JSONTypeAny,
|
|
21
|
+
Cardinality extends ArrayCardinality = 'many',
|
|
22
|
+
> extends JSONType<arrayOutputType<Type, Cardinality>, 'array'>,
|
|
23
|
+
ArrayMethods {
|
|
24
|
+
data: JSONTypeData & {
|
|
25
|
+
min?: number;
|
|
26
|
+
max?: number;
|
|
27
|
+
length?: number;
|
|
28
|
+
};
|
|
29
|
+
element: Type;
|
|
30
|
+
deepPartial(): JSONArray<DeepPartial<Type>, Cardinality>;
|
|
31
|
+
nonEmpty(
|
|
32
|
+
this: JSONArray<Type>,
|
|
33
|
+
): JSONArray<Type, 'atLeastOne'> & { data: { min: 1 } };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const array = <Type extends JSONTypeAny>(
|
|
37
|
+
element: Type,
|
|
38
|
+
): JSONArray<Type> => {
|
|
39
|
+
return constructType<JSONArray<Type>>({
|
|
40
|
+
dataType: 'array' as const,
|
|
41
|
+
element,
|
|
42
|
+
deepPartial(this: JSONArray<Type>) {
|
|
43
|
+
return {
|
|
44
|
+
...this,
|
|
45
|
+
element: this.element.deepPartial(),
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
nonEmpty(this: JSONArray<Type>) {
|
|
49
|
+
return this.min(1) as unknown as JSONArray<Type, 'atLeastOne'> & {
|
|
50
|
+
data: { min: 1 };
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
...arrayMethods,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { constructType, JSONType, Primitive } from './typeBase';
|
|
2
|
+
import { JSONObject } from './object';
|
|
3
|
+
import { JSONLiteral } from './literal';
|
|
4
|
+
|
|
5
|
+
export interface JSONDiscriminatedUnion<
|
|
6
|
+
Discriminator extends string,
|
|
7
|
+
Options extends DiscriminatedOptions<Discriminator>,
|
|
8
|
+
> extends JSONType<Options[number]['type'], 'discriminatedUnion'> {
|
|
9
|
+
discriminator: Discriminator;
|
|
10
|
+
options: OptionsMap<Discriminator, Options>;
|
|
11
|
+
// TODO: gave up on deepPartial type
|
|
12
|
+
// deepPartial(): JSONDiscriminatedUnion<
|
|
13
|
+
// Discriminator,
|
|
14
|
+
// {
|
|
15
|
+
// [Index in keyof Options]: {
|
|
16
|
+
// [K in keyof Options[Index]['shape']]: K extends Discriminator
|
|
17
|
+
// ? Options[Index]['shape'][K]
|
|
18
|
+
// : JSONOptional<Options[Index]['shape'][K]>;
|
|
19
|
+
// } extends JSONObject<Record<Discriminator, JSONLiteral<Primitive>>>
|
|
20
|
+
// ? JSONObject<
|
|
21
|
+
// {
|
|
22
|
+
// [K in keyof Options[Index]['shape']]: K extends Discriminator
|
|
23
|
+
// ? Options[Index]['shape'][K]
|
|
24
|
+
// : JSONOptional<Options[Index]['shape'][K]>;
|
|
25
|
+
// },
|
|
26
|
+
// Options[Index]['unknownKeys'],
|
|
27
|
+
// Options[Index]['catchAllType']
|
|
28
|
+
// >
|
|
29
|
+
// : Options[Index];
|
|
30
|
+
// } & {
|
|
31
|
+
// length: Options['length'];
|
|
32
|
+
// }
|
|
33
|
+
// >;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type JSONDiscriminatedObject<Discriminator extends string> = JSONObject<
|
|
37
|
+
Record<Discriminator, JSONLiteral<Primitive>>
|
|
38
|
+
>;
|
|
39
|
+
|
|
40
|
+
type DiscriminatedOptions<Discriminator extends string> = readonly [
|
|
41
|
+
JSONDiscriminatedObject<Discriminator>,
|
|
42
|
+
JSONDiscriminatedObject<Discriminator>,
|
|
43
|
+
...JSONDiscriminatedObject<Discriminator>[],
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
type OptionsMap<
|
|
47
|
+
Discriminator extends string,
|
|
48
|
+
Options extends DiscriminatedOptions<Discriminator>,
|
|
49
|
+
> = Map<Options[number]['shape'][Discriminator]['value'], Options[number]>;
|
|
50
|
+
|
|
51
|
+
export const discriminatedUnion = <
|
|
52
|
+
Discriminator extends string,
|
|
53
|
+
Options extends DiscriminatedOptions<Discriminator>,
|
|
54
|
+
>(
|
|
55
|
+
discriminator: Discriminator,
|
|
56
|
+
options: Options,
|
|
57
|
+
) => {
|
|
58
|
+
const optionsMap: OptionsMap<
|
|
59
|
+
Discriminator,
|
|
60
|
+
DiscriminatedOptions<Discriminator>
|
|
61
|
+
> = new Map();
|
|
62
|
+
|
|
63
|
+
options.forEach((option) => {
|
|
64
|
+
const discriminatorValue = option.shape[discriminator].value;
|
|
65
|
+
optionsMap.set(discriminatorValue, option);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return constructType<JSONDiscriminatedUnion<Discriminator, Options>>({
|
|
69
|
+
dataType: 'discriminatedUnion',
|
|
70
|
+
discriminator,
|
|
71
|
+
options: optionsMap,
|
|
72
|
+
deepPartial(this: JSONDiscriminatedUnion<Discriminator, Options>) {
|
|
73
|
+
const newOptionsMap: OptionsMap<
|
|
74
|
+
Discriminator,
|
|
75
|
+
DiscriminatedOptions<Discriminator>
|
|
76
|
+
> = new Map();
|
|
77
|
+
|
|
78
|
+
optionsMap.forEach((option, key) => {
|
|
79
|
+
const partial =
|
|
80
|
+
option.deepPartial() as unknown as JSONDiscriminatedObject<Discriminator>;
|
|
81
|
+
partial.shape[discriminator] = option.shape[discriminator];
|
|
82
|
+
newOptionsMap.set(key, partial);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
...this,
|
|
87
|
+
options: newOptionsMap,
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { constructType, JSONType } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONEnum<T extends EnumValues>
|
|
4
|
+
extends JSONType<T[number], 'enum'> {
|
|
5
|
+
enum: { [k in T[number]]: k };
|
|
6
|
+
options: T;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type EnumValues = readonly [string, ...string[]];
|
|
10
|
+
|
|
11
|
+
export const arrayToEnum = <T extends string, U extends readonly [T, ...T[]]>(
|
|
12
|
+
items: U,
|
|
13
|
+
) => {
|
|
14
|
+
const obj = {} as { [k in U[number]]: k };
|
|
15
|
+
for (const item of items) {
|
|
16
|
+
obj[item] = item;
|
|
17
|
+
}
|
|
18
|
+
return obj;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const enumType = <T extends readonly [string, ...string[]]>(
|
|
22
|
+
options: T,
|
|
23
|
+
) => {
|
|
24
|
+
return constructType<JSONEnum<T>>({
|
|
25
|
+
dataType: 'enum',
|
|
26
|
+
enum: arrayToEnum(options),
|
|
27
|
+
options,
|
|
28
|
+
});
|
|
29
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { constructType, JSONType } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONInstanceOf<T extends Class>
|
|
4
|
+
extends JSONType<T, 'instanceOf'> {
|
|
5
|
+
class: T;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
type Class = new (...args: any[]) => any;
|
|
10
|
+
|
|
11
|
+
export const instanceOf = <T extends Class>(cls: T) => {
|
|
12
|
+
return constructType<JSONInstanceOf<T>>({
|
|
13
|
+
dataType: 'instanceOf',
|
|
14
|
+
class: cls,
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { constructType, JSONType, JSONTypeAny } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export type JSONIntersection<
|
|
4
|
+
Left extends JSONTypeAny,
|
|
5
|
+
Right extends JSONTypeAny,
|
|
6
|
+
> = JSONType<Left['type'] & Right['type'], 'intersection'> & {
|
|
7
|
+
left: Left;
|
|
8
|
+
right: Right;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const intersection = <
|
|
12
|
+
Left extends JSONTypeAny,
|
|
13
|
+
Right extends JSONTypeAny,
|
|
14
|
+
>(
|
|
15
|
+
left: Left,
|
|
16
|
+
right: Right,
|
|
17
|
+
) => {
|
|
18
|
+
return constructType<JSONIntersection<Left, Right>>({
|
|
19
|
+
dataType: 'intersection',
|
|
20
|
+
left,
|
|
21
|
+
right,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { constructType, JSONType, JSONTypeAny } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONLazy<T extends JSONTypeAny>
|
|
4
|
+
extends JSONType<T['type'], 'lazy'> {
|
|
5
|
+
typeCache?: T;
|
|
6
|
+
getter(): T;
|
|
7
|
+
deepPartial(): JSONLazy<ReturnType<T['deepPartial']>>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const lazy = <T extends JSONTypeAny>(fn: () => T) => {
|
|
11
|
+
constructType<JSONLazy<T>>({
|
|
12
|
+
dataType: 'lazy',
|
|
13
|
+
getter: fn,
|
|
14
|
+
deepPartial(this: JSONLazy<T>) {
|
|
15
|
+
return {
|
|
16
|
+
...this,
|
|
17
|
+
typeCache: undefined,
|
|
18
|
+
getter: () => this.getter().deepPartial(),
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { constructType, JSONType, Primitive } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONLiteral<T extends Primitive>
|
|
4
|
+
extends JSONType<T, 'literal'> {
|
|
5
|
+
value: Primitive;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const literal = <T extends Primitive>(value: T) =>
|
|
9
|
+
constructType<JSONLiteral<T>>({
|
|
10
|
+
dataType: 'literal',
|
|
11
|
+
value,
|
|
12
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { constructType, JSONType, JSONTypeAny } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONMap<Key extends JSONTypeAny, Value extends JSONTypeAny>
|
|
4
|
+
extends JSONType<Map<Key['type'], Value['type']>, 'map'> {
|
|
5
|
+
keyType: Key;
|
|
6
|
+
valueType: Value;
|
|
7
|
+
deepPartial(): JSONMap<
|
|
8
|
+
ReturnType<Key['deepPartial']>,
|
|
9
|
+
ReturnType<Value['deepPartial']>
|
|
10
|
+
>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const map = <Key extends JSONTypeAny, Value extends JSONTypeAny>(
|
|
14
|
+
keyType: Key,
|
|
15
|
+
valueType: Value,
|
|
16
|
+
) => {
|
|
17
|
+
return constructType<JSONMap<Key, Value>>({
|
|
18
|
+
dataType: 'map',
|
|
19
|
+
keyType: keyType,
|
|
20
|
+
valueType: valueType,
|
|
21
|
+
deepPartial(this: JSONMap<Key, Value>) {
|
|
22
|
+
return {
|
|
23
|
+
...this,
|
|
24
|
+
keyType: this.keyType.deepPartial(),
|
|
25
|
+
valueType: this.valueType.deepPartial(),
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { constructType, JSONType } from './typeBase';
|
|
2
|
+
|
|
3
|
+
export interface JSONNativeEnum<T extends EnumLike>
|
|
4
|
+
extends JSONType<T[keyof T], 'nativeEnum'> {
|
|
5
|
+
dataType: 'nativeEnum';
|
|
6
|
+
enum: T;
|
|
7
|
+
options: (number | string)[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type EnumLike = { [k: string]: string | number; [nu: number]: string };
|
|
11
|
+
|
|
12
|
+
export const getValidEnumValues = (obj: EnumLike) => {
|
|
13
|
+
const values: (number | string)[] = [];
|
|
14
|
+
Object.keys(obj).forEach((k) => {
|
|
15
|
+
if (typeof obj[obj[k]] !== 'number' && !values.includes(obj[k])) {
|
|
16
|
+
values.push(obj[k]);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return values;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const nativeEnum = <T extends EnumLike>(givenEnum: T) => {
|
|
23
|
+
const options = getValidEnumValues(givenEnum);
|
|
24
|
+
|
|
25
|
+
return constructType<JSONNativeEnum<T>>({
|
|
26
|
+
dataType: 'nativeEnum',
|
|
27
|
+
enum: givenEnum,
|
|
28
|
+
options,
|
|
29
|
+
});
|
|
30
|
+
};
|