@bedrockio/yada 1.0.39 → 1.0.40

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.
@@ -271,6 +271,7 @@ class Schema {
271
271
  enum: set
272
272
  }).assert('enum', async (val, options) => {
273
273
  if (val !== undefined) {
274
+ let error;
274
275
  for (let el of set) {
275
276
  if (isSchema(el)) {
276
277
  try {
@@ -279,16 +280,30 @@ class Schema {
279
280
  // example allowing a string or array of strings.
280
281
  options = (0, _utils.omit)(options, 'cast');
281
282
  return await el.validate(val, options);
282
- } catch (error) {
283
+ } catch (err) {
284
+ const [first] = err.details;
285
+ const isTypeError = first?.type === 'type';
286
+ if (!isTypeError) {
287
+ // Capture the first error object only if it is not
288
+ // a simple type error to surface error messages on
289
+ // more complex schemas. Otherwise allow this to fall
290
+ // through to show more meaningful messages for simple
291
+ // enums.
292
+ error ||= err;
293
+ }
283
294
  continue;
284
295
  }
285
296
  } else if (el === val === allow) {
286
297
  return;
287
298
  }
288
299
  }
289
- throw new _errors.LocalizedError(options.message || msg, {
290
- types: types.join(', ')
291
- });
300
+ if (error) {
301
+ throw new _errors.ValidationError(options.message || error.message, error.details);
302
+ } else {
303
+ throw new _errors.LocalizedError(options.message || msg, {
304
+ types: types.join(', ')
305
+ });
306
+ }
292
307
  }
293
308
  });
294
309
  }
@@ -27,8 +27,8 @@ class ValidationError extends Error {
27
27
  if (this.canRollup()) {
28
28
  const [first] = this.details;
29
29
  return {
30
- type: this.type,
31
- message: first.message
30
+ ...first.toJSON(),
31
+ type: this.type
32
32
  };
33
33
  } else {
34
34
  return {
@@ -44,11 +44,14 @@ class ValidationError extends Error {
44
44
  const {
45
45
  details
46
46
  } = this;
47
- if (this.isFieldType() && details.length === 1) {
48
- return !details[0].isFieldType?.();
49
- } else {
47
+ if (details.length !== 1) {
50
48
  return false;
51
49
  }
50
+ const [first] = details;
51
+
52
+ // Roll up field types as long as they are not
53
+ // referencing nested fields.
54
+ return this.isFieldType() && !first.isFieldType?.();
52
55
  }
53
56
  isFieldType() {
54
57
  return this.type === 'field' || this.type === 'element';
@@ -82,6 +82,9 @@ class ObjectSchema extends _TypeSchema.default {
82
82
  return;
83
83
  }
84
84
  try {
85
+ // Do not pass down message into validators
86
+ // to allow custom messages to take precedence.
87
+ options = (0, _utils.omit)(options, 'message');
85
88
  const result = await schema.validate(val, options);
86
89
  if (result !== undefined) {
87
90
  return {
@@ -16,11 +16,17 @@ class StringSchema extends _TypeSchema.default {
16
16
  constructor() {
17
17
  super(String);
18
18
  this.assert('type', (val, options) => {
19
- if (typeof val !== 'string' && options.cast) {
19
+ const {
20
+ cast,
21
+ allowEmpty
22
+ } = options;
23
+ if (cast && typeof val !== 'string') {
20
24
  val = String(val);
21
25
  }
22
26
  if (typeof val !== 'string') {
23
27
  throw new _errors.LocalizedError('Must be a string.');
28
+ } else if (!allowEmpty && val === '') {
29
+ throw new _errors.LocalizedError('String may not be empty.');
24
30
  }
25
31
  return val;
26
32
  });
@@ -35,12 +41,19 @@ class StringSchema extends _TypeSchema.default {
35
41
  }).assert('required', val => {
36
42
  if (val == null) {
37
43
  throw new _errors.LocalizedError('Value is required.');
38
- } else if (val === '') {
39
- throw new _errors.LocalizedError('String may not be empty.');
40
44
  }
41
45
  });
42
46
  }
43
47
 
48
+ /**
49
+ * @returns {this}
50
+ */
51
+ allowEmpty() {
52
+ return this.options({
53
+ allowEmpty: true
54
+ });
55
+ }
56
+
44
57
  /**
45
58
  * @param {number} length
46
59
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/yada",
3
- "version": "1.0.39",
3
+ "version": "1.0.40",
4
4
  "description": "Validation library inspired by Joi.",
5
5
  "scripts": {
6
6
  "test": "jest",
package/src/Schema.js CHANGED
@@ -252,6 +252,7 @@ export default class Schema {
252
252
  const msg = `${allow ? 'Must' : 'Must not'} be one of [{types}].`;
253
253
  return this.clone({ enum: set }).assert('enum', async (val, options) => {
254
254
  if (val !== undefined) {
255
+ let error;
255
256
  for (let el of set) {
256
257
  if (isSchema(el)) {
257
258
  try {
@@ -260,16 +261,33 @@ export default class Schema {
260
261
  // example allowing a string or array of strings.
261
262
  options = omit(options, 'cast');
262
263
  return await el.validate(val, options);
263
- } catch (error) {
264
+ } catch (err) {
265
+ const [first] = err.details;
266
+ const isTypeError = first?.type === 'type';
267
+ if (!isTypeError) {
268
+ // Capture the first error object only if it is not
269
+ // a simple type error to surface error messages on
270
+ // more complex schemas. Otherwise allow this to fall
271
+ // through to show more meaningful messages for simple
272
+ // enums.
273
+ error ||= err;
274
+ }
264
275
  continue;
265
276
  }
266
277
  } else if ((el === val) === allow) {
267
278
  return;
268
279
  }
269
280
  }
270
- throw new LocalizedError(options.message || msg, {
271
- types: types.join(', '),
272
- });
281
+ if (error) {
282
+ throw new ValidationError(
283
+ options.message || error.message,
284
+ error.details
285
+ );
286
+ } else {
287
+ throw new LocalizedError(options.message || msg, {
288
+ types: types.join(', '),
289
+ });
290
+ }
273
291
  }
274
292
  });
275
293
  }
package/src/errors.js CHANGED
@@ -23,8 +23,8 @@ export class ValidationError extends Error {
23
23
  if (this.canRollup()) {
24
24
  const [first] = this.details;
25
25
  return {
26
+ ...first.toJSON(),
26
27
  type: this.type,
27
- message: first.message,
28
28
  };
29
29
  } else {
30
30
  return {
@@ -39,11 +39,14 @@ export class ValidationError extends Error {
39
39
 
40
40
  canRollup() {
41
41
  const { details } = this;
42
- if (this.isFieldType() && details.length === 1) {
43
- return !details[0].isFieldType?.();
44
- } else {
42
+ if (details.length !== 1) {
45
43
  return false;
46
44
  }
45
+ const [first] = details;
46
+
47
+ // Roll up field types as long as they are not
48
+ // referencing nested fields.
49
+ return this.isFieldType() && !first.isFieldType?.();
47
50
  }
48
51
 
49
52
  isFieldType() {
package/src/object.js CHANGED
@@ -68,6 +68,9 @@ class ObjectSchema extends TypeSchema {
68
68
  return;
69
69
  }
70
70
  try {
71
+ // Do not pass down message into validators
72
+ // to allow custom messages to take precedence.
73
+ options = omit(options, 'message');
71
74
  const result = await schema.validate(val, options);
72
75
  if (result !== undefined) {
73
76
  return {
package/src/string.js CHANGED
@@ -20,11 +20,14 @@ class StringSchema extends TypeSchema {
20
20
  constructor() {
21
21
  super(String);
22
22
  this.assert('type', (val, options) => {
23
- if (typeof val !== 'string' && options.cast) {
23
+ const { cast, allowEmpty } = options;
24
+ if (cast && typeof val !== 'string') {
24
25
  val = String(val);
25
26
  }
26
27
  if (typeof val !== 'string') {
27
28
  throw new LocalizedError('Must be a string.');
29
+ } else if (!allowEmpty && val === '') {
30
+ throw new LocalizedError('String may not be empty.');
28
31
  }
29
32
  return val;
30
33
  });
@@ -37,12 +40,17 @@ class StringSchema extends TypeSchema {
37
40
  return this.clone({ required: true }).assert('required', (val) => {
38
41
  if (val == null) {
39
42
  throw new LocalizedError('Value is required.');
40
- } else if (val === '') {
41
- throw new LocalizedError('String may not be empty.');
42
43
  }
43
44
  });
44
45
  }
45
46
 
47
+ /**
48
+ * @returns {this}
49
+ */
50
+ allowEmpty() {
51
+ return this.options({ allowEmpty: true });
52
+ }
53
+
46
54
  /**
47
55
  * @param {number} length
48
56
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../src/Schema.js"],"names":[],"mappings":"AA4WA,4CAEC;AAlWD;;GAEG;AAEH;IACE,uBAGC;IAFC,kBAAoB;IACpB,SAAgB;IAKlB;;OAEG;IACH,YAFa,IAAI,CAQhB;IAED;;;OAGG;IACH,mBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,gBAHW,eAAe,GACb,IAAI,CAmBhB;IAED;;;;OAIG;IACH,mBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,uBAFa,IAAI,CAIhB;IAED;;OAEG;IACH,uBAFa,IAAI,CAIhB;IAED;;OAEG;IACH,gBAFa,IAAI,CAShB;IAED;;OAEG;IACH,+BAFa,IAAI,CAMhB;IAED;;OAEG;IACH,uBAFa,IAAI,CAIhB;IAED,iDAqCC;IAED;;OAEG;IACH,kBAFa,IAAI,CAOhB;IAED;;;OAGG;IACH,qBAFa,IAAI,CAMhB;IAED,2BAWC;IAED;;MAOC;IAED;;;;MASC;IAED,kBAEC;IAED,4BAMC;IAID;;OAEG;IACH,kCAFa,IAAI,CAmChB;IAED;;OAEG;IACH,4BAFa,IAAI,CAUhB;IAED,oCAKC;IAED;;OAEG;IACH,oBAFa,IAAI,CAShB;IAED,gCAGC;IAED,qEAUC;IAED;;;;;;;;MAoCC;CACF;8BA7VY,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC"}
1
+ {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../src/Schema.js"],"names":[],"mappings":"AA8XA,4CAEC;AApXD;;GAEG;AAEH;IACE,uBAGC;IAFC,kBAAoB;IACpB,SAAgB;IAKlB;;OAEG;IACH,YAFa,IAAI,CAQhB;IAED;;;OAGG;IACH,mBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,gBAHW,eAAe,GACb,IAAI,CAmBhB;IAED;;;;OAIG;IACH,mBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,uBAFa,IAAI,CAIhB;IAED;;OAEG;IACH,uBAFa,IAAI,CAIhB;IAED;;OAEG;IACH,gBAFa,IAAI,CAShB;IAED;;OAEG;IACH,+BAFa,IAAI,CAMhB;IAED;;OAEG;IACH,uBAFa,IAAI,CAIhB;IAED,iDAqCC;IAED;;OAEG;IACH,kBAFa,IAAI,CAOhB;IAED;;;OAGG;IACH,qBAFa,IAAI,CAMhB;IAED,2BAWC;IAED;;MAOC;IAED;;;;MASC;IAED,kBAEC;IAED,4BAMC;IAID;;OAEG;IACH,kCAFa,IAAI,CAqDhB;IAED;;OAEG;IACH,4BAFa,IAAI,CAUhB;IAED,oCAKC;IAED;;OAEG;IACH,oBAFa,IAAI,CAShB;IAED,gCAGC;IAED,qEAUC;IAED;;;;;;;;MAoCC;CACF;8BA/WY,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC"}
package/types/errors.d.ts CHANGED
@@ -8,15 +8,7 @@ export class ValidationError extends Error {
8
8
  constructor(message: any, details?: any[], type?: string);
9
9
  details: any[];
10
10
  type: string;
11
- toJSON(): {
12
- type: string;
13
- message: any;
14
- details?: undefined;
15
- } | {
16
- type: string;
17
- message: string;
18
- details: any[];
19
- };
11
+ toJSON(): any;
20
12
  canRollup(): boolean;
21
13
  isFieldType(): boolean;
22
14
  getFullMessage(options: any): any;
@@ -26,34 +18,12 @@ export class FieldError extends ValidationError {
26
18
  field: any;
27
19
  original: any;
28
20
  details: any;
29
- toJSON(): {
30
- field: any;
31
- type: string;
32
- message: any;
33
- details?: undefined;
34
- } | {
35
- field: any;
36
- type: string;
37
- message: string;
38
- details: any[];
39
- };
40
21
  }
41
22
  export class ElementError extends ValidationError {
42
23
  constructor(message: any, index: any, original: any, details: any);
43
24
  index: any;
44
25
  original: any;
45
26
  details: any;
46
- toJSON(): {
47
- index: any;
48
- type: string;
49
- message: any;
50
- details?: undefined;
51
- } | {
52
- index: any;
53
- type: string;
54
- message: string;
55
- details: any[];
56
- };
57
27
  }
58
28
  export class AssertionError extends Error {
59
29
  constructor(message: any, type: any, original: any);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.js"],"names":[],"mappings":"AAkHA,iDAMC;AArHD;IACE,uCAGC;IADC,YAAoB;IAGtB,gBAEC;CACF;AAED;IACE,0DAIC;IAFC,eAAsB;IACtB,aAAgB;IAGlB;;;;;;;;MAgBC;IAED,qBAOC;IAED,uBAEC;IAED,kCAKC;CACF;AAED;IACE,mEAKC;IAHC,WAAkB;IAClB,cAAwB;IACxB,aAAsB;IAGxB;;;;;;;;;;MAKC;CACF;AAED;IACE,mEAKC;IAHC,WAAkB;IAClB,cAAwB;IACxB,aAAsB;IAGxB;;;;;;;;;;MAKC;CACF;AAED;IACE,oDAIC;IAFC,UAAgB;IAChB,cAAwB;IAG1B;;;MAKC;CACF;AAED;IACE,wCAGC;IADC,aAAsB;CAEzB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.js"],"names":[],"mappings":"AAqHA,iDAMC;AAxHD;IACE,uCAGC;IADC,YAAoB;IAGtB,gBAEC;CACF;AAED;IACE,0DAIC;IAFC,eAAsB;IACtB,aAAgB;IAGlB,cAgBC;IAED,qBAUC;IAED,uBAEC;IAED,kCAKC;CACF;AAED;IACE,mEAKC;IAHC,WAAkB;IAClB,cAAwB;IACxB,aAAsB;CASzB;AAED;IACE,mEAKC;IAHC,WAAkB;IAClB,cAAwB;IACxB,aAAsB;CASzB;AAED;IACE,oDAIC;IAFC,UAAgB;IAChB,cAAwB;IAG1B;;;MAKC;CACF;AAED;IACE,wCAGC;IADC,aAAsB;CAEzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.js"],"names":[],"mappings":"AAsMA;;;;;;GAMG;AACH,uCAJW,SAAS,gBAMnB;;;;AAxMD;;GAEG;AAEH;IAUE;;OAEG;IACH,cAgEC;IAED;;OAEG;IACH,kBAEC;IAED;;OAEG;IAEH,YAHW,SAAS,GAAC,MAAM,gBAkC1B;IAED;;OAEG;IACH,gBAFc,MAAM,kBAWnB;IAED;;OAEG;IACH,gBAFc,MAAM,kBAWnB;CAcF"}
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.js"],"names":[],"mappings":"AAyMA;;;;;;GAMG;AACH,uCAJW,SAAS,gBAMnB;;;;AA3MD;;GAEG;AAEH;IAUE;;OAEG;IACH,cAmEC;IAED;;OAEG;IACH,kBAEC;IAED;;OAEG;IAEH,YAHW,SAAS,GAAC,MAAM,gBAkC1B;IAED;;OAEG;IACH,gBAFc,MAAM,kBAWnB;IAED;;OAEG;IACH,gBAFc,MAAM,kBAWnB;CAcF"}
package/types/string.d.ts CHANGED
@@ -8,6 +8,10 @@ declare class StringSchema extends TypeSchema {
8
8
  * @returns {this}
9
9
  */
10
10
  required(): this;
11
+ /**
12
+ * @returns {this}
13
+ */
14
+ allowEmpty(): this;
11
15
  /**
12
16
  * @param {number} length
13
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.js"],"names":[],"mappings":"AAqZA;;GAEG;AACH,iDAEC;AAxYD;IACE,cAWC;IAED;;OAEG;IACH,YAFa,IAAI,CAUhB;IAED;;OAEG;IACH,eAFW,MAAM,gBAUhB;IAED;;OAEG;IACH,YAFW,MAAM,gBAUhB;IAED;;OAEG;IACH,YAFW,MAAM,gBAUhB;IAED,qBAIC;IAED;;OAEG;IACH,mBAFW,OAAO,gBAYjB;IAED;;OAEG;IACH,mBAFW,OAAO,gBAYjB;IAED;;OAEG;IACH,WAFW,MAAM,gBAahB;IAED,sBAMC;IAED,sBAMC;IAED,oBAMC;IAED,oBAMC;IAED,qBAMC;IAED,sBAMC;IAED;;;OAGG;IACH;QAF6B,OAAO,GAAzB,OAAO;qBAQjB;IAED,2BAMC;IAED,mBAMC;IAED,wBAMC;IAED,uBAMC;IAED,oBAMC;IAED,qBAOC;IAED,uBAMC;IAED;;OAEG;IACH,oBAFW,MAAM,gBAQhB;IAED,wBAMC;IAED;;;;;;;OAOG;IACH;QAN4B,SAAS,GAA1B,MAAM;QACW,UAAU,GAA3B,MAAM;QACW,UAAU,GAA3B,MAAM;QACW,YAAY,GAA7B,MAAM;QACW,YAAY,GAA7B,MAAM;qBA+BhB;IAED;;;;;;;;;;;OAWG;IACH;QAV6B,gBAAgB,GAAlC,OAAO;QACW,sBAAsB,GAAxC,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,4BAA4B,GAA9C,OAAO;QACW,eAAe,GAAjC,OAAO;QACW,sBAAsB,GAAxC,OAAO;QACW,eAAe,GAAjC,OAAO;QACY,SAAS,GAA5B,MAAM,EAAE;qBAQlB;IAED;;;;;;;;OAQG;IACH;QAP6B,WAAW,GAA7B,OAAO;QACW,iBAAiB,GAAnC,OAAO;QACW,kBAAkB,GAApC,OAAO;QACW,iBAAiB,GAAnC,OAAO;QACW,cAAc,GAAhC,OAAO;QACW,iBAAiB,GAAnC,OAAO;qBAQjB;IAED;;OAEG;IACH,eAFW,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAQ3B;IAED,oBAMC;IAED,oBAMC;IAED,sBAMC;IAED,sBAMC;CAcF"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.js"],"names":[],"mappings":"AA6ZA;;GAEG;AACH,iDAEC;AAhZD;IACE,cAcC;IAED;;OAEG;IACH,YAFa,IAAI,CAQhB;IAED;;OAEG;IACH,cAFa,IAAI,CAIhB;IAED;;OAEG;IACH,eAFW,MAAM,gBAUhB;IAED;;OAEG;IACH,YAFW,MAAM,gBAUhB;IAED;;OAEG;IACH,YAFW,MAAM,gBAUhB;IAED,qBAIC;IAED;;OAEG;IACH,mBAFW,OAAO,gBAYjB;IAED;;OAEG;IACH,mBAFW,OAAO,gBAYjB;IAED;;OAEG;IACH,WAFW,MAAM,gBAahB;IAED,sBAMC;IAED,sBAMC;IAED,oBAMC;IAED,oBAMC;IAED,qBAMC;IAED,sBAMC;IAED;;;OAGG;IACH;QAF6B,OAAO,GAAzB,OAAO;qBAQjB;IAED,2BAMC;IAED,mBAMC;IAED,wBAMC;IAED,uBAMC;IAED,oBAMC;IAED,qBAOC;IAED,uBAMC;IAED;;OAEG;IACH,oBAFW,MAAM,gBAQhB;IAED,wBAMC;IAED;;;;;;;OAOG;IACH;QAN4B,SAAS,GAA1B,MAAM;QACW,UAAU,GAA3B,MAAM;QACW,UAAU,GAA3B,MAAM;QACW,YAAY,GAA7B,MAAM;QACW,YAAY,GAA7B,MAAM;qBA+BhB;IAED;;;;;;;;;;;OAWG;IACH;QAV6B,gBAAgB,GAAlC,OAAO;QACW,sBAAsB,GAAxC,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,4BAA4B,GAA9C,OAAO;QACW,eAAe,GAAjC,OAAO;QACW,sBAAsB,GAAxC,OAAO;QACW,eAAe,GAAjC,OAAO;QACY,SAAS,GAA5B,MAAM,EAAE;qBAQlB;IAED;;;;;;;;OAQG;IACH;QAP6B,WAAW,GAA7B,OAAO;QACW,iBAAiB,GAAnC,OAAO;QACW,kBAAkB,GAApC,OAAO;QACW,iBAAiB,GAAnC,OAAO;QACW,cAAc,GAAhC,OAAO;QACW,iBAAiB,GAAnC,OAAO;qBAQjB;IAED;;OAEG;IACH,eAFW,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,gBAQ3B;IAED,oBAMC;IAED,oBAMC;IAED,sBAMC;IAED,sBAMC;CAcF"}