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