@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.
Files changed (47) hide show
  1. package/README.md +213 -163
  2. package/package.json +3 -3
  3. package/src/builders/ArraySchemaBuilder.test.ts +270 -0
  4. package/src/builders/ArraySchemaBuilder.ts +381 -0
  5. package/src/builders/BooleanSchemaBuilder.test.ts +196 -0
  6. package/src/builders/BooleanSchemaBuilder.ts +155 -0
  7. package/src/builders/FunctionSchemaBuilder.test.ts +134 -0
  8. package/src/builders/FunctionSchemaBuilder.ts +109 -0
  9. package/src/builders/NumberSchemaBuilder.test.ts +493 -0
  10. package/src/builders/NumberSchemaBuilder.ts +789 -0
  11. package/src/builders/ObjectSchemaBuilder.test.ts +657 -0
  12. package/src/builders/ObjectSchemaBuilder.ts +794 -0
  13. package/src/builders/SchemaBuilder.test.ts +73 -0
  14. package/src/builders/SchemaBuilder.ts +135 -0
  15. package/src/builders/StringSchemaBuilder.test.ts +318 -0
  16. package/src/builders/StringSchemaBuilder.ts +392 -0
  17. package/src/builders/UnionSchemaBuilder.test.ts +162 -0
  18. package/src/builders/UnionSchemaBuilder.ts +154 -0
  19. package/src/defaultSchemas.ts +44 -0
  20. package/src/index.ts +58 -190
  21. package/src/schema.ts +827 -0
  22. package/src/schemaRegistry.builders.test.ts +1393 -0
  23. package/src/schemaRegistry.test.ts +118 -0
  24. package/src/schemaRegistry.ts +461 -0
  25. package/src/validators/validateArray.ts +4 -7
  26. package/src/validators/validateBoolean.ts +2 -11
  27. package/src/validators/validateFunction.ts +25 -0
  28. package/src/validators/validateNumber.ts +2 -7
  29. package/src/validators/validateObject.ts +32 -21
  30. package/src/validators/validateString.ts +2 -7
  31. package/src/validators/validateUnion.ts +36 -0
  32. package/dist/index.d.ts +0 -94
  33. package/dist/index.js +0 -9
  34. package/dist/schemaValidator.d.ts +0 -16
  35. package/dist/schemaValidator.js +0 -234
  36. package/dist/validators/validateArray.d.ts +0 -2
  37. package/dist/validators/validateArray.js +0 -60
  38. package/dist/validators/validateBoolean.d.ts +0 -2
  39. package/dist/validators/validateBoolean.js +0 -33
  40. package/dist/validators/validateNumber.d.ts +0 -2
  41. package/dist/validators/validateNumber.js +0 -69
  42. package/dist/validators/validateObject.d.ts +0 -2
  43. package/dist/validators/validateObject.js +0 -73
  44. package/dist/validators/validateString.d.ts +0 -2
  45. package/dist/validators/validateString.js +0 -50
  46. package/src/schemaValidator.test.ts +0 -1656
  47. 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
+ };