@cleverbrush/schema 1.0.0-beta.4 → 1.0.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.
- package/README.md +118 -320
- package/dist/builders/AnySchemaBuilder.d.ts +76 -0
- package/dist/builders/AnySchemaBuilder.js +112 -0
- package/dist/builders/ArraySchemaBuilder.d.ts +112 -14
- package/dist/builders/ArraySchemaBuilder.js +254 -111
- package/dist/builders/BooleanSchemaBuilder.d.ts +69 -29
- package/dist/builders/BooleanSchemaBuilder.js +134 -74
- package/dist/builders/DateSchemaBuilder.d.ts +177 -0
- package/dist/builders/DateSchemaBuilder.js +433 -0
- package/dist/builders/FunctionSchemaBuilder.d.ts +59 -23
- package/dist/builders/FunctionSchemaBuilder.js +103 -56
- package/dist/builders/NumberSchemaBuilder.d.ts +159 -59
- package/dist/builders/NumberSchemaBuilder.js +345 -165
- package/dist/builders/ObjectSchemaBuilder.d.ts +357 -81
- package/dist/builders/ObjectSchemaBuilder.js +519 -283
- package/dist/builders/SchemaBuilder.d.ts +158 -34
- package/dist/builders/SchemaBuilder.js +258 -71
- package/dist/builders/StringSchemaBuilder.d.ts +138 -13
- package/dist/builders/StringSchemaBuilder.js +261 -115
- package/dist/builders/UnionSchemaBuilder.d.ts +129 -9
- package/dist/builders/UnionSchemaBuilder.js +196 -75
- package/dist/index.d.ts +20 -40
- package/dist/index.js +19 -32
- package/dist/utils/transaction.d.ts +46 -0
- package/dist/utils/transaction.js +178 -0
- package/package.json +27 -14
- package/dist/defaultSchemas.d.ts +0 -4
- package/dist/defaultSchemas.js +0 -45
- package/dist/schema.d.ts +0 -230
- package/dist/schema.js +0 -2
- package/dist/schemaRegistry.d.ts +0 -49
- package/dist/schemaRegistry.js +0 -278
- package/dist/validators/validateArray.d.ts +0 -3
- package/dist/validators/validateArray.js +0 -60
- package/dist/validators/validateBoolean.d.ts +0 -2
- package/dist/validators/validateBoolean.js +0 -30
- package/dist/validators/validateFunction.d.ts +0 -2
- package/dist/validators/validateFunction.js +0 -21
- package/dist/validators/validateNumber.d.ts +0 -2
- package/dist/validators/validateNumber.js +0 -69
- package/dist/validators/validateObject.d.ts +0 -3
- package/dist/validators/validateObject.js +0 -95
- package/dist/validators/validateString.d.ts +0 -2
- package/dist/validators/validateString.js +0 -50
- package/dist/validators/validateUnion.d.ts +0 -3
- package/dist/validators/validateUnion.js +0 -30
- package/src/builders/ArraySchemaBuilder.test.ts +0 -270
- package/src/builders/ArraySchemaBuilder.ts +0 -381
- package/src/builders/BooleanSchemaBuilder.test.ts +0 -196
- package/src/builders/BooleanSchemaBuilder.ts +0 -155
- package/src/builders/FunctionSchemaBuilder.test.ts +0 -134
- package/src/builders/FunctionSchemaBuilder.ts +0 -109
- package/src/builders/NumberSchemaBuilder.test.ts +0 -493
- package/src/builders/NumberSchemaBuilder.ts +0 -789
- package/src/builders/ObjectSchemaBuilder.test.ts +0 -657
- package/src/builders/ObjectSchemaBuilder.ts +0 -794
- package/src/builders/SchemaBuilder.test.ts +0 -73
- package/src/builders/SchemaBuilder.ts +0 -135
- package/src/builders/StringSchemaBuilder.test.ts +0 -318
- package/src/builders/StringSchemaBuilder.ts +0 -392
- package/src/builders/UnionSchemaBuilder.test.ts +0 -162
- package/src/builders/UnionSchemaBuilder.ts +0 -154
- package/src/defaultSchemas.ts +0 -44
- package/src/index.ts +0 -66
- package/src/schema.ts +0 -827
- package/src/schemaRegistry.builders.test.ts +0 -1393
- package/src/schemaRegistry.test.ts +0 -118
- package/src/schemaRegistry.ts +0 -461
- package/src/validators/validateArray.ts +0 -76
- package/src/validators/validateBoolean.ts +0 -36
- package/src/validators/validateFunction.ts +0 -25
- package/src/validators/validateNumber.ts +0 -82
- package/src/validators/validateObject.ts +0 -119
- package/src/validators/validateString.ts +0 -59
- package/src/validators/validateUnion.ts +0 -36
- package/tsconfig.json +0 -16
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { deepEqual } from '@cleverbrush/deep';
|
|
2
|
-
|
|
3
|
-
import { ObjectSchema } from './schema.js';
|
|
4
|
-
import SchemaRegistry from './schemaRegistry.js';
|
|
5
|
-
|
|
6
|
-
test('Can add schema', () => {
|
|
7
|
-
const validator = new SchemaRegistry().addSchema('something', {
|
|
8
|
-
type: 'object',
|
|
9
|
-
properties: {
|
|
10
|
-
a: 'string'
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
expect(validator.schemas.something).toBeDefined();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('Throws when not array or object is passed to addSchemaType', () => {
|
|
17
|
-
expect(() => {
|
|
18
|
-
new SchemaRegistry().addSchema('something', 1234 as any);
|
|
19
|
-
}).toThrow();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('Error thrown on adding a schema with duplicate name', () => {
|
|
23
|
-
expect(() =>
|
|
24
|
-
new SchemaRegistry()
|
|
25
|
-
.addSchema('smth', {} as any)
|
|
26
|
-
.addSchema('smth', {} as any)
|
|
27
|
-
).toThrow();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('Receiving the same schema after add', () => {
|
|
31
|
-
const schema: ObjectSchema<{ name: string }> = {
|
|
32
|
-
type: 'object',
|
|
33
|
-
properties: {
|
|
34
|
-
name: 'string'
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const validator = new SchemaRegistry().addSchema('something', schema);
|
|
38
|
-
|
|
39
|
-
expect(
|
|
40
|
-
deepEqual(
|
|
41
|
-
{ ...schema, type: 'object' },
|
|
42
|
-
validator.schemas.something.schema
|
|
43
|
-
)
|
|
44
|
-
).toEqual(true);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('Schemas property is cached when reading', () => {
|
|
48
|
-
const validator = new SchemaRegistry().addSchema('something', {});
|
|
49
|
-
expect(validator.schemas).toEqual(validator.schemas);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('Schemas property is updated after adding a new schema', () => {
|
|
53
|
-
let validator = new SchemaRegistry().addSchema(
|
|
54
|
-
'something',
|
|
55
|
-
{} as ObjectSchema<any>
|
|
56
|
-
);
|
|
57
|
-
const s = validator.schemas;
|
|
58
|
-
validator = validator.addSchema('another', {});
|
|
59
|
-
expect(s).not.toEqual(validator.schemas);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('Trows when trying to add a schema with name = "number"', () => {
|
|
63
|
-
const validator = new SchemaRegistry();
|
|
64
|
-
expect(() =>
|
|
65
|
-
validator.addSchema('number', {} as ObjectSchema<any>)
|
|
66
|
-
).toThrow();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('Trows when trying to add a schema with name = "array"', () => {
|
|
70
|
-
const validator = new SchemaRegistry();
|
|
71
|
-
expect(() =>
|
|
72
|
-
validator.addSchema('array', {} as ObjectSchema<any>)
|
|
73
|
-
).toThrow();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('Trows when trying to add a schema with name = "string"', () => {
|
|
77
|
-
const validator = new SchemaRegistry();
|
|
78
|
-
expect(() =>
|
|
79
|
-
validator.addSchema('string', {} as ObjectSchema<any>)
|
|
80
|
-
).toThrow();
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test('Throws if schema name is empty', () => {
|
|
84
|
-
const validator = new SchemaRegistry();
|
|
85
|
-
expect(() => validator.addSchema('', {} as ObjectSchema<any>)).toThrow();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('Throws if schema name is not a string', () => {
|
|
89
|
-
const validator = new SchemaRegistry();
|
|
90
|
-
expect(() =>
|
|
91
|
-
validator.addSchema(
|
|
92
|
-
new Date() as any as string,
|
|
93
|
-
{} as ObjectSchema<any>
|
|
94
|
-
)
|
|
95
|
-
).toThrow();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test('Throws if schema is not an object', () => {
|
|
99
|
-
const validator = new SchemaRegistry();
|
|
100
|
-
expect(() =>
|
|
101
|
-
validator.addSchema('string', 'string' as any as ObjectSchema<any>)
|
|
102
|
-
).toThrow();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('Preprocessors - 1', async () => {
|
|
106
|
-
expect(() => {
|
|
107
|
-
new SchemaRegistry().addPreprocessor('BornAt', 123 as any);
|
|
108
|
-
}).toThrow();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test('Submodules - 1', async () => {
|
|
112
|
-
const validator = new SchemaRegistry().addSchema('Module1.Schema1', {});
|
|
113
|
-
|
|
114
|
-
const result = validator.schemas;
|
|
115
|
-
|
|
116
|
-
expect(result).toHaveProperty('Module1');
|
|
117
|
-
expect(result).toHaveProperty('Module1.Schema1');
|
|
118
|
-
});
|
package/src/schemaRegistry.ts
DELETED
|
@@ -1,461 +0,0 @@
|
|
|
1
|
-
import { ISchemaRegistry as ISchemaRegistry, Unfold } from './index.js';
|
|
2
|
-
import { validateNumber } from './validators/validateNumber.js';
|
|
3
|
-
import { validateBoolean } from './validators/validateBoolean.js';
|
|
4
|
-
import { validateString } from './validators/validateString.js';
|
|
5
|
-
import { validateArray } from './validators/validateArray.js';
|
|
6
|
-
import { validateObject } from './validators/validateObject.js';
|
|
7
|
-
import { validateUnion } from './validators/validateUnion.js';
|
|
8
|
-
import { validateFunction } from './validators/validateFunction.js';
|
|
9
|
-
import {
|
|
10
|
-
ArraySchema,
|
|
11
|
-
BooleanSchema,
|
|
12
|
-
DefaultSchemaType,
|
|
13
|
-
NumberSchema,
|
|
14
|
-
ObjectSchema,
|
|
15
|
-
Schema,
|
|
16
|
-
ReduceSchemaBuilder,
|
|
17
|
-
SchemaSpecification,
|
|
18
|
-
StringSchema,
|
|
19
|
-
ValidationResult,
|
|
20
|
-
ValidationResultRaw,
|
|
21
|
-
ExpandSchemaBuilder,
|
|
22
|
-
FunctionSchema
|
|
23
|
-
} from './schema.js';
|
|
24
|
-
|
|
25
|
-
import { number } from './builders/NumberSchemaBuilder.js';
|
|
26
|
-
import { union } from './builders/UnionSchemaBuilder.js';
|
|
27
|
-
import { object } from './builders/ObjectSchemaBuilder.js';
|
|
28
|
-
import { string } from './builders/StringSchemaBuilder.js';
|
|
29
|
-
import { boolean } from './builders/BooleanSchemaBuilder.js';
|
|
30
|
-
import { array } from './builders/ArraySchemaBuilder.js';
|
|
31
|
-
import { func } from './builders/FunctionSchemaBuilder.js';
|
|
32
|
-
import { defaultSchemas } from './defaultSchemas.js';
|
|
33
|
-
import { ISchemaBuilder, SchemaBuilder } from './builders/SchemaBuilder.js';
|
|
34
|
-
|
|
35
|
-
const defaultSchemaNames = ['string', 'boolean', 'number', 'array', 'function'];
|
|
36
|
-
|
|
37
|
-
const defaultSchemasValidationStrategies = {
|
|
38
|
-
number: (obj: any, schema: NumberSchema): Promise<ValidationResult> =>
|
|
39
|
-
validateNumber(obj, schema),
|
|
40
|
-
boolean: (obj: any, schema: BooleanSchema): Promise<ValidationResult> =>
|
|
41
|
-
validateBoolean(obj, schema),
|
|
42
|
-
string: (obj: any, schema: StringSchema): Promise<ValidationResult> =>
|
|
43
|
-
validateString(obj, schema),
|
|
44
|
-
array: (
|
|
45
|
-
obj: any,
|
|
46
|
-
schema: ArraySchema<any>,
|
|
47
|
-
validator: SchemaRegistry<any>
|
|
48
|
-
): Promise<ValidationResult> => validateArray(obj, schema, validator),
|
|
49
|
-
function: (obj: any, schema: FunctionSchema): Promise<ValidationResult> =>
|
|
50
|
-
validateFunction(obj, schema)
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const isDefaultType = (name: string): boolean =>
|
|
54
|
-
defaultSchemaNames.indexOf(name) !== -1;
|
|
55
|
-
|
|
56
|
-
export default class SchemaRegistry<T extends Record<string, Schema> = {}>
|
|
57
|
-
implements ISchemaRegistry<T>
|
|
58
|
-
{
|
|
59
|
-
private _schemasMap = new Map<string, Schema>();
|
|
60
|
-
private _schemasCache: Unfold<T> = null;
|
|
61
|
-
private _preprocessorsMap = new Map<
|
|
62
|
-
string,
|
|
63
|
-
(value: unknown) => unknown | Promise<unknown> | undefined
|
|
64
|
-
>();
|
|
65
|
-
|
|
66
|
-
public get preprocessors(): Map<string, (value: unknown) => unknown> {
|
|
67
|
-
return this._preprocessorsMap;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public addPreprocessor(
|
|
71
|
-
name: string,
|
|
72
|
-
preprocessor: (value: unknown) => unknown | Promise<unknown>
|
|
73
|
-
): SchemaRegistry<T> {
|
|
74
|
-
if (this._preprocessorsMap.has(name))
|
|
75
|
-
throw new Error(`Preprocessor '${name}' is already registered`);
|
|
76
|
-
if (typeof preprocessor !== 'function') {
|
|
77
|
-
throw new Error('preprocessor must be a function');
|
|
78
|
-
}
|
|
79
|
-
this._preprocessorsMap.set(name, preprocessor);
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private _aliasBuilder = <TSchemaName extends keyof T>(
|
|
84
|
-
schemaName: TSchemaName
|
|
85
|
-
): ExpandSchemaBuilder<T[TSchemaName]> => {
|
|
86
|
-
if (typeof schemaName !== 'string' || !schemaName)
|
|
87
|
-
throw new Error('schemaName must be non-empty string');
|
|
88
|
-
const aliasSchema = this._schemasMap.get(schemaName.toString());
|
|
89
|
-
if (!aliasSchema)
|
|
90
|
-
throw new Error(`Schema name ${schemaName} is not defined.`);
|
|
91
|
-
return aliasSchema;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
private _externalAlias = <
|
|
95
|
-
TExternalSchemaName extends keyof TExternalAliases,
|
|
96
|
-
TExternalAliases extends Record<string, any>,
|
|
97
|
-
TExternalSchemaRegistry extends ISchemaRegistry<TExternalAliases>
|
|
98
|
-
>(
|
|
99
|
-
registry: TExternalSchemaRegistry,
|
|
100
|
-
schemaName: TExternalSchemaName
|
|
101
|
-
): ExpandSchemaBuilder<TExternalAliases[TExternalSchemaName]> => {
|
|
102
|
-
if (typeof schemaName !== 'string' || !schemaName)
|
|
103
|
-
throw new Error('schemaName must be non-empty string');
|
|
104
|
-
// TODO: accessing private property here...
|
|
105
|
-
const externalSchema = (registry as any)._schemasMap.get(schemaName);
|
|
106
|
-
if (!externalSchema)
|
|
107
|
-
throw new Error(`Schema name ${schemaName} is not defined.`);
|
|
108
|
-
return externalSchema;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
public addSchemaFrom<
|
|
112
|
-
TOldName extends keyof T,
|
|
113
|
-
TName extends string,
|
|
114
|
-
TParam extends
|
|
115
|
-
| Record<string, any>
|
|
116
|
-
| ((params: {
|
|
117
|
-
base: ExpandSchemaBuilder<T[TOldName]>;
|
|
118
|
-
boolean: typeof boolean;
|
|
119
|
-
func: typeof func;
|
|
120
|
-
array: typeof array;
|
|
121
|
-
string: typeof string;
|
|
122
|
-
number: typeof number;
|
|
123
|
-
union: typeof union;
|
|
124
|
-
object: typeof object;
|
|
125
|
-
alias: <TSchemaName extends keyof T>(
|
|
126
|
-
schemaName: TSchemaName
|
|
127
|
-
) => ExpandSchemaBuilder<T[TSchemaName]>;
|
|
128
|
-
}) => TSchema),
|
|
129
|
-
TSchema extends Schema | ISchemaBuilder
|
|
130
|
-
>(
|
|
131
|
-
oldName: TOldName,
|
|
132
|
-
name: TName,
|
|
133
|
-
param: TParam
|
|
134
|
-
): SchemaRegistry<{
|
|
135
|
-
[key in keyof T | TName]: key extends keyof T
|
|
136
|
-
? T[key]
|
|
137
|
-
: TParam extends (...args: any[]) => any
|
|
138
|
-
? ReduceSchemaBuilder<ReturnType<TParam>>
|
|
139
|
-
: TParam;
|
|
140
|
-
}> {
|
|
141
|
-
if (!this._schemasMap.has(oldName.toString())) {
|
|
142
|
-
throw new Error(`unknown schema name ${oldName.toString()}`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const oldSchema = this._schemasMap.get(oldName.toString());
|
|
146
|
-
|
|
147
|
-
const schema =
|
|
148
|
-
typeof param === 'function'
|
|
149
|
-
? param({
|
|
150
|
-
base: oldSchema,
|
|
151
|
-
alias: this._aliasBuilder,
|
|
152
|
-
array,
|
|
153
|
-
boolean,
|
|
154
|
-
func,
|
|
155
|
-
number,
|
|
156
|
-
object,
|
|
157
|
-
string,
|
|
158
|
-
union
|
|
159
|
-
})
|
|
160
|
-
: param;
|
|
161
|
-
|
|
162
|
-
if (Array.isArray(schema)) {
|
|
163
|
-
this._schemasMap.set(name.toString(), schema as Schema);
|
|
164
|
-
this._schemasCache = null;
|
|
165
|
-
return this as any;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (typeof schema !== 'object')
|
|
169
|
-
throw new Error('Array or Object is required');
|
|
170
|
-
this._schemasMap.set(name.toString(), {
|
|
171
|
-
...(schema instanceof SchemaBuilder
|
|
172
|
-
? schema._schema
|
|
173
|
-
: (schema as any))
|
|
174
|
-
} as any as Schema);
|
|
175
|
-
|
|
176
|
-
this._schemasCache = null;
|
|
177
|
-
return this as any;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
public addSchema<
|
|
181
|
-
TName extends string,
|
|
182
|
-
TParam extends
|
|
183
|
-
| Record<string, any>
|
|
184
|
-
| ((params: {
|
|
185
|
-
boolean: typeof boolean;
|
|
186
|
-
array: typeof array;
|
|
187
|
-
string: typeof string;
|
|
188
|
-
number: typeof number;
|
|
189
|
-
union: typeof union;
|
|
190
|
-
object: typeof object;
|
|
191
|
-
func: typeof func;
|
|
192
|
-
alias: <TSchemaName extends keyof T>(
|
|
193
|
-
schemaName: TSchemaName
|
|
194
|
-
) => ExpandSchemaBuilder<T[TSchemaName]>;
|
|
195
|
-
external: <
|
|
196
|
-
TRegistryKeys,
|
|
197
|
-
TSchemaName extends keyof TRegistryKeys
|
|
198
|
-
>(
|
|
199
|
-
registry: SchemaRegistry<TRegistryKeys>,
|
|
200
|
-
schemaName: TSchemaName
|
|
201
|
-
) => ExpandSchemaBuilder<TRegistryKeys[TSchemaName]>;
|
|
202
|
-
}) => TSchema),
|
|
203
|
-
TSchema extends Schema | ISchemaBuilder
|
|
204
|
-
>(
|
|
205
|
-
name: TName,
|
|
206
|
-
param: TParam
|
|
207
|
-
): SchemaRegistry<{
|
|
208
|
-
[key in keyof T | TName]: key extends keyof T
|
|
209
|
-
? T[key]
|
|
210
|
-
: TParam extends (...args: any[]) => any
|
|
211
|
-
? ReduceSchemaBuilder<ReturnType<TParam>>
|
|
212
|
-
: TParam;
|
|
213
|
-
}> {
|
|
214
|
-
if (typeof name !== 'string' || !name)
|
|
215
|
-
throw new Error('Name is required');
|
|
216
|
-
|
|
217
|
-
if (isDefaultType(name.toString()))
|
|
218
|
-
throw new Error(
|
|
219
|
-
`You can't add a schema named "${name}" because it's a name of a default schema, please consider another name to be used`
|
|
220
|
-
);
|
|
221
|
-
if (this._schemasMap.has(name.toString())) {
|
|
222
|
-
throw new Error(`Schema "${name}" already exists`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const schema =
|
|
226
|
-
typeof param === 'function'
|
|
227
|
-
? param({
|
|
228
|
-
alias: this._aliasBuilder,
|
|
229
|
-
external: this._externalAlias,
|
|
230
|
-
array,
|
|
231
|
-
boolean,
|
|
232
|
-
number,
|
|
233
|
-
object,
|
|
234
|
-
string,
|
|
235
|
-
union,
|
|
236
|
-
func
|
|
237
|
-
})
|
|
238
|
-
: param;
|
|
239
|
-
|
|
240
|
-
if (Array.isArray(schema)) {
|
|
241
|
-
this._schemasMap.set(name.toString(), schema as Schema);
|
|
242
|
-
this._schemasCache = null;
|
|
243
|
-
return this as any;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (typeof schema !== 'object')
|
|
247
|
-
throw new Error('Array or Object is required');
|
|
248
|
-
this._schemasMap.set(
|
|
249
|
-
name.toString(),
|
|
250
|
-
schema instanceof SchemaBuilder ? schema.clone() : schema
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
this._schemasCache = null;
|
|
254
|
-
return this as any;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
public get schemas(): Unfold<T> {
|
|
258
|
-
if (this._schemasCache) return this._schemasCache;
|
|
259
|
-
const res = {};
|
|
260
|
-
for (const key of this._schemasMap.keys()) {
|
|
261
|
-
const parts = key.split('.');
|
|
262
|
-
let curr = res;
|
|
263
|
-
for (let i = 0; i < parts.length; i++) {
|
|
264
|
-
if (i === parts.length - 1) {
|
|
265
|
-
curr[parts[i]] = {
|
|
266
|
-
validate: async (value: any): Promise<any> => {
|
|
267
|
-
const result = await this.validate(
|
|
268
|
-
this._schemasMap.get(key),
|
|
269
|
-
value
|
|
270
|
-
);
|
|
271
|
-
if (!result.valid) {
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
274
|
-
return {
|
|
275
|
-
...result,
|
|
276
|
-
object: value
|
|
277
|
-
};
|
|
278
|
-
},
|
|
279
|
-
schema: this._schemasMap.get(key)
|
|
280
|
-
};
|
|
281
|
-
} else {
|
|
282
|
-
if (typeof curr[parts[i]] === 'undefined') {
|
|
283
|
-
curr[parts[i]] = {};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
curr = curr[parts[i]];
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
this._schemasCache = res as Unfold<T>;
|
|
290
|
-
return this._schemasCache;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private async validateDefaultType(
|
|
294
|
-
name: DefaultSchemaType,
|
|
295
|
-
value: any,
|
|
296
|
-
mergeSchema?: Schema
|
|
297
|
-
): Promise<ValidationResult> {
|
|
298
|
-
const strategy = defaultSchemasValidationStrategies[name] as (
|
|
299
|
-
obj: any,
|
|
300
|
-
schema: Schema,
|
|
301
|
-
validator: SchemaRegistry<any>
|
|
302
|
-
) => ValidationResult;
|
|
303
|
-
let finalSchema = defaultSchemas[name] as SchemaSpecification;
|
|
304
|
-
if (strategy) {
|
|
305
|
-
if (typeof mergeSchema === 'object' && mergeSchema) {
|
|
306
|
-
finalSchema = Object.assign({}, finalSchema, mergeSchema);
|
|
307
|
-
}
|
|
308
|
-
if (typeof mergeSchema === 'number') {
|
|
309
|
-
finalSchema = {
|
|
310
|
-
...finalSchema,
|
|
311
|
-
equals: mergeSchema
|
|
312
|
-
} as NumberSchema;
|
|
313
|
-
mergeSchema;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
let preliminaryResult = await strategy(
|
|
317
|
-
value,
|
|
318
|
-
finalSchema,
|
|
319
|
-
this as any
|
|
320
|
-
);
|
|
321
|
-
if (!preliminaryResult.valid) return preliminaryResult;
|
|
322
|
-
|
|
323
|
-
preliminaryResult = await this.checkValidators(finalSchema, value);
|
|
324
|
-
|
|
325
|
-
return preliminaryResult;
|
|
326
|
-
}
|
|
327
|
-
throw new Error('not implemented');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
private async checkValidators(
|
|
331
|
-
schema: SchemaSpecification,
|
|
332
|
-
value: any
|
|
333
|
-
): Promise<ValidationResult> {
|
|
334
|
-
if (!schema.isRequired && typeof value === 'undefined') {
|
|
335
|
-
return {
|
|
336
|
-
valid: true
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
if (Array.isArray(schema.validators)) {
|
|
340
|
-
const validatorsResults = await Promise.allSettled(
|
|
341
|
-
schema.validators.map((v) => Promise.resolve(v(value)))
|
|
342
|
-
);
|
|
343
|
-
const rejections = validatorsResults
|
|
344
|
-
.filter((f) => f.status === 'rejected')
|
|
345
|
-
.map((f: PromiseRejectedResult) => f.reason);
|
|
346
|
-
const errors = validatorsResults
|
|
347
|
-
.filter(
|
|
348
|
-
(f) =>
|
|
349
|
-
f.status === 'fulfilled' &&
|
|
350
|
-
typeof f.value !== 'boolean' &&
|
|
351
|
-
f.value.valid === false
|
|
352
|
-
)
|
|
353
|
-
.map(
|
|
354
|
-
(f: PromiseFulfilledResult<ValidationResultRaw>) => f.value
|
|
355
|
-
)
|
|
356
|
-
.map((f: ValidationResultRaw) => f.errors);
|
|
357
|
-
|
|
358
|
-
if (rejections.length === 0 && errors.length === 0) {
|
|
359
|
-
return {
|
|
360
|
-
valid: true
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
return {
|
|
364
|
-
valid: false,
|
|
365
|
-
errors: [...rejections, ...errors]
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
valid: true
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
public async validate(
|
|
374
|
-
schemaToValidate: keyof T | Schema,
|
|
375
|
-
obj: any
|
|
376
|
-
): Promise<ValidationResult> {
|
|
377
|
-
if (!schemaToValidate) throw new Error('schemaName is required');
|
|
378
|
-
const schema =
|
|
379
|
-
schemaToValidate instanceof SchemaBuilder
|
|
380
|
-
? schemaToValidate._schema
|
|
381
|
-
: schemaToValidate;
|
|
382
|
-
if (typeof schema === 'string') {
|
|
383
|
-
if (isDefaultType(schema)) {
|
|
384
|
-
return await this.validateDefaultType(
|
|
385
|
-
schema as DefaultSchemaType,
|
|
386
|
-
obj
|
|
387
|
-
);
|
|
388
|
-
} else if (typeof this._schemasMap.get(schema) !== 'undefined') {
|
|
389
|
-
if (Array.isArray(this._schemasMap.get(schema))) {
|
|
390
|
-
return this.validate(this._schemasMap.get(schema), obj);
|
|
391
|
-
}
|
|
392
|
-
const objSchema = Object.assign(
|
|
393
|
-
{},
|
|
394
|
-
defaultSchemas.object,
|
|
395
|
-
this._schemasMap.get(schema)
|
|
396
|
-
) as ObjectSchema;
|
|
397
|
-
const res = await validateObject(
|
|
398
|
-
obj,
|
|
399
|
-
objSchema as any,
|
|
400
|
-
this as any
|
|
401
|
-
);
|
|
402
|
-
if (!res.valid) return res;
|
|
403
|
-
return await this.checkValidators(objSchema, obj);
|
|
404
|
-
} else {
|
|
405
|
-
return await this.validateDefaultType('string', obj, {
|
|
406
|
-
type: 'string',
|
|
407
|
-
equals: schema
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (Array.isArray(schema)) {
|
|
413
|
-
for (let i = 0; i < schema.length; i++) {
|
|
414
|
-
const res = await this.validate(schema[i], obj);
|
|
415
|
-
if (res.valid) {
|
|
416
|
-
return res;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
valid: false,
|
|
421
|
-
errors: ['object does not match any schema']
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if (typeof schema === 'number') {
|
|
426
|
-
return await this.validateDefaultType('number', obj, schema);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (typeof schema === 'object') {
|
|
430
|
-
const spec = schema as SchemaSpecification;
|
|
431
|
-
if (typeof spec.type !== 'string')
|
|
432
|
-
throw new Error('Schema has no type');
|
|
433
|
-
|
|
434
|
-
if (isDefaultType(spec.type)) {
|
|
435
|
-
return await this.validateDefaultType(
|
|
436
|
-
spec.type as DefaultSchemaType,
|
|
437
|
-
obj,
|
|
438
|
-
schema
|
|
439
|
-
);
|
|
440
|
-
} else if (spec.type === 'union') {
|
|
441
|
-
return await validateUnion(obj, spec, this as any);
|
|
442
|
-
} else if (spec.type === 'object') {
|
|
443
|
-
const preliminaryResult = await validateObject(
|
|
444
|
-
obj,
|
|
445
|
-
schema as ObjectSchema<any>,
|
|
446
|
-
this as any
|
|
447
|
-
);
|
|
448
|
-
if (!preliminaryResult.valid) return preliminaryResult;
|
|
449
|
-
|
|
450
|
-
return await this.checkValidators(
|
|
451
|
-
schema as SchemaSpecification,
|
|
452
|
-
obj
|
|
453
|
-
);
|
|
454
|
-
} else if (spec.type === 'function') {
|
|
455
|
-
return await validateFunction(obj, spec);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
throw new Error("Couldn't understand the Schema provided");
|
|
460
|
-
}
|
|
461
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { ArraySchema, ValidationResult } from '../schema.js';
|
|
2
|
-
import SchemaRegistry from '../schemaRegistry.js';
|
|
3
|
-
|
|
4
|
-
export const validateArray = async (
|
|
5
|
-
obj: any,
|
|
6
|
-
schema: ArraySchema<any>,
|
|
7
|
-
validator: SchemaRegistry<any>
|
|
8
|
-
): Promise<ValidationResult> => {
|
|
9
|
-
if (
|
|
10
|
-
typeof obj === 'undefined' &&
|
|
11
|
-
typeof schema === 'object' &&
|
|
12
|
-
schema.isRequired === false
|
|
13
|
-
) {
|
|
14
|
-
return {
|
|
15
|
-
valid: true
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
if (!Array.isArray(obj))
|
|
19
|
-
return {
|
|
20
|
-
valid: false,
|
|
21
|
-
errors: ['expected type array']
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
if (schema.preprocessor) {
|
|
25
|
-
const preprocessor =
|
|
26
|
-
typeof schema.preprocessor === 'function'
|
|
27
|
-
? schema.preprocessor
|
|
28
|
-
: validator.preprocessors.get(schema.preprocessor);
|
|
29
|
-
if (typeof preprocessor !== 'function') {
|
|
30
|
-
throw new Error(`unknown preprocessor '${schema.preprocessor}'`);
|
|
31
|
-
}
|
|
32
|
-
for (let i = 0; i < obj.length; i++) {
|
|
33
|
-
obj[i] = await Promise.resolve(preprocessor(obj[i]));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (typeof schema.minLength === 'number' && obj.length < schema.minLength) {
|
|
38
|
-
return {
|
|
39
|
-
valid: false,
|
|
40
|
-
errors: [`expected to be at least ${schema.minLength} chars long`]
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (typeof schema.maxLength === 'number' && obj.length > schema.maxLength) {
|
|
45
|
-
return {
|
|
46
|
-
valid: false,
|
|
47
|
-
errors: [`expected to be at most ${schema.maxLength} chars long`]
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (typeof schema.ofType !== 'undefined') {
|
|
52
|
-
const results = await Promise.all(
|
|
53
|
-
obj.map((i) => validator.validate(schema.ofType, i))
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const errors = results
|
|
57
|
-
.filter((r) => !r.valid)
|
|
58
|
-
.map((r) => r.errors)
|
|
59
|
-
.flat(Infinity) as Array<string>;
|
|
60
|
-
|
|
61
|
-
if (errors.length) {
|
|
62
|
-
return {
|
|
63
|
-
valid: false,
|
|
64
|
-
errors
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
valid: true
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
valid: true
|
|
75
|
-
};
|
|
76
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { BooleanSchema, ValidationResult } from '../schema.js';
|
|
2
|
-
|
|
3
|
-
export const validateBoolean = async (
|
|
4
|
-
obj: any,
|
|
5
|
-
schema: BooleanSchema
|
|
6
|
-
): Promise<ValidationResult> => {
|
|
7
|
-
if (
|
|
8
|
-
typeof obj === 'undefined' &&
|
|
9
|
-
typeof schema === 'object' &&
|
|
10
|
-
schema.isRequired === false
|
|
11
|
-
) {
|
|
12
|
-
return {
|
|
13
|
-
valid: true
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
if (typeof obj !== 'boolean')
|
|
17
|
-
return {
|
|
18
|
-
valid: false,
|
|
19
|
-
errors: [`expected type boolean, but saw ${typeof obj}`]
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const bool = obj as boolean;
|
|
23
|
-
|
|
24
|
-
if (typeof schema.equals === 'boolean') {
|
|
25
|
-
return schema.equals === bool
|
|
26
|
-
? { valid: true }
|
|
27
|
-
: {
|
|
28
|
-
valid: false,
|
|
29
|
-
errors: [`must be equal to ${schema.equals}`]
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
valid: true
|
|
35
|
-
};
|
|
36
|
-
};
|