pqb 0.7.13 → 0.8.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +618 -563
- package/dist/index.esm.js +1011 -402
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1014 -401
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/columnSchema/array.test.ts +67 -0
- package/src/columnSchema/array.ts +39 -13
- package/src/columnSchema/boolean.test.ts +17 -0
- package/src/columnSchema/boolean.ts +5 -1
- package/src/columnSchema/columnType.test.ts +230 -107
- package/src/columnSchema/columnType.ts +198 -28
- package/src/columnSchema/columnTypes.ts +28 -15
- package/src/columnSchema/columnsSchema.ts +6 -4
- package/src/columnSchema/commonMethods.ts +11 -4
- package/src/columnSchema/dateTime.test.ts +298 -0
- package/src/columnSchema/dateTime.ts +59 -2
- package/src/columnSchema/enum.test.ts +33 -0
- package/src/columnSchema/enum.ts +11 -1
- package/src/columnSchema/json/array.test.ts +21 -0
- package/src/columnSchema/json/array.ts +27 -13
- package/src/columnSchema/json/discriminatedUnion.test.ts +32 -0
- package/src/columnSchema/json/discriminatedUnion.ts +17 -2
- package/src/columnSchema/json/enum.test.ts +9 -0
- package/src/columnSchema/json/enum.ts +9 -1
- package/src/columnSchema/json/index.ts +19 -19
- package/src/columnSchema/json/instanceOf.test.ts +8 -0
- package/src/columnSchema/json/instanceOf.ts +4 -1
- package/src/columnSchema/json/intersection.test.ts +19 -0
- package/src/columnSchema/json/intersection.ts +9 -1
- package/src/columnSchema/json/lazy.test.ts +22 -0
- package/src/columnSchema/json/lazy.ts +22 -1
- package/src/columnSchema/json/literal.test.ts +7 -0
- package/src/columnSchema/json/literal.ts +12 -1
- package/src/columnSchema/json/map.test.ts +10 -0
- package/src/columnSchema/json/map.ts +21 -1
- package/src/columnSchema/json/nativeEnum.test.ts +10 -0
- package/src/columnSchema/json/nativeEnum.ts +4 -1
- package/src/columnSchema/json/nullable.test.ts +18 -0
- package/src/columnSchema/json/nullish.test.ts +18 -0
- package/src/columnSchema/json/object.test.ts +77 -0
- package/src/columnSchema/json/object.ts +31 -3
- package/src/columnSchema/json/optional.test.ts +18 -0
- package/src/columnSchema/json/record.test.ts +14 -0
- package/src/columnSchema/json/record.ts +12 -1
- package/src/columnSchema/json/scalarTypes.test.ts +133 -0
- package/src/columnSchema/json/scalarTypes.ts +90 -1
- package/src/columnSchema/json/set.test.ts +29 -0
- package/src/columnSchema/json/set.ts +26 -7
- package/src/columnSchema/json/tuple.test.ts +17 -0
- package/src/columnSchema/json/tuple.ts +16 -1
- package/src/columnSchema/json/typeBase.test.ts +123 -0
- package/src/columnSchema/json/typeBase.ts +52 -13
- package/src/columnSchema/json/union.test.ts +10 -0
- package/src/columnSchema/json/union.ts +18 -1
- package/src/columnSchema/json.test.ts +17 -0
- package/src/columnSchema/json.ts +10 -2
- package/src/columnSchema/number.test.ts +176 -0
- package/src/columnSchema/number.ts +48 -1
- package/src/columnSchema/string.test.ts +412 -0
- package/src/columnSchema/string.ts +126 -15
- package/src/columnSchema/timestamps.test.ts +6 -6
- package/src/columnSchema/virtual.ts +4 -0
- package/src/db.ts +1 -1
- package/src/query.ts +1 -1
- package/src/queryMethods/create.ts +6 -6
- package/src/queryMethods/for.ts +3 -3
- package/src/queryMethods/having.ts +1 -1
- package/src/queryMethods/join.ts +4 -4
- package/src/queryMethods/json.ts +1 -1
- package/src/queryMethods/queryMethods.ts +2 -2
- package/src/queryMethods/select.ts +3 -3
- package/src/queryMethods/update.ts +17 -17
- package/src/queryMethods/where.test.ts +1 -1
- package/src/queryMethods/where.ts +4 -4
- package/src/relations.ts +1 -1
- package/src/sql/aggregate.ts +2 -2
- package/src/sql/copy.ts +3 -3
- package/src/sql/delete.ts +5 -5
- package/src/sql/fromAndAs.ts +4 -4
- package/src/sql/having.ts +7 -7
- package/src/sql/insert.ts +5 -5
- package/src/sql/join.ts +16 -16
- package/src/sql/select.ts +6 -6
- package/src/sql/toSql.ts +24 -24
- package/src/sql/update.ts +4 -4
- package/src/sql/where.ts +18 -18
- package/src/utils.test.ts +9 -0
- package/src/utils.ts +3 -0
- package/src/columnSchema/columnTypes.test.ts +0 -527
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { constructType, JSONType, JSONTypeAny } from './typeBase';
|
|
1
|
+
import { constructType, JSONType, JSONTypeAny, toCode } from './typeBase';
|
|
2
2
|
import { BaseNumberData } from '../number';
|
|
3
3
|
import { BaseStringData } from '../string';
|
|
4
4
|
import {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
stringTypeMethods,
|
|
8
8
|
} from '../commonMethods';
|
|
9
9
|
import { DateColumnData } from '../dateTime';
|
|
10
|
+
import { singleQuote } from '../../utils';
|
|
10
11
|
|
|
11
12
|
export type JSONAny = JSONTypeAny & {
|
|
12
13
|
dataType: 'any';
|
|
@@ -14,6 +15,9 @@ export type JSONAny = JSONTypeAny & {
|
|
|
14
15
|
const any = () => {
|
|
15
16
|
return constructType<JSONAny>({
|
|
16
17
|
dataType: 'any',
|
|
18
|
+
toCode(this: JSONAny, t: string) {
|
|
19
|
+
return toCode(this, t, `${t}.any()`);
|
|
20
|
+
},
|
|
17
21
|
});
|
|
18
22
|
};
|
|
19
23
|
|
|
@@ -23,6 +27,9 @@ export type JSONBigInt = JSONType<bigint, 'bigint'> & {
|
|
|
23
27
|
const bigIntMethods = {
|
|
24
28
|
dataType: 'bigint' as const,
|
|
25
29
|
...numberTypeMethods,
|
|
30
|
+
toCode(this: JSONTypeAny, t: string) {
|
|
31
|
+
return toCode(this, t, `${t}.bigint()`);
|
|
32
|
+
},
|
|
26
33
|
};
|
|
27
34
|
const bigint = () => {
|
|
28
35
|
return constructType<JSONBigInt>(bigIntMethods);
|
|
@@ -32,6 +39,9 @@ export type JSONBoolean = JSONType<boolean, 'boolean'>;
|
|
|
32
39
|
const boolean = () => {
|
|
33
40
|
return constructType<JSONBoolean>({
|
|
34
41
|
dataType: 'boolean',
|
|
42
|
+
toCode(this: JSONBoolean, t: string) {
|
|
43
|
+
return toCode(this, t, `${t}.boolean()`);
|
|
44
|
+
},
|
|
35
45
|
});
|
|
36
46
|
};
|
|
37
47
|
|
|
@@ -39,6 +49,9 @@ export type JSONNaN = JSONType<number, 'nan'>;
|
|
|
39
49
|
const nan = () => {
|
|
40
50
|
return constructType<JSONNaN>({
|
|
41
51
|
dataType: 'nan',
|
|
52
|
+
toCode(this: JSONNaN, t: string) {
|
|
53
|
+
return toCode(this, t, `${t}.nan()`);
|
|
54
|
+
},
|
|
42
55
|
});
|
|
43
56
|
};
|
|
44
57
|
|
|
@@ -46,6 +59,9 @@ export type JSONNever = JSONType<unknown, 'never'>;
|
|
|
46
59
|
const never = () => {
|
|
47
60
|
return constructType<JSONNever>({
|
|
48
61
|
dataType: 'never',
|
|
62
|
+
toCode(this: JSONNever, t: string) {
|
|
63
|
+
return toCode(this, t, `${t}.never()`);
|
|
64
|
+
},
|
|
49
65
|
});
|
|
50
66
|
};
|
|
51
67
|
|
|
@@ -53,6 +69,9 @@ export type JSONNull = JSONType<null, 'null'>;
|
|
|
53
69
|
const nullType = () => {
|
|
54
70
|
return constructType<JSONNull>({
|
|
55
71
|
dataType: 'null',
|
|
72
|
+
toCode(this: JSONNull, t: string) {
|
|
73
|
+
return toCode(this, t, `${t}.null()`);
|
|
74
|
+
},
|
|
56
75
|
});
|
|
57
76
|
};
|
|
58
77
|
|
|
@@ -62,6 +81,24 @@ export type JSONNumber = JSONType<number, 'number'> & {
|
|
|
62
81
|
const numberMethods = {
|
|
63
82
|
...numberTypeMethods,
|
|
64
83
|
dataType: 'number' as const,
|
|
84
|
+
toCode(
|
|
85
|
+
this: JSONType<number, 'number'> & {
|
|
86
|
+
data: BaseNumberData;
|
|
87
|
+
},
|
|
88
|
+
t: string,
|
|
89
|
+
) {
|
|
90
|
+
let code = `${t}.number()`;
|
|
91
|
+
|
|
92
|
+
if (this.data.gte !== undefined) code += `.min(${this.data.gte})`;
|
|
93
|
+
if (this.data.gt !== undefined) code += `.gt(${this.data.gt})`;
|
|
94
|
+
if (this.data.lte !== undefined) code += `.max(${this.data.lte})`;
|
|
95
|
+
if (this.data.lt !== undefined) code += `.lt(${this.data.lt})`;
|
|
96
|
+
if (this.data.multipleOf !== undefined)
|
|
97
|
+
code += `.step(${this.data.multipleOf})`;
|
|
98
|
+
if (this.data.int) code += `.int()`;
|
|
99
|
+
|
|
100
|
+
return toCode(this, t, code);
|
|
101
|
+
},
|
|
65
102
|
};
|
|
66
103
|
const number = () => {
|
|
67
104
|
return constructType<JSONNumber>(numberMethods);
|
|
@@ -73,6 +110,21 @@ export type JSONDate = JSONType<Date, 'date'> & {
|
|
|
73
110
|
const dateMethods = {
|
|
74
111
|
...dateTypeMethods,
|
|
75
112
|
dataType: 'date' as const,
|
|
113
|
+
toCode(
|
|
114
|
+
this: JSONType<Date, 'date'> & {
|
|
115
|
+
data: DateColumnData;
|
|
116
|
+
},
|
|
117
|
+
t: string,
|
|
118
|
+
) {
|
|
119
|
+
let code = `${t}.date()`;
|
|
120
|
+
|
|
121
|
+
if (this.data.min)
|
|
122
|
+
code += `.min(new Date('${this.data.min.toISOString()}'))`;
|
|
123
|
+
if (this.data.max)
|
|
124
|
+
code += `.max(new Date('${this.data.max.toISOString()}'))`;
|
|
125
|
+
|
|
126
|
+
return toCode(this, t, code);
|
|
127
|
+
},
|
|
76
128
|
};
|
|
77
129
|
const date = () => {
|
|
78
130
|
return constructType<JSONDate>(dateMethods);
|
|
@@ -84,6 +136,34 @@ export type JSONString = JSONType<string, 'string'> & {
|
|
|
84
136
|
const stringMethods = {
|
|
85
137
|
...stringTypeMethods(),
|
|
86
138
|
dataType: 'string' as const,
|
|
139
|
+
toCode(
|
|
140
|
+
this: JSONType<string, 'string'> & {
|
|
141
|
+
data: BaseStringData;
|
|
142
|
+
},
|
|
143
|
+
t: string,
|
|
144
|
+
) {
|
|
145
|
+
let code = `${t}.string()`;
|
|
146
|
+
|
|
147
|
+
const { min, isNonEmpty } = this.data;
|
|
148
|
+
|
|
149
|
+
if (min !== undefined && (!isNonEmpty || (isNonEmpty && min !== 1)))
|
|
150
|
+
code += `.min(${min})`;
|
|
151
|
+
|
|
152
|
+
if (this.data.max !== undefined) code += `.max(${this.data.max})`;
|
|
153
|
+
if (this.data.length !== undefined) code += `.length(${this.data.length})`;
|
|
154
|
+
if (this.data.email !== undefined) code += `.email()`;
|
|
155
|
+
if (this.data.url !== undefined) code += `.url()`;
|
|
156
|
+
if (this.data.uuid !== undefined) code += `.uuid()`;
|
|
157
|
+
if (this.data.cuid !== undefined) code += `.cuid()`;
|
|
158
|
+
if (this.data.regex) code += `.regex(${this.data.regex.toString()})`;
|
|
159
|
+
if (this.data.startsWith !== undefined)
|
|
160
|
+
code += `.startsWith(${singleQuote(this.data.startsWith)})`;
|
|
161
|
+
if (this.data.endsWith !== undefined)
|
|
162
|
+
code += `.endsWith(${singleQuote(this.data.endsWith)})`;
|
|
163
|
+
if (this.data.cuid !== undefined) code += `.trim()`;
|
|
164
|
+
|
|
165
|
+
return toCode(this, t, code);
|
|
166
|
+
},
|
|
87
167
|
};
|
|
88
168
|
const string = () => {
|
|
89
169
|
return constructType<JSONString>(stringMethods);
|
|
@@ -93,6 +173,9 @@ export type JSONUndefined = JSONType<undefined, 'undefined'>;
|
|
|
93
173
|
const undefinedType = () => {
|
|
94
174
|
return constructType<JSONUndefined>({
|
|
95
175
|
dataType: 'undefined',
|
|
176
|
+
toCode(this: JSONUndefined, t: string) {
|
|
177
|
+
return toCode(this, t, `${t}.undefined()`);
|
|
178
|
+
},
|
|
96
179
|
});
|
|
97
180
|
};
|
|
98
181
|
|
|
@@ -100,6 +183,9 @@ export type JSONUnknown = JSONType<unknown, 'unknown'>;
|
|
|
100
183
|
const unknown = () => {
|
|
101
184
|
return constructType<JSONUnknown>({
|
|
102
185
|
dataType: 'unknown',
|
|
186
|
+
toCode(this: JSONUnknown, t: string) {
|
|
187
|
+
return toCode(this, t, `${t}.unknown()`);
|
|
188
|
+
},
|
|
103
189
|
});
|
|
104
190
|
};
|
|
105
191
|
|
|
@@ -107,6 +193,9 @@ export type JSONVoid = JSONType<void, 'void'>;
|
|
|
107
193
|
const voidType = () => {
|
|
108
194
|
return constructType<JSONVoid>({
|
|
109
195
|
dataType: 'void',
|
|
196
|
+
toCode(this: JSONVoid, t: string) {
|
|
197
|
+
return toCode(this, t, `${t}.void()`);
|
|
198
|
+
},
|
|
110
199
|
});
|
|
111
200
|
};
|
|
112
201
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { set } from './set';
|
|
2
|
+
import { scalarTypes } from './scalarTypes';
|
|
3
|
+
|
|
4
|
+
const { number } = scalarTypes;
|
|
5
|
+
|
|
6
|
+
describe('set', () => {
|
|
7
|
+
it('should have toCode', () => {
|
|
8
|
+
expect(set(number()).toCode('t')).toEqual(['t.set(', 't.number()', ')']);
|
|
9
|
+
|
|
10
|
+
expect(set(number()).deepPartial().toCode('t')).toEqual([
|
|
11
|
+
't.set(',
|
|
12
|
+
't.number().optional()',
|
|
13
|
+
')',
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
expect(set(number()).nonEmpty().toCode('t')).toEqual([
|
|
17
|
+
't.set(',
|
|
18
|
+
't.number()',
|
|
19
|
+
')',
|
|
20
|
+
'.nonEmpty()',
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
expect(set(number()).min(1).max(10).size(15).toCode('t')).toEqual([
|
|
24
|
+
't.set(',
|
|
25
|
+
't.number()',
|
|
26
|
+
').min(1).max(10).size(15)',
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
constructType,
|
|
3
|
+
JSONType,
|
|
4
|
+
JSONTypeAny,
|
|
5
|
+
JSONTypeData,
|
|
6
|
+
toCode,
|
|
7
|
+
} from './typeBase';
|
|
2
8
|
import { SetMethods, setMethods } from '../commonMethods';
|
|
9
|
+
import { toArray } from '../../utils';
|
|
3
10
|
|
|
4
11
|
export interface JSONSet<Value extends JSONTypeAny>
|
|
5
12
|
extends JSONType<Set<Value['type']>, 'set'>,
|
|
@@ -11,24 +18,36 @@ export interface JSONSet<Value extends JSONTypeAny>
|
|
|
11
18
|
};
|
|
12
19
|
valueType: Value;
|
|
13
20
|
deepPartial(): JSONSet<ReturnType<Value['deepPartial']>>;
|
|
14
|
-
nonEmpty(this: JSONSet<Value>): JSONSet<Value> & { data: { min: 1 } };
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export const set = <Value extends JSONTypeAny>(valueType: Value) => {
|
|
18
24
|
return constructType<JSONSet<Value>>({
|
|
19
25
|
dataType: 'set',
|
|
20
26
|
valueType,
|
|
27
|
+
toCode(this: JSONSet<Value>, t: string) {
|
|
28
|
+
let append = ')';
|
|
29
|
+
|
|
30
|
+
const { min, max, size, isNonEmpty } = this.data;
|
|
31
|
+
|
|
32
|
+
if (min !== undefined && (!isNonEmpty || (isNonEmpty && min !== 1)))
|
|
33
|
+
append += `.min(${min})`;
|
|
34
|
+
|
|
35
|
+
if (max !== undefined) append += `.max(${max})`;
|
|
36
|
+
|
|
37
|
+
if (size !== undefined) append += `.size(${size})`;
|
|
38
|
+
|
|
39
|
+
return toCode(this, t, [
|
|
40
|
+
`${t}.set(`,
|
|
41
|
+
...toArray(this.valueType.toCode(t)),
|
|
42
|
+
append,
|
|
43
|
+
]);
|
|
44
|
+
},
|
|
21
45
|
deepPartial(this: JSONSet<Value>) {
|
|
22
46
|
return {
|
|
23
47
|
...this,
|
|
24
48
|
valueType: this.valueType.deepPartial(),
|
|
25
49
|
};
|
|
26
50
|
},
|
|
27
|
-
nonEmpty(this: JSONSet<Value>) {
|
|
28
|
-
return this.min(1) as unknown as JSONSet<Value> & {
|
|
29
|
-
data: { min: 1 };
|
|
30
|
-
};
|
|
31
|
-
},
|
|
32
51
|
...setMethods,
|
|
33
52
|
});
|
|
34
53
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { tuple } from './tuple';
|
|
2
|
+
import { scalarTypes } from './scalarTypes';
|
|
3
|
+
|
|
4
|
+
describe('tuple', () => {
|
|
5
|
+
it('should have toCode', () => {
|
|
6
|
+
expect(
|
|
7
|
+
tuple([scalarTypes.string(), scalarTypes.number()]).toCode('t'),
|
|
8
|
+
).toBe('t.tuple([t.string(), t.number()])');
|
|
9
|
+
|
|
10
|
+
expect(
|
|
11
|
+
tuple(
|
|
12
|
+
[scalarTypes.string(), scalarTypes.number()],
|
|
13
|
+
scalarTypes.boolean(),
|
|
14
|
+
).toCode('t'),
|
|
15
|
+
).toBe('t.tuple([t.string(), t.number()], t.boolean())');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
constructType,
|
|
3
|
+
DeepPartial,
|
|
4
|
+
JSONType,
|
|
5
|
+
JSONTypeAny,
|
|
6
|
+
toCode,
|
|
7
|
+
} from './typeBase';
|
|
2
8
|
|
|
3
9
|
export interface JSONTuple<
|
|
4
10
|
T extends JSONTupleItems | [] = JSONTupleItems,
|
|
@@ -39,6 +45,15 @@ export const tuple = <
|
|
|
39
45
|
dataType: 'tuple',
|
|
40
46
|
items,
|
|
41
47
|
restType: rest,
|
|
48
|
+
toCode(this: JSONTuple<T, Rest>, t: string) {
|
|
49
|
+
return toCode(
|
|
50
|
+
this,
|
|
51
|
+
t,
|
|
52
|
+
`${t}.tuple([${this.items.map((item) => item.toCode(t)).join(', ')}]${
|
|
53
|
+
this.restType ? `, ${this.restType.toCode(t)}` : ''
|
|
54
|
+
})`,
|
|
55
|
+
);
|
|
56
|
+
},
|
|
42
57
|
rest<Rest extends JSONTypeAny | null>(rest: Rest): JSONTuple<T, Rest> {
|
|
43
58
|
return {
|
|
44
59
|
...this,
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { scalarTypes } from './scalarTypes';
|
|
2
|
+
|
|
3
|
+
const { string, number } = scalarTypes;
|
|
4
|
+
|
|
5
|
+
describe('typeBase', () => {
|
|
6
|
+
describe('optional', () => {
|
|
7
|
+
it('should have toCode', () => {
|
|
8
|
+
expect(string().optional().toCode('t')).toBe('t.string().optional()');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('required', () => {
|
|
13
|
+
it('should have toCode', () => {
|
|
14
|
+
expect(string().optional().required().toCode('t')).toBe('t.string()');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('nullable', () => {
|
|
19
|
+
it('should have toCode', () => {
|
|
20
|
+
expect(string().nullable().toCode('t')).toBe('t.string().nullable()');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('notNullable', () => {
|
|
25
|
+
it('should have toCode', () => {
|
|
26
|
+
expect(string().nullable().notNullable().toCode('t')).toBe('t.string()');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('nullish', () => {
|
|
31
|
+
it('should have toCode', () => {
|
|
32
|
+
expect(string().nullish().toCode('t')).toBe('t.string().nullish()');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('notNullish', () => {
|
|
37
|
+
it('should have toCode', () => {
|
|
38
|
+
expect(string().nullish().notNullish().toCode('t')).toBe('t.string()');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('deepPartial', () => {
|
|
43
|
+
it('should have toCode', () => {
|
|
44
|
+
expect(string().deepPartial().toCode('t')).toBe('t.string().optional()');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('transform', () => {
|
|
49
|
+
it('should have toCode', () => {
|
|
50
|
+
expect(
|
|
51
|
+
string()
|
|
52
|
+
.transform((s) => s)
|
|
53
|
+
.toCode('t'),
|
|
54
|
+
).toEqual(['t.string()', '.transform((s)=>s)']);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('to', () => {
|
|
59
|
+
it('should have toCode', () => {
|
|
60
|
+
expect(
|
|
61
|
+
string()
|
|
62
|
+
.to((s) => parseInt(s), number())
|
|
63
|
+
.toCode('t'),
|
|
64
|
+
).toEqual(['t.string()', '.to((s)=>parseInt(s), ', 't.number()', ')']);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('refine', () => {
|
|
69
|
+
it('should have toCode', () => {
|
|
70
|
+
expect(
|
|
71
|
+
string()
|
|
72
|
+
.refine((s) => s.length > 0)
|
|
73
|
+
.toCode('t'),
|
|
74
|
+
).toEqual(['t.string()', '.refine((s)=>s.length > 0)']);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('superRefine', () => {
|
|
79
|
+
it('should have toCode', () => {
|
|
80
|
+
expect(
|
|
81
|
+
string()
|
|
82
|
+
.superRefine((s) => s)
|
|
83
|
+
.toCode('t'),
|
|
84
|
+
).toEqual(['t.string()', '.superRefine((s)=>s)']);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('and', () => {
|
|
89
|
+
it('should have toCode', () => {
|
|
90
|
+
expect(string().and(number()).toCode('t')).toEqual([
|
|
91
|
+
't.string()',
|
|
92
|
+
'.and(',
|
|
93
|
+
't.number()',
|
|
94
|
+
')',
|
|
95
|
+
]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('or', () => {
|
|
100
|
+
it('should have toCode', () => {
|
|
101
|
+
expect(string().or(number()).toCode('t')).toEqual([
|
|
102
|
+
't.string()',
|
|
103
|
+
'.or(',
|
|
104
|
+
't.number()',
|
|
105
|
+
')',
|
|
106
|
+
]);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('default', () => {
|
|
111
|
+
it('should have toCode', () => {
|
|
112
|
+
expect(string().default('value').toCode('t')).toBe(
|
|
113
|
+
't.string().default("value")',
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('array', () => {
|
|
119
|
+
it('should have toCode', () => {
|
|
120
|
+
expect(string().array().toCode('t')).toEqual(['t.string()', '.array()']);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -9,10 +9,16 @@ import { JSONNotNullish, JSONNullish, notNullish, nullish } from './nullish';
|
|
|
9
9
|
import { intersection, JSONIntersection } from './intersection';
|
|
10
10
|
import { array, JSONArray } from './array';
|
|
11
11
|
import { union } from './union';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Code,
|
|
14
|
+
ColumnChain,
|
|
15
|
+
columnChainToCode,
|
|
16
|
+
ColumnData,
|
|
17
|
+
ValidationContext,
|
|
18
|
+
} from '../columnType';
|
|
13
19
|
|
|
14
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
-
export type JSONTypeAny = JSONType<any
|
|
21
|
+
export type JSONTypeAny = JSONType<any>;
|
|
16
22
|
|
|
17
23
|
export type DeepPartial<T extends JSONTypeAny> = ReturnType<
|
|
18
24
|
JSONTypeAny['deepPartial']
|
|
@@ -23,6 +29,8 @@ export type DeepPartial<T extends JSONTypeAny> = ReturnType<
|
|
|
23
29
|
export type JSONTypeData = ColumnData & {
|
|
24
30
|
optional?: true;
|
|
25
31
|
nullable?: true;
|
|
32
|
+
isDeepPartial?: true;
|
|
33
|
+
isNonEmpty?: true;
|
|
26
34
|
};
|
|
27
35
|
|
|
28
36
|
export type Primitive = string | number | bigint | boolean | null | undefined;
|
|
@@ -31,12 +39,9 @@ export type JSONType<Type, DataType extends string = string> = {
|
|
|
31
39
|
type: Type;
|
|
32
40
|
data: JSONTypeData;
|
|
33
41
|
dataType: DataType;
|
|
34
|
-
chain:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| ['refine', (input: unknown) => unknown]
|
|
38
|
-
| ['superRefine', (input: unknown, ctx: ValidationContext) => unknown]
|
|
39
|
-
)[];
|
|
42
|
+
chain: ColumnChain;
|
|
43
|
+
|
|
44
|
+
toCode(t: string): Code;
|
|
40
45
|
|
|
41
46
|
optional<T extends JSONTypeAny>(this: T): JSONOptional<T>;
|
|
42
47
|
required<T extends JSONTypeAny>(this: T): JSONRequired<T>;
|
|
@@ -90,6 +95,32 @@ export type JSONType<Type, DataType extends string = string> = {
|
|
|
90
95
|
array<T extends JSONTypeAny>(this: T): JSONArray<T>;
|
|
91
96
|
};
|
|
92
97
|
|
|
98
|
+
export const toCode = (type: JSONTypeAny, t: string, code: Code) => {
|
|
99
|
+
let append = '';
|
|
100
|
+
|
|
101
|
+
if (type.data.nullable && type.data.optional) {
|
|
102
|
+
append += '.nullish()';
|
|
103
|
+
} else if (type.data.nullable) {
|
|
104
|
+
append += '.nullable()';
|
|
105
|
+
} else if (type.data.optional) {
|
|
106
|
+
append += '.optional()';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (type.data.isDeepPartial) {
|
|
110
|
+
append += '.deepPartial()';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (type.data.isNonEmpty) {
|
|
114
|
+
append += '.nonEmpty()';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (type.data.default) {
|
|
118
|
+
append += `.default(${JSON.stringify(type.data.default)})`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return columnChainToCode(type.chain, t, code, append);
|
|
122
|
+
};
|
|
123
|
+
|
|
93
124
|
const baseTypeMethods: JSONTypeAny = {
|
|
94
125
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
126
|
type: undefined as any,
|
|
@@ -97,6 +128,10 @@ const baseTypeMethods: JSONTypeAny = {
|
|
|
97
128
|
dataType: 'any',
|
|
98
129
|
chain: [],
|
|
99
130
|
|
|
131
|
+
toCode() {
|
|
132
|
+
throw new Error('toCode is not implemented');
|
|
133
|
+
},
|
|
134
|
+
|
|
100
135
|
optional<T extends JSONTypeAny>(this: T) {
|
|
101
136
|
return optional(this);
|
|
102
137
|
},
|
|
@@ -122,7 +157,7 @@ const baseTypeMethods: JSONTypeAny = {
|
|
|
122
157
|
},
|
|
123
158
|
|
|
124
159
|
deepPartial() {
|
|
125
|
-
return this;
|
|
160
|
+
return this.optional();
|
|
126
161
|
},
|
|
127
162
|
|
|
128
163
|
transform<T extends JSONTypeAny, Transformed>(
|
|
@@ -135,11 +170,15 @@ const baseTypeMethods: JSONTypeAny = {
|
|
|
135
170
|
};
|
|
136
171
|
},
|
|
137
172
|
|
|
138
|
-
to
|
|
173
|
+
to<T extends JSONTypeAny, ToType extends JSONTypeAny>(
|
|
174
|
+
this: T,
|
|
175
|
+
fn: (input: T['type']) => ToType['type'] | undefined,
|
|
176
|
+
type: ToType,
|
|
177
|
+
): ToType {
|
|
139
178
|
return {
|
|
140
|
-
...
|
|
179
|
+
...this,
|
|
141
180
|
chain: [...this.chain, ['to', fn, type], ...type.chain],
|
|
142
|
-
};
|
|
181
|
+
} as unknown as ToType;
|
|
143
182
|
},
|
|
144
183
|
|
|
145
184
|
refine(check) {
|
|
@@ -177,7 +216,7 @@ const baseTypeMethods: JSONTypeAny = {
|
|
|
177
216
|
};
|
|
178
217
|
|
|
179
218
|
type BaseTypeProps<T extends JSONTypeAny> = Omit<
|
|
180
|
-
JSONType<T['type']
|
|
219
|
+
JSONType<T['type']>,
|
|
181
220
|
'dataType'
|
|
182
221
|
>;
|
|
183
222
|
export type OwnTypeProps<T extends JSONTypeAny> = Omit<
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { union } from './union';
|
|
2
|
+
import { scalarTypes } from './scalarTypes';
|
|
3
|
+
|
|
4
|
+
describe('union', () => {
|
|
5
|
+
it('should have toCode', () => {
|
|
6
|
+
expect(
|
|
7
|
+
union([scalarTypes.string(), scalarTypes.number()]).toCode('t'),
|
|
8
|
+
).toEqual(['t.string()', '.or(', 't.number()', ')']);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { constructType, JSONType, JSONTypeAny } from './typeBase';
|
|
1
|
+
import { constructType, JSONType, JSONTypeAny, toCode } from './typeBase';
|
|
2
|
+
import { toArray } from '../../utils';
|
|
2
3
|
|
|
3
4
|
export interface JSONUnion<
|
|
4
5
|
T extends [JSONTypeAny, JSONTypeAny, ...JSONTypeAny[]],
|
|
@@ -12,5 +13,21 @@ export const union = <T extends [JSONTypeAny, JSONTypeAny, ...JSONTypeAny[]]>(
|
|
|
12
13
|
return constructType<JSONUnion<T>>({
|
|
13
14
|
dataType: 'union',
|
|
14
15
|
types,
|
|
16
|
+
toCode(this: JSONUnion<T>, t: string) {
|
|
17
|
+
const last = this.types.length - 1;
|
|
18
|
+
return toCode(
|
|
19
|
+
this,
|
|
20
|
+
t,
|
|
21
|
+
this.types.flatMap((type, i) => {
|
|
22
|
+
const item = [...toArray(type.toCode(t))];
|
|
23
|
+
if (i < last) {
|
|
24
|
+
item.push(`${i > 0 ? ')' : ''}.or(`);
|
|
25
|
+
} else {
|
|
26
|
+
item.push(')');
|
|
27
|
+
}
|
|
28
|
+
return item;
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
},
|
|
15
32
|
});
|
|
16
33
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSONColumn, JSONTextColumn } from './json';
|
|
2
|
+
|
|
3
|
+
describe('json columns', () => {
|
|
4
|
+
describe('json', () => {
|
|
5
|
+
it('should have toCode', () => {
|
|
6
|
+
expect(new JSONColumn((t) => t.string()).toCode('t')).toBe(
|
|
7
|
+
't.json((t) => t.string())',
|
|
8
|
+
);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('jsonText', () => {
|
|
13
|
+
it('should have toCode', () => {
|
|
14
|
+
expect(new JSONTextColumn().toCode('t')).toBe('t.jsonText()');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
});
|
package/src/columnSchema/json.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnData, ColumnType } from './columnType';
|
|
1
|
+
import { Code, columnCode, ColumnData, ColumnType } from './columnType';
|
|
2
2
|
import { Operators } from '../columnsOperators';
|
|
3
3
|
import {
|
|
4
4
|
scalarTypes,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
tuple,
|
|
21
21
|
union,
|
|
22
22
|
JSONTypeAny,
|
|
23
|
-
} from './json
|
|
23
|
+
} from './json';
|
|
24
24
|
|
|
25
25
|
export * from './json/index';
|
|
26
26
|
|
|
@@ -60,9 +60,17 @@ export class JSONColumn<
|
|
|
60
60
|
typeof schemaOrFn === 'function' ? schemaOrFn(jsonTypes) : schemaOrFn;
|
|
61
61
|
this.data = { schema };
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
toCode(t: string): Code {
|
|
65
|
+
const { schema } = this.data;
|
|
66
|
+
return columnCode(this, t, `${t}.json((t) => ${schema.toCode('t')})`);
|
|
67
|
+
}
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
export class JSONTextColumn extends ColumnType<string, typeof Operators.text> {
|
|
66
71
|
dataType = 'json' as const;
|
|
67
72
|
operators = Operators.text;
|
|
73
|
+
toCode(t: string): Code {
|
|
74
|
+
return columnCode(this, t, `${t}.jsonText()`);
|
|
75
|
+
}
|
|
68
76
|
}
|