@travetto/schema 4.0.0-rc.6 → 4.0.0-rc.7

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 CHANGED
@@ -220,20 +220,22 @@ Validation Failed {
220
220
  "category": "data",
221
221
  "type": "ValidationResultError",
222
222
  "at": "2029-03-14T04:00:00.618Z",
223
- "errors": [
224
- {
225
- "kind": "type",
226
- "type": "number",
227
- "message": "age is not a valid number",
228
- "path": "age"
229
- },
230
- {
231
- "kind": "required",
232
- "active": true,
233
- "message": "address.street2 is required",
234
- "path": "address.street2"
235
- }
236
- ]
223
+ "details": {
224
+ "errors": [
225
+ {
226
+ "kind": "type",
227
+ "type": "number",
228
+ "message": "age is not a valid number",
229
+ "path": "age"
230
+ },
231
+ {
232
+ "kind": "required",
233
+ "active": true,
234
+ "message": "address.street2 is required",
235
+ "path": "address.street2"
236
+ }
237
+ ]
238
+ }
237
239
  }
238
240
  ```
239
241
 
@@ -363,14 +365,16 @@ Validation Failed {
363
365
  "category": "data",
364
366
  "type": "ValidationResultError",
365
367
  "at": "2029-03-14T04:00:00.837Z",
366
- "errors": [
367
- {
368
- "kind": "type",
369
- "type": "PointImpl",
370
- "message": "point is not a valid PointImpl",
371
- "path": "point"
372
- }
373
- ]
368
+ "details": {
369
+ "errors": [
370
+ {
371
+ "kind": "type",
372
+ "type": "PointImpl",
373
+ "message": "point is not a valid PointImpl",
374
+ "path": "point"
375
+ }
376
+ ]
377
+ }
374
378
  }
375
379
  ```
376
380
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/schema",
3
- "version": "4.0.0-rc.6",
3
+ "version": "4.0.0-rc.7",
4
4
  "description": "Data type registry for runtime validation, reflection and binding.",
5
5
  "keywords": [
6
6
  "schema",
@@ -27,10 +27,10 @@
27
27
  "directory": "module/schema"
28
28
  },
29
29
  "dependencies": {
30
- "@travetto/registry": "^4.0.0-rc.6"
30
+ "@travetto/registry": "^4.0.0-rc.7"
31
31
  },
32
32
  "peerDependencies": {
33
- "@travetto/transformer": "^4.0.0-rc.5"
33
+ "@travetto/transformer": "^4.0.0-rc.6"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@travetto/transformer": {
@@ -56,16 +56,7 @@ export class SchemaValidator {
56
56
  * @param relative The relative path of object traversal
57
57
  */
58
58
  static #validateFieldSchema(fieldSchema: FieldConfig, val: unknown, relative: string = ''): ValidationError[] {
59
- return this.#validateFieldSchemaRaw(fieldSchema, val, `${relative}${relative ? '.' : ''}${fieldSchema.name}`);
60
- }
61
-
62
- /**
63
- * Validate a single field config against a passed in value
64
- * @param fieldSchema The field schema configuration
65
- * @param val The raw value, could be an array or not
66
- * @param path The current path of validation traversal
67
- */
68
- static #validateFieldSchemaRaw(fieldSchema: FieldConfig, val: unknown, path: string = ''): ValidationError[] {
59
+ const path = `${relative}${relative ? '.' : ''}${fieldSchema.name}`;
69
60
  const hasValue = !(val === undefined || val === null || (typeof val === 'string' && val === '') || (Array.isArray(val) && val.length === 0));
70
61
 
71
62
  if (!hasValue) {
@@ -242,27 +233,17 @@ export class SchemaValidator {
242
233
  }
243
234
 
244
235
  /**
245
- * Validate an object against it's constructor's schema
246
- * @param cls The class to validate the objects against
247
- * @param o The object to validate
248
- * @param view The optional view to limit the scope to
236
+ * Validate the class level validations
249
237
  */
250
- static async validate<T>(cls: Class<T>, o: T, view?: string): Promise<T> {
251
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
252
- if (!ObjectUtil.isPlainObject(o) && !(o instanceof cls || cls.Ⲑid === (o as ClassInstance<T>).constructor.Ⲑid)) {
253
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
254
- throw new TypeMismatchError(cls.name, (o as ClassInstance).constructor.name);
238
+ static async #validateClassLevel<T>(cls: Class<T>, o: T, view?: string): Promise<ValidationError[]> {
239
+ const schema = SchemaRegistry.get(cls);
240
+ if (!schema) {
241
+ return [];
255
242
  }
256
- cls = SchemaRegistry.resolveSubTypeForInstance(cls, o);
257
-
258
- const config = SchemaRegistry.getViewSchema(cls, view);
259
- const validators = SchemaRegistry.get(cls).validators;
260
-
261
- // Validate using standard behaviors
262
- const errors = this.#validateSchema(config.schema, o, '');
263
243
 
244
+ const errors: ValidationError[] = [];
264
245
  // Handle class level validators
265
- for (const fn of validators) {
246
+ for (const fn of schema.validators) {
266
247
  try {
267
248
  const res = await fn(o, view);
268
249
  if (res) {
@@ -276,7 +257,30 @@ export class SchemaValidator {
276
257
  }
277
258
  }
278
259
  }
260
+ return errors;
261
+ }
279
262
 
263
+ /**
264
+ * Validate an object against it's constructor's schema
265
+ * @param cls The class to validate the objects against
266
+ * @param o The object to validate
267
+ * @param view The optional view to limit the scope to
268
+ */
269
+ static async validate<T>(cls: Class<T>, o: T, view?: string): Promise<T> {
270
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
271
+ if (!ObjectUtil.isPlainObject(o) && !(o instanceof cls || cls.Ⲑid === (o as ClassInstance<T>).constructor.Ⲑid)) {
272
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
273
+ throw new TypeMismatchError(cls.name, (o as ClassInstance).constructor.name);
274
+ }
275
+ cls = SchemaRegistry.resolveSubTypeForInstance(cls, o);
276
+
277
+ const config = SchemaRegistry.getViewSchema(cls, view);
278
+
279
+ // Validate using standard behaviors
280
+ const errors = [
281
+ ...this.#validateSchema(config.schema, o, ''),
282
+ ... await this.#validateClassLevel(cls, o, view)
283
+ ];
280
284
  if (errors.length) {
281
285
  throw new ValidationResultError(errors);
282
286
  }
@@ -327,7 +331,14 @@ export class SchemaValidator {
327
331
  static async validateMethod<T>(cls: Class<T>, method: string, params: unknown[], prefixes: (string | undefined)[] = []): Promise<void> {
328
332
  const errors: ValidationError[] = [];
329
333
  for (const field of SchemaRegistry.getMethodSchema(cls, method)) {
330
- errors.push(...this.#validateFieldSchemaRaw(field, params[field.index!], prefixes[field.index!]));
334
+ const i = field.index!;
335
+ errors.push(...[
336
+ ... this.#validateFieldSchema(field, params[i]),
337
+ ... await this.#validateClassLevel(field.type, params[i])
338
+ ].map(x => {
339
+ x.path = !prefixes[i] ? x.path.replace(`${field.name}.`, '') : x.path.replace(field.name, prefixes[i]!);
340
+ return x;
341
+ }));
331
342
  }
332
343
  if (errors.length) {
333
344
  throw new ValidationResultError(errors);