@cleverbrush/schema 0.0.17 → 1.0.0-beta.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/README.md +213 -163
- package/package.json +3 -3
- package/src/builders/ArraySchemaBuilder.test.ts +270 -0
- package/src/builders/ArraySchemaBuilder.ts +381 -0
- package/src/builders/BooleanSchemaBuilder.test.ts +196 -0
- package/src/builders/BooleanSchemaBuilder.ts +155 -0
- package/src/builders/FunctionSchemaBuilder.test.ts +134 -0
- package/src/builders/FunctionSchemaBuilder.ts +109 -0
- package/src/builders/NumberSchemaBuilder.test.ts +493 -0
- package/src/builders/NumberSchemaBuilder.ts +789 -0
- package/src/builders/ObjectSchemaBuilder.test.ts +657 -0
- package/src/builders/ObjectSchemaBuilder.ts +794 -0
- package/src/builders/SchemaBuilder.test.ts +73 -0
- package/src/builders/SchemaBuilder.ts +135 -0
- package/src/builders/StringSchemaBuilder.test.ts +318 -0
- package/src/builders/StringSchemaBuilder.ts +392 -0
- package/src/builders/UnionSchemaBuilder.test.ts +162 -0
- package/src/builders/UnionSchemaBuilder.ts +154 -0
- package/src/defaultSchemas.ts +44 -0
- package/src/index.ts +58 -190
- package/src/schema.ts +827 -0
- package/src/schemaRegistry.builders.test.ts +1393 -0
- package/src/schemaRegistry.test.ts +118 -0
- package/src/schemaRegistry.ts +461 -0
- package/src/validators/validateArray.ts +4 -7
- package/src/validators/validateBoolean.ts +2 -11
- package/src/validators/validateFunction.ts +25 -0
- package/src/validators/validateNumber.ts +2 -7
- package/src/validators/validateObject.ts +32 -21
- package/src/validators/validateString.ts +2 -7
- package/src/validators/validateUnion.ts +36 -0
- package/dist/index.d.ts +0 -94
- package/dist/index.js +0 -9
- package/dist/schemaValidator.d.ts +0 -16
- package/dist/schemaValidator.js +0 -234
- package/dist/validators/validateArray.d.ts +0 -2
- package/dist/validators/validateArray.js +0 -60
- package/dist/validators/validateBoolean.d.ts +0 -2
- package/dist/validators/validateBoolean.js +0 -33
- package/dist/validators/validateNumber.d.ts +0 -2
- package/dist/validators/validateNumber.js +0 -69
- package/dist/validators/validateObject.d.ts +0 -2
- package/dist/validators/validateObject.js +0 -73
- package/dist/validators/validateString.d.ts +0 -2
- package/dist/validators/validateString.js +0 -50
- package/src/schemaValidator.test.ts +0 -1656
- package/src/schemaValidator.ts +0 -367
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { ISchemaBuilder, SchemaBuilder } from './SchemaBuilder.js';
|
|
2
|
+
import { Schema, Validator } from '../schema.js';
|
|
3
|
+
import { defaultSchemas } from '../defaultSchemas.js';
|
|
4
|
+
|
|
5
|
+
export interface IStringSchemaBuilder<
|
|
6
|
+
TRequired extends boolean = true,
|
|
7
|
+
TNullable extends boolean = false,
|
|
8
|
+
TMinLength extends number | undefined = undefined,
|
|
9
|
+
TMaxLength extends number | undefined = undefined,
|
|
10
|
+
TEqualsTo extends string | undefined = undefined
|
|
11
|
+
> extends ISchemaBuilder<TRequired, TNullable> {
|
|
12
|
+
optional(): IStringSchemaBuilder<
|
|
13
|
+
false,
|
|
14
|
+
TNullable,
|
|
15
|
+
TMinLength,
|
|
16
|
+
TMaxLength,
|
|
17
|
+
TEqualsTo
|
|
18
|
+
>;
|
|
19
|
+
required(): IStringSchemaBuilder<
|
|
20
|
+
true,
|
|
21
|
+
TNullable,
|
|
22
|
+
TMinLength,
|
|
23
|
+
TMaxLength,
|
|
24
|
+
TEqualsTo
|
|
25
|
+
>;
|
|
26
|
+
nullable(): IStringSchemaBuilder<
|
|
27
|
+
TRequired,
|
|
28
|
+
true,
|
|
29
|
+
TMinLength,
|
|
30
|
+
TMaxLength,
|
|
31
|
+
TEqualsTo
|
|
32
|
+
>;
|
|
33
|
+
notNullable(): IStringSchemaBuilder<
|
|
34
|
+
TRequired,
|
|
35
|
+
false,
|
|
36
|
+
TMinLength,
|
|
37
|
+
TMaxLength,
|
|
38
|
+
TEqualsTo
|
|
39
|
+
>;
|
|
40
|
+
minLength<K extends number>(
|
|
41
|
+
val: K
|
|
42
|
+
): IStringSchemaBuilder<TRequired, TNullable, K, TMaxLength, TEqualsTo>;
|
|
43
|
+
clearMinLength(): IStringSchemaBuilder<
|
|
44
|
+
TRequired,
|
|
45
|
+
TNullable,
|
|
46
|
+
undefined,
|
|
47
|
+
TMaxLength,
|
|
48
|
+
TEqualsTo
|
|
49
|
+
>;
|
|
50
|
+
maxLength<K extends number>(
|
|
51
|
+
val: K
|
|
52
|
+
): IStringSchemaBuilder<TRequired, TNullable, TMinLength, K, TEqualsTo>;
|
|
53
|
+
clearMaxLength(): IStringSchemaBuilder<
|
|
54
|
+
TRequired,
|
|
55
|
+
TNullable,
|
|
56
|
+
TMinLength,
|
|
57
|
+
undefined,
|
|
58
|
+
TEqualsTo
|
|
59
|
+
>;
|
|
60
|
+
equals<T extends string>(
|
|
61
|
+
val: T
|
|
62
|
+
): IStringSchemaBuilder<TRequired, TNullable, TMinLength, TMaxLength, T>;
|
|
63
|
+
clearEquals(): IStringSchemaBuilder<
|
|
64
|
+
TRequired,
|
|
65
|
+
TNullable,
|
|
66
|
+
TMinLength,
|
|
67
|
+
TMaxLength,
|
|
68
|
+
undefined
|
|
69
|
+
>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class StringSchemaBuilder<
|
|
73
|
+
TRequired extends boolean = true,
|
|
74
|
+
TNullable extends boolean = false,
|
|
75
|
+
TMinLength extends number | undefined = undefined,
|
|
76
|
+
TMaxLength extends number | undefined = undefined,
|
|
77
|
+
TEqualsTo extends string | undefined = undefined
|
|
78
|
+
>
|
|
79
|
+
extends SchemaBuilder<TRequired, TNullable>
|
|
80
|
+
implements
|
|
81
|
+
IStringSchemaBuilder<
|
|
82
|
+
TRequired,
|
|
83
|
+
TNullable,
|
|
84
|
+
TMinLength,
|
|
85
|
+
TMaxLength,
|
|
86
|
+
TEqualsTo
|
|
87
|
+
>
|
|
88
|
+
{
|
|
89
|
+
protected _minLength?: TMinLength;
|
|
90
|
+
protected _maxLength?: TMaxLength;
|
|
91
|
+
protected _equals?: TEqualsTo;
|
|
92
|
+
|
|
93
|
+
protected readonly type = 'string';
|
|
94
|
+
|
|
95
|
+
public clone(): this {
|
|
96
|
+
return StringSchemaBuilder.create(this._schema as any) as this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public get _schema(): Schema {
|
|
100
|
+
return Object.assign(
|
|
101
|
+
{
|
|
102
|
+
type: this.type
|
|
103
|
+
},
|
|
104
|
+
this.getCommonSchema(),
|
|
105
|
+
typeof this._minLength !== 'undefined'
|
|
106
|
+
? { minLength: this._minLength }
|
|
107
|
+
: {},
|
|
108
|
+
typeof this._maxLength !== 'undefined'
|
|
109
|
+
? { maxLength: this._maxLength }
|
|
110
|
+
: {},
|
|
111
|
+
typeof this._equals !== 'undefined' ? { equals: this._equals } : {}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public optional(): IStringSchemaBuilder<
|
|
116
|
+
false,
|
|
117
|
+
TNullable,
|
|
118
|
+
TMinLength,
|
|
119
|
+
TMaxLength,
|
|
120
|
+
TEqualsTo
|
|
121
|
+
> {
|
|
122
|
+
if (this.isRequired === false) {
|
|
123
|
+
return this as IStringSchemaBuilder<
|
|
124
|
+
false,
|
|
125
|
+
TNullable,
|
|
126
|
+
TMinLength,
|
|
127
|
+
TMaxLength,
|
|
128
|
+
TEqualsTo
|
|
129
|
+
>;
|
|
130
|
+
}
|
|
131
|
+
return StringSchemaBuilder.create({
|
|
132
|
+
...(this._schema as any),
|
|
133
|
+
isRequired: false
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public required(): IStringSchemaBuilder<
|
|
138
|
+
true,
|
|
139
|
+
TNullable,
|
|
140
|
+
TMinLength,
|
|
141
|
+
TMaxLength,
|
|
142
|
+
TEqualsTo
|
|
143
|
+
> {
|
|
144
|
+
if (this.isRequired === true) {
|
|
145
|
+
return this as any as IStringSchemaBuilder<
|
|
146
|
+
true,
|
|
147
|
+
TNullable,
|
|
148
|
+
TMinLength,
|
|
149
|
+
TMaxLength,
|
|
150
|
+
TEqualsTo
|
|
151
|
+
>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return StringSchemaBuilder.create({
|
|
155
|
+
...(this._schema as any),
|
|
156
|
+
isRequired: true
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public nullable(): IStringSchemaBuilder<
|
|
161
|
+
TRequired,
|
|
162
|
+
true,
|
|
163
|
+
TMinLength,
|
|
164
|
+
TMaxLength,
|
|
165
|
+
TEqualsTo
|
|
166
|
+
> {
|
|
167
|
+
if (this.isNullable === true) {
|
|
168
|
+
return this as any as IStringSchemaBuilder<
|
|
169
|
+
TRequired,
|
|
170
|
+
true,
|
|
171
|
+
TMinLength,
|
|
172
|
+
TMaxLength,
|
|
173
|
+
TEqualsTo
|
|
174
|
+
>;
|
|
175
|
+
}
|
|
176
|
+
return StringSchemaBuilder.create({
|
|
177
|
+
...(this._schema as any),
|
|
178
|
+
isNullable: true
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public notNullable(): IStringSchemaBuilder<
|
|
183
|
+
TRequired,
|
|
184
|
+
false,
|
|
185
|
+
TMinLength,
|
|
186
|
+
TMaxLength,
|
|
187
|
+
TEqualsTo
|
|
188
|
+
> {
|
|
189
|
+
if (this.isNullable === false) {
|
|
190
|
+
return this as any as IStringSchemaBuilder<
|
|
191
|
+
TRequired,
|
|
192
|
+
false,
|
|
193
|
+
TMinLength,
|
|
194
|
+
TMaxLength,
|
|
195
|
+
TEqualsTo
|
|
196
|
+
>;
|
|
197
|
+
}
|
|
198
|
+
return StringSchemaBuilder.create({
|
|
199
|
+
...(this._schema as any),
|
|
200
|
+
isNullable: false
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public minLength<K extends number>(
|
|
205
|
+
val: K
|
|
206
|
+
): IStringSchemaBuilder<TRequired, TNullable, K, TMaxLength, TEqualsTo> {
|
|
207
|
+
if ((this._minLength as any) === val) {
|
|
208
|
+
return this as any as IStringSchemaBuilder<
|
|
209
|
+
TRequired,
|
|
210
|
+
TNullable,
|
|
211
|
+
K,
|
|
212
|
+
TMaxLength,
|
|
213
|
+
TEqualsTo
|
|
214
|
+
>;
|
|
215
|
+
}
|
|
216
|
+
return StringSchemaBuilder.create({
|
|
217
|
+
...(this._schema as any),
|
|
218
|
+
minLength: val
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
public clearMinLength(): IStringSchemaBuilder<
|
|
223
|
+
TRequired,
|
|
224
|
+
TNullable,
|
|
225
|
+
undefined,
|
|
226
|
+
TMaxLength,
|
|
227
|
+
TEqualsTo
|
|
228
|
+
> {
|
|
229
|
+
if (typeof this._minLength === 'undefined') {
|
|
230
|
+
return this as any as IStringSchemaBuilder<
|
|
231
|
+
TRequired,
|
|
232
|
+
TNullable,
|
|
233
|
+
undefined,
|
|
234
|
+
TMaxLength,
|
|
235
|
+
TEqualsTo
|
|
236
|
+
>;
|
|
237
|
+
}
|
|
238
|
+
return StringSchemaBuilder.create({
|
|
239
|
+
...(this._schema as any),
|
|
240
|
+
minLength: undefined
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public maxLength<K extends number>(
|
|
245
|
+
val: K
|
|
246
|
+
): IStringSchemaBuilder<TRequired, TNullable, TMinLength, K, TEqualsTo> {
|
|
247
|
+
if ((this._maxLength as any) === val) {
|
|
248
|
+
return this as any as IStringSchemaBuilder<
|
|
249
|
+
TRequired,
|
|
250
|
+
TNullable,
|
|
251
|
+
TMinLength,
|
|
252
|
+
K,
|
|
253
|
+
TEqualsTo
|
|
254
|
+
>;
|
|
255
|
+
}
|
|
256
|
+
return StringSchemaBuilder.create({
|
|
257
|
+
...(this._schema as any),
|
|
258
|
+
maxLength: val
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public clearMaxLength(): IStringSchemaBuilder<
|
|
263
|
+
TRequired,
|
|
264
|
+
TNullable,
|
|
265
|
+
TMinLength,
|
|
266
|
+
undefined,
|
|
267
|
+
TEqualsTo
|
|
268
|
+
> {
|
|
269
|
+
if (typeof this._maxLength === 'undefined') {
|
|
270
|
+
return this as IStringSchemaBuilder<
|
|
271
|
+
TRequired,
|
|
272
|
+
TNullable,
|
|
273
|
+
TMinLength,
|
|
274
|
+
undefined,
|
|
275
|
+
TEqualsTo
|
|
276
|
+
>;
|
|
277
|
+
}
|
|
278
|
+
return StringSchemaBuilder.create({
|
|
279
|
+
...(this._schema as any),
|
|
280
|
+
maxLength: undefined
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
public equals<T extends string>(
|
|
285
|
+
val: T
|
|
286
|
+
): IStringSchemaBuilder<TRequired, TNullable, TMinLength, TMaxLength, T> {
|
|
287
|
+
if ((this._equals as any) === val) {
|
|
288
|
+
return this as any as IStringSchemaBuilder<
|
|
289
|
+
TRequired,
|
|
290
|
+
TNullable,
|
|
291
|
+
TMinLength,
|
|
292
|
+
TMaxLength,
|
|
293
|
+
T
|
|
294
|
+
>;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return StringSchemaBuilder.create({
|
|
298
|
+
...(this._schema as any),
|
|
299
|
+
equals: val as T
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
public clearEquals(): IStringSchemaBuilder<
|
|
304
|
+
TRequired,
|
|
305
|
+
TNullable,
|
|
306
|
+
TMinLength,
|
|
307
|
+
TMaxLength,
|
|
308
|
+
undefined
|
|
309
|
+
> {
|
|
310
|
+
if (typeof this._equals === 'undefined') {
|
|
311
|
+
return this as IStringSchemaBuilder<
|
|
312
|
+
TRequired,
|
|
313
|
+
TNullable,
|
|
314
|
+
TMinLength,
|
|
315
|
+
TMaxLength,
|
|
316
|
+
undefined
|
|
317
|
+
>;
|
|
318
|
+
}
|
|
319
|
+
return StringSchemaBuilder.create({
|
|
320
|
+
...(this._schema as any),
|
|
321
|
+
equals: undefined
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
public static create<
|
|
326
|
+
TRequired extends boolean = true,
|
|
327
|
+
TNullable extends boolean = false,
|
|
328
|
+
TMinLength extends number | undefined = undefined,
|
|
329
|
+
TMaxLength extends number | undefined = undefined,
|
|
330
|
+
TEqualsTo extends string | undefined = undefined
|
|
331
|
+
>(obj?: {
|
|
332
|
+
isRequired: TRequired;
|
|
333
|
+
isNullable: TNullable;
|
|
334
|
+
minLength?: TMinLength;
|
|
335
|
+
maxLength?: TMaxLength;
|
|
336
|
+
equals?: TEqualsTo;
|
|
337
|
+
validators?: Validator[];
|
|
338
|
+
preprocessor?:
|
|
339
|
+
| ((value: unknown) => unknown | Promise<unknown>)
|
|
340
|
+
| string;
|
|
341
|
+
}): IStringSchemaBuilder<
|
|
342
|
+
TRequired,
|
|
343
|
+
TNullable,
|
|
344
|
+
TMinLength,
|
|
345
|
+
TMaxLength,
|
|
346
|
+
TEqualsTo
|
|
347
|
+
> {
|
|
348
|
+
return new StringSchemaBuilder(obj as any);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private constructor(obj: {
|
|
352
|
+
isRequired: TRequired;
|
|
353
|
+
isNullable: TNullable;
|
|
354
|
+
minLength: TMinLength;
|
|
355
|
+
maxLength: TMaxLength;
|
|
356
|
+
equals: TEqualsTo;
|
|
357
|
+
validators?: Validator[];
|
|
358
|
+
preprocessor?:
|
|
359
|
+
| ((value: unknown) => unknown | Promise<unknown>)
|
|
360
|
+
| string;
|
|
361
|
+
}) {
|
|
362
|
+
super(obj);
|
|
363
|
+
if (typeof obj === 'object' && obj) {
|
|
364
|
+
if (typeof obj.minLength !== 'undefined') {
|
|
365
|
+
this._minLength = obj.minLength;
|
|
366
|
+
}
|
|
367
|
+
if (typeof obj.maxLength !== 'undefined') {
|
|
368
|
+
this._maxLength = obj.maxLength;
|
|
369
|
+
}
|
|
370
|
+
if (typeof obj.equals !== 'undefined') {
|
|
371
|
+
this._equals = obj.equals;
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
const defaultSchema = defaultSchemas['string'] as any;
|
|
375
|
+
this.isRequired = defaultSchema.isRequired;
|
|
376
|
+
this.isNullable = defaultSchema.isNullable;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export const string = <T extends string | undefined = undefined>(
|
|
382
|
+
equals?: T
|
|
383
|
+
): IStringSchemaBuilder<
|
|
384
|
+
true,
|
|
385
|
+
false,
|
|
386
|
+
undefined,
|
|
387
|
+
undefined,
|
|
388
|
+
T extends undefined ? undefined : T
|
|
389
|
+
> => {
|
|
390
|
+
const res = StringSchemaBuilder.create();
|
|
391
|
+
return typeof equals === 'string' ? res.equals(equals) : res;
|
|
392
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { union } from './UnionSchemaBuilder.js';
|
|
2
|
+
import { string } from './StringSchemaBuilder.js';
|
|
3
|
+
import { number } from './NumberSchemaBuilder.js';
|
|
4
|
+
|
|
5
|
+
test('Clean', () => {
|
|
6
|
+
const schema = union(string())._schema;
|
|
7
|
+
expect(schema).toHaveProperty('type', 'union');
|
|
8
|
+
expect(schema).toHaveProperty('variants');
|
|
9
|
+
expect(schema).toHaveProperty('variants.length', 1);
|
|
10
|
+
expect(schema).toHaveProperty('isRequired', true);
|
|
11
|
+
expect(schema).toHaveProperty('isNullable', false);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('optional', () => {
|
|
15
|
+
const schema = union(number()).optional();
|
|
16
|
+
expect(schema).toHaveProperty('isRequired', false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('optional - 2', () => {
|
|
20
|
+
const schema = union(number()).optional().required();
|
|
21
|
+
expect(schema).toHaveProperty('isRequired', true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('optional - 3', () => {
|
|
25
|
+
const schema1 = union(number());
|
|
26
|
+
const schema2 = schema1.optional();
|
|
27
|
+
const e = (schema1 as any) === schema2;
|
|
28
|
+
const isRequiredEqual = (schema1 as any).isRequired !== schema2.isRequired;
|
|
29
|
+
expect(e).toEqual(false);
|
|
30
|
+
expect(isRequiredEqual).toEqual(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('optional - 4', () => {
|
|
34
|
+
const schema1 = union(number()).optional();
|
|
35
|
+
const schema2 = schema1.optional();
|
|
36
|
+
const e = (schema1 as any) === schema2;
|
|
37
|
+
const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
|
|
38
|
+
expect(e).toEqual(true);
|
|
39
|
+
expect(isRequiredEqual).toEqual(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('optional - 5', () => {
|
|
43
|
+
const schema1 = union(number());
|
|
44
|
+
const schema2 = schema1.required();
|
|
45
|
+
const e = (schema1 as any) === schema2;
|
|
46
|
+
const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
|
|
47
|
+
expect(e).toEqual(true);
|
|
48
|
+
expect(isRequiredEqual).toEqual(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('optional - 6', () => {
|
|
52
|
+
const schema1 = union(number()).optional();
|
|
53
|
+
const schema2 = schema1.required();
|
|
54
|
+
const e = (schema1 as any) === schema2;
|
|
55
|
+
const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
|
|
56
|
+
expect(e).toEqual(false);
|
|
57
|
+
expect(isRequiredEqual).toEqual(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('optional - 7', () => {
|
|
61
|
+
const schema1 = union(number()).optional().required();
|
|
62
|
+
const schema2 = schema1.required();
|
|
63
|
+
const e = (schema1 as any) === schema2;
|
|
64
|
+
const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
|
|
65
|
+
expect(e).toEqual(true);
|
|
66
|
+
expect(isRequiredEqual).toEqual(true);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('nullable - 1', () => {
|
|
70
|
+
const schema = union(number()).nullable();
|
|
71
|
+
expect(schema).toHaveProperty('isNullable', true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('nullable - 2', () => {
|
|
75
|
+
const schema = union(number()).nullable().notNullable();
|
|
76
|
+
expect(schema).toHaveProperty('isNullable', false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('nullable - 3', () => {
|
|
80
|
+
const schema1 = union(string());
|
|
81
|
+
const schema2 = schema1.nullable();
|
|
82
|
+
const e = (schema1 as any) === schema2;
|
|
83
|
+
const isNullableEqual = (schema1 as any).isNullable !== schema2.isNullable;
|
|
84
|
+
expect(e).toEqual(false);
|
|
85
|
+
expect(isNullableEqual).toEqual(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('nullable - 4', () => {
|
|
89
|
+
const schema1 = union(number()).nullable();
|
|
90
|
+
const schema2 = schema1.nullable();
|
|
91
|
+
const e = (schema1 as any) === schema2;
|
|
92
|
+
const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
|
|
93
|
+
expect(e).toEqual(true);
|
|
94
|
+
expect(isNullableEqual).toEqual(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('nullable - 5', () => {
|
|
98
|
+
const schema1 = union(number());
|
|
99
|
+
const schema2 = schema1.nullable();
|
|
100
|
+
const e = (schema1 as any) === schema2;
|
|
101
|
+
const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
|
|
102
|
+
expect(e).toEqual(false);
|
|
103
|
+
expect(isNullableEqual).toEqual(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('nullable - 6', () => {
|
|
107
|
+
const schema1 = union(number());
|
|
108
|
+
const schema2 = schema1.notNullable();
|
|
109
|
+
const e = (schema1 as any) === schema2;
|
|
110
|
+
const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
|
|
111
|
+
expect(e).toEqual(true);
|
|
112
|
+
expect(isNullableEqual).toEqual(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('nullable - 7', () => {
|
|
116
|
+
const schema1 = union(number()).nullable();
|
|
117
|
+
const schema2 = schema1.notNullable();
|
|
118
|
+
const e = (schema1 as any) === schema2;
|
|
119
|
+
const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
|
|
120
|
+
expect(e).toEqual(false);
|
|
121
|
+
expect(isNullableEqual).toEqual(false);
|
|
122
|
+
});
|
|
123
|
+
test('or - 1', () => {
|
|
124
|
+
const schema1 = union(string());
|
|
125
|
+
const schema2 = schema1.or(number());
|
|
126
|
+
const equal = (schema1 as any) === schema2;
|
|
127
|
+
expect(equal).toEqual(false);
|
|
128
|
+
expect(schema2._schema).toHaveProperty('type', 'union');
|
|
129
|
+
expect(schema2._schema).toHaveProperty('variants');
|
|
130
|
+
expect(schema2._schema).toHaveProperty('variants.length', 2);
|
|
131
|
+
expect(schema2._schema).toHaveProperty('isRequired', true);
|
|
132
|
+
expect(schema2._schema).toHaveProperty('isNullable', false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('or - 2', () => {
|
|
136
|
+
const schema1 = union(string()).or(number());
|
|
137
|
+
const schema2 = schema1.clearVariants();
|
|
138
|
+
const equal = (schema1 as any) === schema2;
|
|
139
|
+
expect(equal).toEqual(false);
|
|
140
|
+
expect(schema2._schema).toHaveProperty('type', 'union');
|
|
141
|
+
expect(schema2._schema).toHaveProperty('variants');
|
|
142
|
+
expect(schema2._schema).toHaveProperty('variants.length', 0);
|
|
143
|
+
expect(schema2._schema).toHaveProperty('isRequired', true);
|
|
144
|
+
expect(schema2._schema).toHaveProperty('isNullable', false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('or - 3', () => {
|
|
148
|
+
const schema1 = union(string()).or(number()).clearVariants();
|
|
149
|
+
const schema2 = schema1.clearVariants();
|
|
150
|
+
const equal = (schema1 as any) === schema2;
|
|
151
|
+
expect(equal).toEqual(true);
|
|
152
|
+
expect(schema2._schema).toHaveProperty('type', 'union');
|
|
153
|
+
expect(schema2._schema).toHaveProperty('variants');
|
|
154
|
+
expect(schema2._schema).toHaveProperty('variants.length', 0);
|
|
155
|
+
expect(schema2._schema).toHaveProperty('isRequired', true);
|
|
156
|
+
expect(schema2._schema).toHaveProperty('isNullable', false);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('or - 4', () => {
|
|
160
|
+
const schema1 = union(string('123'), string('321'));
|
|
161
|
+
expect(schema1._schema.variants.length).toEqual(2);
|
|
162
|
+
});
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Schema } from '../schema.js';
|
|
2
|
+
import { SchemaBuilder, ISchemaBuilder } from './SchemaBuilder.js';
|
|
3
|
+
|
|
4
|
+
export interface IUnionSchemaBuilder<
|
|
5
|
+
TRequired extends boolean = true,
|
|
6
|
+
TNullable extends boolean = false,
|
|
7
|
+
TVariants extends any[] = []
|
|
8
|
+
> extends ISchemaBuilder<TRequired, TNullable> {
|
|
9
|
+
optional(): IUnionSchemaBuilder<false, TNullable, TVariants>;
|
|
10
|
+
required(): IUnionSchemaBuilder<true, TNullable, TVariants>;
|
|
11
|
+
nullable(): IUnionSchemaBuilder<TRequired, true, TVariants>;
|
|
12
|
+
notNullable(): IUnionSchemaBuilder<TRequired, false, TVariants>;
|
|
13
|
+
or<T>(
|
|
14
|
+
schema: T
|
|
15
|
+
): IUnionSchemaBuilder<TRequired, TNullable, [...TVariants, T]>;
|
|
16
|
+
clearVariants(): IUnionSchemaBuilder<TRequired, TNullable, []>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class UnionSchemaBuilder<
|
|
20
|
+
TRequired extends boolean = true,
|
|
21
|
+
TNullable extends boolean = false,
|
|
22
|
+
TVariants extends any[] = []
|
|
23
|
+
>
|
|
24
|
+
extends SchemaBuilder<TRequired, TNullable>
|
|
25
|
+
implements IUnionSchemaBuilder<TRequired, TNullable, TVariants>
|
|
26
|
+
{
|
|
27
|
+
protected readonly type = 'union';
|
|
28
|
+
|
|
29
|
+
get _schema(): Schema {
|
|
30
|
+
return Object.assign(
|
|
31
|
+
{
|
|
32
|
+
type: this.type
|
|
33
|
+
},
|
|
34
|
+
this.getCommonSchema(),
|
|
35
|
+
{
|
|
36
|
+
variants: this._variants
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public clone(): this {
|
|
42
|
+
return UnionSchemaBuilder.create(this._schema as any) as this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected _variants: TVariants;
|
|
46
|
+
|
|
47
|
+
public static create<
|
|
48
|
+
TRequired extends boolean = true,
|
|
49
|
+
TNullable extends boolean = false,
|
|
50
|
+
TSchemas extends Schema[] = []
|
|
51
|
+
>(obj: {
|
|
52
|
+
isRequired: TRequired;
|
|
53
|
+
isNullable: TNullable;
|
|
54
|
+
variants?: TSchemas;
|
|
55
|
+
}): IUnionSchemaBuilder<TRequired, TNullable, TSchemas> {
|
|
56
|
+
return new UnionSchemaBuilder(obj);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private constructor(obj: {
|
|
60
|
+
isRequired: TRequired;
|
|
61
|
+
isNullable: TNullable;
|
|
62
|
+
variants?: TVariants;
|
|
63
|
+
}) {
|
|
64
|
+
super(obj);
|
|
65
|
+
this._variants = [] as TVariants;
|
|
66
|
+
if (Array.isArray(obj.variants)) {
|
|
67
|
+
for (let i = 0; i < obj.variants.length; i++) {
|
|
68
|
+
this._variants.push(obj.variants[i]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
optional(): IUnionSchemaBuilder<false, TNullable, TVariants> {
|
|
74
|
+
if (this.isRequired === false) {
|
|
75
|
+
return this as IUnionSchemaBuilder<false, TNullable, TVariants>;
|
|
76
|
+
}
|
|
77
|
+
return UnionSchemaBuilder.create({
|
|
78
|
+
...(this._schema as any),
|
|
79
|
+
isRequired: false
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
required(): IUnionSchemaBuilder<true, TNullable, TVariants> {
|
|
84
|
+
if (this.isRequired === true) {
|
|
85
|
+
return this as IUnionSchemaBuilder<true, TNullable, TVariants>;
|
|
86
|
+
}
|
|
87
|
+
return UnionSchemaBuilder.create({
|
|
88
|
+
...(this._schema as any),
|
|
89
|
+
isRequired: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
nullable(): IUnionSchemaBuilder<TRequired, true, TVariants> {
|
|
94
|
+
if (this.isNullable === true) {
|
|
95
|
+
return this as IUnionSchemaBuilder<TRequired, true, TVariants>;
|
|
96
|
+
}
|
|
97
|
+
return UnionSchemaBuilder.create({
|
|
98
|
+
...(this._schema as any),
|
|
99
|
+
isNullable: true
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
notNullable(): IUnionSchemaBuilder<TRequired, false, TVariants> {
|
|
104
|
+
if (this.isNullable === false) {
|
|
105
|
+
return this as IUnionSchemaBuilder<TRequired, false, TVariants>;
|
|
106
|
+
}
|
|
107
|
+
return UnionSchemaBuilder.create({
|
|
108
|
+
...(this._schema as any),
|
|
109
|
+
isNullable: false
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
or<T>(
|
|
114
|
+
schema: T
|
|
115
|
+
): IUnionSchemaBuilder<TRequired, TNullable, [...TVariants, T]> {
|
|
116
|
+
return UnionSchemaBuilder.create({
|
|
117
|
+
...(this._schema as any),
|
|
118
|
+
variants: [...this._variants, schema]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
clearVariants(): IUnionSchemaBuilder<TRequired, TNullable, []> {
|
|
123
|
+
if (this._variants.length === 0)
|
|
124
|
+
return this as any as IUnionSchemaBuilder<TRequired, TNullable, []>;
|
|
125
|
+
return UnionSchemaBuilder.create({
|
|
126
|
+
...(this._schema as any),
|
|
127
|
+
variants: []
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const union = <
|
|
133
|
+
T extends ISchemaBuilder,
|
|
134
|
+
K extends T[],
|
|
135
|
+
TRequired extends boolean = true,
|
|
136
|
+
TNullable extends boolean = false
|
|
137
|
+
>(
|
|
138
|
+
...schemas: K
|
|
139
|
+
): IUnionSchemaBuilder<TRequired, TNullable, K> => {
|
|
140
|
+
if (schemas.length < 1) {
|
|
141
|
+
throw new Error('should provide at least one variant');
|
|
142
|
+
}
|
|
143
|
+
let res = UnionSchemaBuilder.create({
|
|
144
|
+
isRequired: true,
|
|
145
|
+
isNullable: false,
|
|
146
|
+
variants: [schemas[0] as any]
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
for (let i = 1; i < schemas.length; i++) {
|
|
150
|
+
res = res.or(schemas[i]);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return res as any;
|
|
154
|
+
};
|