@cleverbrush/schema 0.0.17 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +213 -163
  2. package/dist/builders/AliasSchemaBuilder.d.ts +14 -0
  3. package/dist/builders/AliasSchemaBuilder.js +91 -0
  4. package/dist/builders/ArraySchemaBuilder.d.ts +15 -0
  5. package/dist/builders/ArraySchemaBuilder.js +141 -0
  6. package/dist/builders/BooleanSchemaBuilder.d.ts +31 -0
  7. package/dist/builders/BooleanSchemaBuilder.js +90 -0
  8. package/dist/builders/FunctionSchemaBuilder.d.ts +25 -0
  9. package/dist/builders/FunctionSchemaBuilder.js +66 -0
  10. package/dist/builders/NumberSchemaBuilder.d.ts +61 -0
  11. package/dist/builders/NumberSchemaBuilder.js +206 -0
  12. package/dist/builders/ObjectSchemaBuilder.d.ts +83 -0
  13. package/dist/builders/ObjectSchemaBuilder.js +344 -0
  14. package/dist/builders/SchemaBuilder.d.ts +36 -0
  15. package/dist/builders/SchemaBuilder.js +88 -0
  16. package/dist/builders/StringSchemaBuilder.d.ts +14 -0
  17. package/dist/builders/StringSchemaBuilder.js +140 -0
  18. package/dist/builders/UnionSchemaBuilder.d.ts +10 -0
  19. package/dist/builders/UnionSchemaBuilder.js +100 -0
  20. package/dist/defaultSchemas.d.ts +4 -0
  21. package/dist/defaultSchemas.js +45 -0
  22. package/dist/index.d.ts +38 -90
  23. package/dist/index.js +30 -4
  24. package/dist/schema.d.ts +242 -0
  25. package/dist/schema.js +2 -0
  26. package/dist/schemaRegistry.d.ts +54 -0
  27. package/dist/schemaRegistry.js +301 -0
  28. package/dist/validators/validateArray.d.ts +3 -2
  29. package/dist/validators/validateBoolean.d.ts +2 -2
  30. package/dist/validators/validateBoolean.js +1 -4
  31. package/dist/validators/validateFunction.d.ts +2 -0
  32. package/dist/validators/validateFunction.js +21 -0
  33. package/dist/validators/validateNumber.d.ts +2 -2
  34. package/dist/validators/validateNumber.js +1 -1
  35. package/dist/validators/validateObject.d.ts +3 -2
  36. package/dist/validators/validateObject.js +33 -11
  37. package/dist/validators/validateString.d.ts +2 -2
  38. package/dist/validators/validateString.js +1 -1
  39. package/dist/validators/validateUnion.d.ts +3 -0
  40. package/dist/validators/validateUnion.js +30 -0
  41. package/package.json +3 -3
  42. package/src/builders/AliasSchemaBuilder.test.ts +124 -0
  43. package/src/builders/AliasSchemaBuilder.ts +250 -0
  44. package/src/builders/ArraySchemaBuilder.test.ts +270 -0
  45. package/src/builders/ArraySchemaBuilder.ts +381 -0
  46. package/src/builders/BooleanSchemaBuilder.test.ts +196 -0
  47. package/src/builders/BooleanSchemaBuilder.ts +155 -0
  48. package/src/builders/FunctionSchemaBuilder.test.ts +134 -0
  49. package/src/builders/FunctionSchemaBuilder.ts +109 -0
  50. package/src/builders/NumberSchemaBuilder.test.ts +493 -0
  51. package/src/builders/NumberSchemaBuilder.ts +789 -0
  52. package/src/builders/ObjectSchemaBuilder.test.ts +657 -0
  53. package/src/builders/ObjectSchemaBuilder.ts +794 -0
  54. package/src/builders/SchemaBuilder.test.ts +73 -0
  55. package/src/builders/SchemaBuilder.ts +135 -0
  56. package/src/builders/StringSchemaBuilder.test.ts +318 -0
  57. package/src/builders/StringSchemaBuilder.ts +392 -0
  58. package/src/builders/UnionSchemaBuilder.test.ts +162 -0
  59. package/src/builders/UnionSchemaBuilder.ts +159 -0
  60. package/src/defaultSchemas.ts +44 -0
  61. package/src/index.ts +70 -190
  62. package/src/schema.ts +922 -0
  63. package/src/schemaRegistry.builders.test.ts +1438 -0
  64. package/src/{schemaValidator.test.ts → schemaRegistry.test.ts} +561 -185
  65. package/src/schemaRegistry.ts +532 -0
  66. package/src/validators/validateArray.ts +4 -7
  67. package/src/validators/validateBoolean.ts +2 -11
  68. package/src/validators/validateFunction.ts +25 -0
  69. package/src/validators/validateNumber.ts +2 -7
  70. package/src/validators/validateObject.ts +32 -21
  71. package/src/validators/validateString.ts +2 -7
  72. package/src/validators/validateUnion.ts +36 -0
  73. package/dist/schemaValidator.d.ts +0 -16
  74. package/dist/schemaValidator.js +0 -234
  75. package/src/schemaValidator.ts +0 -367
@@ -0,0 +1,196 @@
1
+ import { deepEqual } from '@cleverbrush/deep';
2
+
3
+ import { Schema } from '../schema.js';
4
+ import { boolean } from './BooleanSchemaBuilder.js';
5
+
6
+ test('Clean', () => {
7
+ const schema = boolean();
8
+ expect(schema).toHaveProperty('type', 'boolean');
9
+ expect(schema).toHaveProperty('isRequired', true);
10
+ expect(schema).toHaveProperty('isNullable', false);
11
+ });
12
+
13
+ test('optional', () => {
14
+ const schema = boolean().optional();
15
+ expect(schema).toHaveProperty('type', 'boolean');
16
+ expect(schema).toHaveProperty('isRequired', false);
17
+ });
18
+
19
+ test('optional - 2', () => {
20
+ const schema = boolean().optional().required();
21
+ expect(schema).toHaveProperty('type', 'boolean');
22
+ expect(schema).toHaveProperty('isRequired', true);
23
+ });
24
+
25
+ test('optional - 3', () => {
26
+ const schema1 = boolean();
27
+ const schema2 = schema1.optional();
28
+ const e = (schema1 as Schema) === (schema2 as Schema);
29
+ const isRequiredEqual = (schema1 as any).isRequired !== schema2.isRequired;
30
+ expect(e).toEqual(false);
31
+ expect(isRequiredEqual).toEqual(true);
32
+ });
33
+
34
+ test('optional - 4', () => {
35
+ const schema1 = boolean().optional();
36
+ const schema2 = schema1.optional();
37
+ const e = (schema1 as Schema) === (schema2 as Schema);
38
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
39
+ expect(e).toEqual(true);
40
+ expect(isRequiredEqual).toEqual(true);
41
+ });
42
+
43
+ test('optional - 5', () => {
44
+ const schema1 = boolean();
45
+ const schema2 = schema1.required();
46
+ const e = (schema1 as Schema) === (schema2 as Schema);
47
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
48
+ expect(e).toEqual(true);
49
+ expect(isRequiredEqual).toEqual(true);
50
+ });
51
+
52
+ test('optional - 6', () => {
53
+ const schema1 = boolean().optional();
54
+ const schema2 = schema1.required();
55
+ const e = (schema1 as Schema) === (schema2 as Schema);
56
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
57
+ expect(e).toEqual(false);
58
+ expect(isRequiredEqual).toEqual(false);
59
+ });
60
+
61
+ test('optional - 7', () => {
62
+ const schema1 = boolean().optional().required();
63
+ const schema2 = schema1.required();
64
+ const e = (schema1 as Schema) === (schema2 as Schema);
65
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
66
+ expect(e).toEqual(true);
67
+ expect(isRequiredEqual).toEqual(true);
68
+ });
69
+
70
+ test('nullable', () => {
71
+ const schema = boolean().nullable();
72
+ expect(schema).toHaveProperty('type', 'boolean');
73
+ expect(schema).toHaveProperty('isNullable', true);
74
+ });
75
+
76
+ test('nullable - 2', () => {
77
+ const schema = boolean().nullable().notNullable();
78
+ expect(schema).toHaveProperty('type', 'boolean');
79
+ expect(schema).toHaveProperty('isNullable', false);
80
+ });
81
+
82
+ test('nullable - 3', () => {
83
+ const schema1 = boolean();
84
+ const schema2 = schema1.nullable();
85
+ const e = (schema1 as Schema) === (schema2 as Schema);
86
+ const isNullableEqual = (schema1 as any).isNullable !== schema2.isNullable;
87
+ expect(e).toEqual(false);
88
+ expect(isNullableEqual).toEqual(true);
89
+ });
90
+
91
+ test('nullable - 4', () => {
92
+ const schema1 = boolean().nullable();
93
+ const schema2 = schema1.nullable();
94
+ const e = (schema1 as Schema) === (schema2 as Schema);
95
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
96
+ expect(e).toEqual(true);
97
+ expect(isNullableEqual).toEqual(true);
98
+ });
99
+
100
+ test('nullable - 5', () => {
101
+ const schema1 = boolean();
102
+ const schema2 = schema1.nullable();
103
+ const e = (schema1 as Schema) === (schema2 as Schema);
104
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
105
+ expect(e).toEqual(false);
106
+ expect(isNullableEqual).toEqual(false);
107
+ });
108
+
109
+ test('nullable - 6', () => {
110
+ const schema1 = boolean();
111
+ const schema2 = schema1.notNullable();
112
+ const e = (schema1 as Schema) === (schema2 as Schema);
113
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
114
+ expect(e).toEqual(true);
115
+ expect(isNullableEqual).toEqual(true);
116
+ });
117
+
118
+ test('nullable - 7', () => {
119
+ const schema1 = boolean().nullable();
120
+ const schema2 = schema1.notNullable();
121
+ const e = (schema1 as Schema) === (schema2 as Schema);
122
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
123
+ expect(e).toEqual(false);
124
+ expect(isNullableEqual).toEqual(false);
125
+ });
126
+
127
+ test('equals - 1', () => {
128
+ const schema = boolean().equals(true);
129
+ expect(schema._schema).toHaveProperty('type', 'boolean');
130
+ expect(schema._schema).toHaveProperty('equals', true);
131
+ });
132
+
133
+ test('equals - 2', () => {
134
+ const schema = boolean().equals(false);
135
+ expect(schema._schema).toHaveProperty('type', 'boolean');
136
+ expect(schema._schema).toHaveProperty('equals', false);
137
+ });
138
+
139
+ test('equals - 3', () => {
140
+ const schema = boolean();
141
+ expect(schema._schema).toHaveProperty('type', 'boolean');
142
+ expect(schema._schema).not.toHaveProperty('equals');
143
+ });
144
+
145
+ test('equals - 4', () => {
146
+ const schema = boolean().equals(true).clearEqualsTo();
147
+ expect(schema._schema).toHaveProperty('type', 'boolean');
148
+ expect(schema._schema).not.toHaveProperty('equals');
149
+ });
150
+
151
+ test('equals - 5', () => {
152
+ const schema1 = boolean().equals(true);
153
+ const schema2 = schema1.equals(true);
154
+ const equal = (schema1 as any) === schema2;
155
+ expect(equal).toEqual(true);
156
+ expect(schema1._schema).toHaveProperty('equals', true);
157
+ expect(schema2._schema).toHaveProperty('equals', true);
158
+ });
159
+
160
+ test('equals - 6', () => {
161
+ const schema1 = boolean();
162
+ const schema2 = schema1.equals(true);
163
+ const equal = (schema1 as any) === schema2;
164
+ expect(equal).toEqual(false);
165
+ expect(schema1._schema).not.toHaveProperty('equals');
166
+ expect(schema2._schema).toHaveProperty('equals', true);
167
+ });
168
+
169
+ test('equals - 7', () => {
170
+ const schema1 = boolean();
171
+ const schema2 = schema1.clearEqualsTo();
172
+ const equal = (schema1 as any) === schema2;
173
+ expect(equal).toEqual(true);
174
+ expect(schema1._schema).not.toHaveProperty('equals');
175
+ expect(schema2._schema).not.toHaveProperty('equals');
176
+ });
177
+
178
+ test('equals - 8', () => {
179
+ const schema1 = boolean().clearEqualsTo();
180
+ const schema2 = schema1.equals(false);
181
+ const equal = (schema1 as any) === schema2;
182
+ expect(equal).toEqual(false);
183
+ expect(schema1._schema).not.toHaveProperty('equals');
184
+ expect(schema2._schema).toHaveProperty('equals', false);
185
+ });
186
+
187
+ test('Clone', () => {
188
+ const schema1 = boolean()
189
+ .addValidator(() => ({ valid: true }))
190
+ .equals(true);
191
+ const schema2 = schema1.clone();
192
+ const equal = (schema1 as any) === schema2;
193
+ expect(equal).toEqual(false);
194
+ const equal2 = deepEqual(schema1._schema, schema2._schema);
195
+ expect(equal2).toEqual(true);
196
+ });
@@ -0,0 +1,155 @@
1
+ import { Schema, Validator } from '../schema.js';
2
+ import { ISchemaBuilder, SchemaBuilder } from './SchemaBuilder.js';
3
+ import { defaultSchemas } from '../defaultSchemas.js';
4
+
5
+ export interface IBooleanSchemaBuilder<
6
+ TRequired extends boolean = true,
7
+ TNullable extends boolean = false,
8
+ TEqualsTo extends boolean | undefined = undefined
9
+ > extends ISchemaBuilder<TRequired, TNullable> {
10
+ equals<T extends boolean>(
11
+ val: T
12
+ ): IBooleanSchemaBuilder<TRequired, TNullable, T>;
13
+ clearEqualsTo(): IBooleanSchemaBuilder<TRequired, TNullable, undefined>;
14
+ optional(): IBooleanSchemaBuilder<false, TNullable, TEqualsTo>;
15
+ required(): IBooleanSchemaBuilder<true, TNullable, TEqualsTo>;
16
+ nullable(): IBooleanSchemaBuilder<TRequired, true, TEqualsTo>;
17
+ notNullable(): IBooleanSchemaBuilder<TRequired, false, TEqualsTo>;
18
+ }
19
+
20
+ export class BooleanSchemaBuilder<
21
+ TRequired extends boolean = true,
22
+ TNullable extends boolean = false,
23
+ TEqualsTo extends boolean | undefined = undefined
24
+ >
25
+ extends SchemaBuilder<TRequired, TNullable>
26
+ implements IBooleanSchemaBuilder<TRequired, TNullable, TEqualsTo>
27
+ {
28
+ protected readonly type = 'boolean';
29
+
30
+ public get _schema(): Schema {
31
+ return Object.assign(
32
+ {
33
+ type: this.type
34
+ },
35
+ this.getCommonSchema(),
36
+ typeof this._equals !== 'undefined' ? { equals: this._equals } : {}
37
+ );
38
+ }
39
+
40
+ public clone(): this {
41
+ return BooleanSchemaBuilder.create(this._schema as any) as this;
42
+ }
43
+
44
+ public static create<
45
+ TRequired extends boolean = true,
46
+ TNullable extends boolean = false,
47
+ TEqualsTo extends boolean | undefined = undefined
48
+ >(obj?: {
49
+ isRequired: TRequired;
50
+ isNullable: TNullable;
51
+ equals?: TEqualsTo;
52
+ validators?: Validator[];
53
+ preprocessor?:
54
+ | ((value: unknown) => unknown | Promise<unknown>)
55
+ | string;
56
+ }): IBooleanSchemaBuilder<TRequired, TNullable, TEqualsTo> {
57
+ return new BooleanSchemaBuilder(obj as any);
58
+ }
59
+
60
+ private constructor(obj: {
61
+ isRequired: TRequired;
62
+ isNullable: TNullable;
63
+ equals: TEqualsTo;
64
+ validators?: Validator[];
65
+ preprocessor?:
66
+ | ((value: unknown) => unknown | Promise<unknown>)
67
+ | string;
68
+ }) {
69
+ super(obj);
70
+ if (typeof obj === 'object' && obj) {
71
+ if (typeof obj.equals !== 'undefined') {
72
+ this._equals = obj.equals;
73
+ }
74
+ } else {
75
+ const defaultSchema = defaultSchemas['boolean'] as any;
76
+ this.isRequired = defaultSchema.isRequired;
77
+ this.isNullable = defaultSchema.isNullable;
78
+ }
79
+ }
80
+
81
+ protected _equals?: TEqualsTo;
82
+
83
+ equals<T extends boolean>(
84
+ val: T
85
+ ): IBooleanSchemaBuilder<TRequired, TNullable, T> {
86
+ if ((this._equals as any) === val) {
87
+ return this as any as IBooleanSchemaBuilder<
88
+ TRequired,
89
+ TNullable,
90
+ T
91
+ >;
92
+ }
93
+ return BooleanSchemaBuilder.create({
94
+ ...(this._schema as any),
95
+ equals: val
96
+ });
97
+ }
98
+
99
+ clearEqualsTo(): IBooleanSchemaBuilder<TRequired, TNullable, undefined> {
100
+ if (typeof this._equals === 'undefined') {
101
+ return this as IBooleanSchemaBuilder<
102
+ TRequired,
103
+ TNullable,
104
+ undefined
105
+ >;
106
+ }
107
+ return BooleanSchemaBuilder.create({
108
+ ...(this._schema as any),
109
+ equals: undefined
110
+ });
111
+ }
112
+
113
+ optional(): IBooleanSchemaBuilder<false, TNullable, TEqualsTo> {
114
+ if (this.isRequired === false) {
115
+ return this as IBooleanSchemaBuilder<false, TNullable, TEqualsTo>;
116
+ }
117
+ return BooleanSchemaBuilder.create({
118
+ ...(this._schema as any),
119
+ isRequired: false
120
+ });
121
+ }
122
+
123
+ required(): IBooleanSchemaBuilder<true, TNullable, TEqualsTo> {
124
+ if (this.isRequired === true) {
125
+ return this as IBooleanSchemaBuilder<true, TNullable, TEqualsTo>;
126
+ }
127
+ return BooleanSchemaBuilder.create({
128
+ ...(this._schema as any),
129
+ isRequired: true
130
+ });
131
+ }
132
+
133
+ nullable(): IBooleanSchemaBuilder<TRequired, true, TEqualsTo> {
134
+ if (this.isNullable === true) {
135
+ return this as IBooleanSchemaBuilder<TRequired, true, TEqualsTo>;
136
+ }
137
+ return BooleanSchemaBuilder.create({
138
+ ...(this._schema as any),
139
+ isNullable: true
140
+ });
141
+ }
142
+
143
+ notNullable(): IBooleanSchemaBuilder<TRequired, false, TEqualsTo> {
144
+ if (this.isNullable === false) {
145
+ return this as IBooleanSchemaBuilder<TRequired, false, TEqualsTo>;
146
+ }
147
+ return BooleanSchemaBuilder.create({
148
+ ...(this._schema as any),
149
+ isNullable: false
150
+ });
151
+ }
152
+ }
153
+
154
+ export const boolean = (): IBooleanSchemaBuilder =>
155
+ BooleanSchemaBuilder.create();
@@ -0,0 +1,134 @@
1
+ import { deepEqual } from '@cleverbrush/deep';
2
+
3
+ import { Schema } from '../schema.js';
4
+ import { func } from './FunctionSchemaBuilder.js';
5
+
6
+ test('Clean', () => {
7
+ const schema = func();
8
+ expect(schema).toHaveProperty('type', 'function');
9
+ expect(schema).toHaveProperty('isRequired', true);
10
+ expect(schema).toHaveProperty('isNullable', false);
11
+ });
12
+
13
+ test('optional', () => {
14
+ const schema = func().optional();
15
+ expect(schema).toHaveProperty('type', 'function');
16
+ expect(schema).toHaveProperty('isRequired', false);
17
+ });
18
+
19
+ test('optional - 2', () => {
20
+ const schema = func().optional().required();
21
+ expect(schema).toHaveProperty('type', 'function');
22
+ expect(schema).toHaveProperty('isRequired', true);
23
+ });
24
+
25
+ test('optional - 3', () => {
26
+ const schema1 = func();
27
+ const schema2 = schema1.optional();
28
+ const e = (schema1 as Schema) === (schema2 as Schema);
29
+ const isRequiredEqual = (schema1 as any).isRequired !== schema2.isRequired;
30
+ expect(e).toEqual(false);
31
+ expect(isRequiredEqual).toEqual(true);
32
+ });
33
+
34
+ test('optional - 4', () => {
35
+ const schema1 = func().optional();
36
+ const schema2 = schema1.optional();
37
+ const e = (schema1 as Schema) === (schema2 as Schema);
38
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
39
+ expect(e).toEqual(true);
40
+ expect(isRequiredEqual).toEqual(true);
41
+ });
42
+
43
+ test('optional - 5', () => {
44
+ const schema1 = func();
45
+ const schema2 = schema1.required();
46
+ const e = (schema1 as Schema) === (schema2 as Schema);
47
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
48
+ expect(e).toEqual(true);
49
+ expect(isRequiredEqual).toEqual(true);
50
+ });
51
+
52
+ test('optional - 6', () => {
53
+ const schema1 = func().optional();
54
+ const schema2 = schema1.required();
55
+ const e = (schema1 as Schema) === (schema2 as Schema);
56
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
57
+ expect(e).toEqual(false);
58
+ expect(isRequiredEqual).toEqual(false);
59
+ });
60
+
61
+ test('optional - 7', () => {
62
+ const schema1 = func().optional().required();
63
+ const schema2 = schema1.required();
64
+ const e = (schema1 as Schema) === (schema2 as Schema);
65
+ const isRequiredEqual = (schema1 as any).isRequired === schema2.isRequired;
66
+ expect(e).toEqual(true);
67
+ expect(isRequiredEqual).toEqual(true);
68
+ });
69
+
70
+ test('nullable', () => {
71
+ const schema = func().nullable();
72
+ expect(schema).toHaveProperty('type', 'function');
73
+ expect(schema).toHaveProperty('isNullable', true);
74
+ });
75
+
76
+ test('nullable - 2', () => {
77
+ const schema = func().nullable().notNullable();
78
+ expect(schema).toHaveProperty('type', 'function');
79
+ expect(schema).toHaveProperty('isNullable', false);
80
+ });
81
+
82
+ test('nullable - 3', () => {
83
+ const schema1 = func();
84
+ const schema2 = schema1.nullable();
85
+ const e = (schema1 as Schema) === (schema2 as Schema);
86
+ const isNullableEqual = (schema1 as any).isNullable !== schema2.isNullable;
87
+ expect(e).toEqual(false);
88
+ expect(isNullableEqual).toEqual(true);
89
+ });
90
+
91
+ test('nullable - 4', () => {
92
+ const schema1 = func().nullable();
93
+ const schema2 = schema1.nullable();
94
+ const e = (schema1 as Schema) === (schema2 as Schema);
95
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
96
+ expect(e).toEqual(true);
97
+ expect(isNullableEqual).toEqual(true);
98
+ });
99
+
100
+ test('nullable - 5', () => {
101
+ const schema1 = func();
102
+ const schema2 = schema1.nullable();
103
+ const e = (schema1 as Schema) === (schema2 as Schema);
104
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
105
+ expect(e).toEqual(false);
106
+ expect(isNullableEqual).toEqual(false);
107
+ });
108
+
109
+ test('nullable - 6', () => {
110
+ const schema1 = func();
111
+ const schema2 = schema1.notNullable();
112
+ const e = (schema1 as Schema) === (schema2 as Schema);
113
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
114
+ expect(e).toEqual(true);
115
+ expect(isNullableEqual).toEqual(true);
116
+ });
117
+
118
+ test('nullable - 7', () => {
119
+ const schema1 = func().nullable();
120
+ const schema2 = schema1.notNullable();
121
+ const e = (schema1 as Schema) === (schema2 as Schema);
122
+ const isNullableEqual = (schema1 as any).isNullable === schema2.isNullable;
123
+ expect(e).toEqual(false);
124
+ expect(isNullableEqual).toEqual(false);
125
+ });
126
+
127
+ test('Clone', () => {
128
+ const schema1 = func().addValidator(() => ({ valid: true }));
129
+ const schema2 = schema1.clone();
130
+ const equal = (schema1 as any) === schema2;
131
+ expect(equal).toEqual(false);
132
+ const equal2 = deepEqual(schema1._schema, schema2._schema);
133
+ expect(equal2).toEqual(true);
134
+ });
@@ -0,0 +1,109 @@
1
+ import { Schema, Validator } from '../schema.js';
2
+ import { ISchemaBuilder, SchemaBuilder } from './SchemaBuilder.js';
3
+ import { defaultSchemas } from '../defaultSchemas.js';
4
+
5
+ export interface IFunctionSchemaBuilder<
6
+ TRequired extends boolean = true,
7
+ TNullable extends boolean = false
8
+ > extends ISchemaBuilder<TRequired, TNullable> {
9
+ optional(): IFunctionSchemaBuilder<false, TNullable>;
10
+ required(): IFunctionSchemaBuilder<true, TNullable>;
11
+ nullable(): IFunctionSchemaBuilder<TRequired, true>;
12
+ notNullable(): IFunctionSchemaBuilder<TRequired, false>;
13
+ }
14
+
15
+ export class FunctionSchemaBuilder<
16
+ TRequired extends boolean = true,
17
+ TNullable extends boolean = false
18
+ >
19
+ extends SchemaBuilder<TRequired, TNullable>
20
+ implements IFunctionSchemaBuilder<TRequired, TNullable>
21
+ {
22
+ protected readonly type = 'function';
23
+
24
+ public get _schema(): Schema {
25
+ return Object.assign(
26
+ {
27
+ type: this.type
28
+ },
29
+ this.getCommonSchema()
30
+ );
31
+ }
32
+
33
+ public clone(): this {
34
+ return FunctionSchemaBuilder.create(this._schema as any) as this;
35
+ }
36
+
37
+ public static create<
38
+ TRequired extends boolean = true,
39
+ TNullable extends boolean = false
40
+ >(obj?: {
41
+ isRequired: TRequired;
42
+ isNullable: TNullable;
43
+ validators?: Validator[];
44
+ preprocessor?:
45
+ | ((value: unknown) => unknown | Promise<unknown>)
46
+ | string;
47
+ }): IFunctionSchemaBuilder<TRequired, TNullable> {
48
+ return new FunctionSchemaBuilder(obj as any);
49
+ }
50
+
51
+ private constructor(obj: {
52
+ isRequired: TRequired;
53
+ isNullable: TNullable;
54
+ validators?: Validator[];
55
+ preprocessor?:
56
+ | ((value: unknown) => unknown | Promise<unknown>)
57
+ | string;
58
+ }) {
59
+ super(obj);
60
+ if (typeof obj !== 'object' || !obj) {
61
+ const defaultSchema = defaultSchemas['function'] as any;
62
+ this.isRequired = defaultSchema.isRequired;
63
+ this.isNullable = defaultSchema.isNullable;
64
+ }
65
+ }
66
+
67
+ optional(): IFunctionSchemaBuilder<false, TNullable> {
68
+ if (this.isRequired === false) {
69
+ return this as IFunctionSchemaBuilder<false, TNullable>;
70
+ }
71
+ return FunctionSchemaBuilder.create({
72
+ ...(this._schema as any),
73
+ isRequired: false
74
+ });
75
+ }
76
+
77
+ required(): IFunctionSchemaBuilder<true, TNullable> {
78
+ if (this.isRequired === true) {
79
+ return this as IFunctionSchemaBuilder<true, TNullable>;
80
+ }
81
+ return FunctionSchemaBuilder.create({
82
+ ...(this._schema as any),
83
+ isRequired: true
84
+ });
85
+ }
86
+
87
+ nullable(): IFunctionSchemaBuilder<TRequired, true> {
88
+ if (this.isNullable === true) {
89
+ return this as IFunctionSchemaBuilder<TRequired, true>;
90
+ }
91
+ return FunctionSchemaBuilder.create({
92
+ ...(this._schema as any),
93
+ isNullable: true
94
+ });
95
+ }
96
+
97
+ notNullable(): IFunctionSchemaBuilder<TRequired, false> {
98
+ if (this.isNullable === false) {
99
+ return this as IFunctionSchemaBuilder<TRequired, false>;
100
+ }
101
+ return FunctionSchemaBuilder.create({
102
+ ...(this._schema as any),
103
+ isNullable: false
104
+ });
105
+ }
106
+ }
107
+
108
+ export const func = (): IFunctionSchemaBuilder =>
109
+ FunctionSchemaBuilder.create();