@bedrockio/yada 1.10.0 → 1.10.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.10.2
2
+
3
+ - Shortcut methods for object options.
4
+
5
+ ## 1.10.1
6
+
7
+ - Refactored object field validation.
8
+ - Fixed issue with base object failing on flat keys.
9
+ - Ensure that arrays only accept a single inner schema.
10
+
1
11
  ## 1.10.0
2
12
 
3
13
  - Added `style` option to `toJsonSchema` to control disallowed formats for
package/README.md CHANGED
@@ -255,19 +255,37 @@ be a boolean, either `true` or `false`.
255
255
 
256
256
  ### Array
257
257
 
258
- Array schemas validate that input is an array. By default elements may be of any
259
- type, however however other schemas may be passed in as arguments:
258
+ Array schemas validate that input is an array and elements are of the provided
259
+ type:
260
260
 
261
261
  ```js
262
- // Allows arrays containing either strings or numbers.
263
- const schema = yd.array(yd.string(), yd.number());
262
+ // Allows arrays containing strings.
263
+ const schema = yd.array(yd.string());
264
264
  ```
265
265
 
266
- A single array may also be passed in place of enumerated arguments:
266
+ These types can be object of a specific shape:
267
267
 
268
268
  ```js
269
- // Allows arrays containing either strings or numbers.
270
- const schema = yd.array([schemas]);
269
+ // Allows arrays containing objects that follow a schema.
270
+ const schema = yd.array(
271
+ yd.object({
272
+ name: yd.string().required(),
273
+ }),
274
+ );
275
+ ```
276
+
277
+ If no inner schema is provided any element type is allowed:
278
+
279
+ ```js
280
+ // Allows any type of element inside the array:
281
+ const schema = yd.array();
282
+ ```
283
+
284
+ To allow mixed types inside the same array use allow:
285
+
286
+ ```js
287
+ // Allows both strings and numbers in the array:
288
+ const schema = yd.array(yd.allow(yd.string(), yd.number()));
271
289
  ```
272
290
 
273
291
  #### Methods:
@@ -285,7 +303,7 @@ well as types for a given position. Compare the following:
285
303
 
286
304
  ```js
287
305
  // Accepts any length of either strings or numbers.
288
- const schema1 = yd.array(yd.string(), yd.number());
306
+ const schema1 = yd.array(yd.allow(yd.string(), yd.number()));
289
307
  // Accepts exactly 2 elements. The first MUST be a
290
308
  // string and the second MUST be a number.
291
309
  const schema2 = yd.tuple(yd.string(), yd.number());
@@ -181,6 +181,8 @@ class Schema {
181
181
  details.push(new _errors.FormatError(message, this.meta.format));
182
182
  } else if (error instanceof _errors.LocalizedError) {
183
183
  details.push(new _errors.AssertionError(message, type));
184
+ } else if (error instanceof _errors.AggregateError) {
185
+ details = [...details, ...error.errors];
184
186
  } else {
185
187
  details.push(error);
186
188
  }
package/dist/cjs/array.js CHANGED
@@ -5,23 +5,18 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = _default;
7
7
  var _lodash = require("lodash");
8
- var _Schema = _interopRequireDefault(require("./Schema"));
9
8
  var _TypeSchema = _interopRequireDefault(require("./TypeSchema"));
10
9
  var _errors = require("./errors");
11
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
11
  class ArraySchema extends _TypeSchema.default {
13
- constructor(schemas, meta) {
14
- super(Array, {
15
- ...meta,
16
- schemas
17
- });
12
+ constructor(meta) {
13
+ super(Array, meta);
18
14
  this.setup();
19
15
  }
20
16
  setup() {
21
17
  const {
22
- schemas
18
+ schema
23
19
  } = this.meta;
24
- const schema = schemas.length > 1 ? new _Schema.default().allow(schemas) : schemas[0];
25
20
  this.assert('type', (val, options) => {
26
21
  if (typeof val === 'string' && options.cast) {
27
22
  val = val.split(',');
@@ -115,13 +110,15 @@ class ArraySchema extends _TypeSchema.default {
115
110
  */
116
111
  transform(fn, root = true) {
117
112
  const {
118
- schemas,
113
+ schema,
119
114
  ...rest
120
115
  } = this.meta;
121
- const newSchemas = schemas.map(schema => {
122
- return schema.transform(fn, false);
116
+ const transformed = new ArraySchema({
117
+ ...rest,
118
+ ...(schema && {
119
+ schema: schema.transform(fn, false)
120
+ })
123
121
  });
124
- const transformed = new ArraySchema(newSchemas, rest);
125
122
  if (root) {
126
123
  // @ts-ignore
127
124
  return transformed;
@@ -136,24 +133,14 @@ class ArraySchema extends _TypeSchema.default {
136
133
  return 'array';
137
134
  }
138
135
  toJsonSchema(options) {
139
- let other;
140
136
  const {
141
- schemas
137
+ schema
142
138
  } = this.meta;
143
- if (schemas.length > 1) {
144
- other = {
145
- anyOf: schemas.map(schema => {
146
- return schema.toJsonSchema(options);
147
- })
148
- };
149
- } else if (schemas.length === 1) {
150
- other = {
151
- items: schemas[0].toJsonSchema(options)
152
- };
153
- }
154
139
  return {
155
140
  ...super.toJsonSchema(options),
156
- ...other
141
+ ...(schema && {
142
+ items: schema?.toJsonSchema(options)
143
+ })
157
144
  };
158
145
  }
159
146
  }
@@ -161,14 +148,14 @@ class ArraySchema extends _TypeSchema.default {
161
148
  /**
162
149
  * Creates an [array schema](https://github.com/bedrockio/yada#array).
163
150
  *
164
- * @param {...Schema} [schemas] Optional schemas to validate
165
- * the different types of elements allowed in the array. If
166
- * no arguments are passed elements may be of any type. Also
167
- * accepts a single array argument.
151
+ * @param {*} [schema] - The schema to validate elements in
152
+ * the array. If not passed then elements may be of any type.
168
153
  */
169
- function _default(...schemas) {
170
- if (Array.isArray(schemas[0])) {
171
- schemas = schemas[0];
154
+ function _default(schema) {
155
+ if (arguments.length > 1) {
156
+ throw new Error('Arrays may only have a single schema. Use "allow" instead.');
172
157
  }
173
- return new ArraySchema(schemas);
158
+ return new ArraySchema({
159
+ schema
160
+ });
174
161
  }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ValidationError = exports.TypeError = exports.LocalizedError = exports.FormatError = exports.FieldError = exports.ElementError = exports.AssertionError = exports.ArrayError = exports.AllowedError = void 0;
6
+ exports.ValidationError = exports.TypeError = exports.LocalizedError = exports.FormatError = exports.FieldError = exports.ElementError = exports.AssertionError = exports.ArrayError = exports.AllowedError = exports.AggregateError = void 0;
7
7
  exports.isSchemaError = isSchemaError;
8
8
  var _localization = require("./localization");
9
9
  var _messages = require("./messages");
@@ -54,6 +54,13 @@ class ValidationError extends Error {
54
54
  }
55
55
  }
56
56
  exports.ValidationError = ValidationError;
57
+ class AggregateError extends Error {
58
+ constructor(message, errors) {
59
+ super(message);
60
+ this.errors = errors;
61
+ }
62
+ }
63
+ exports.AggregateError = AggregateError;
57
64
  class AssertionError extends ValidationError {
58
65
  constructor(message, type = 'assertion') {
59
66
  super(message);
@@ -21,92 +21,105 @@ const INTEGER_REG = /^\d+$/;
21
21
  class ObjectSchema extends _TypeSchema.default {
22
22
  constructor(meta) {
23
23
  super(Object, meta);
24
+ this.validateInput();
24
25
  this.setup();
25
26
  }
27
+ validateInput() {
28
+ const {
29
+ fields
30
+ } = this.meta;
31
+ for (let [key, value] of Object.entries(fields || {})) {
32
+ if (!(0, _Schema.isSchema)(value)) {
33
+ throw new Error(`Key "${key}" must be a schema.`);
34
+ }
35
+ }
36
+ }
26
37
  setup() {
27
38
  this.assert('type', val => {
28
39
  if (val === null || typeof val !== 'object') {
29
40
  throw new _errors.LocalizedError('Must be an object.');
30
41
  }
31
42
  });
32
- this.transformValue((obj, options) => {
43
+ this.assert('fields', async (obj, options) => {
33
44
  const {
45
+ path = [],
46
+ original,
47
+ stripEmpty,
34
48
  stripUnknown,
35
- stripEmpty
49
+ allowFlatKeys,
50
+ expandFlatKeys
36
51
  } = options;
37
- if (obj) {
38
- const result = {};
39
- obj = expandFlatSyntax(obj, options);
40
- for (let key of Object.keys(obj)) {
41
- const value = obj[key];
42
- const isUnknown = !isKnownKey(key, this, options);
43
- if (value === '' && stripEmpty || isUnknown && stripUnknown) {
52
+ const {
53
+ fields
54
+ } = this.meta;
55
+ if (!fields) {
56
+ return;
57
+ }
58
+ let passed = obj;
59
+ if (expandFlatKeys) {
60
+ passed = expandFlatSyntax(passed);
61
+ }
62
+ const keys = new Set([...Object.keys(fields || {}), ...Object.keys(passed)]);
63
+ let errors = [];
64
+ const result = {};
65
+ for (let key of keys) {
66
+ const value = passed[key];
67
+ if (value === '' && stripEmpty) {
68
+ continue;
69
+ }
70
+ const schema = getSchema(fields, key, options);
71
+ if (!schema) {
72
+ if (stripUnknown) {
44
73
  continue;
45
- } else if (isUnknown) {
46
- throw new _errors.LocalizedError('Unknown field "{key}".', {
47
- key,
48
- type: 'field'
49
- });
50
- } else {
51
- result[key] = obj[key];
52
74
  }
75
+ throw new _errors.LocalizedError('Unknown field "{key}".', {
76
+ type: 'field',
77
+ key
78
+ });
53
79
  }
54
- return result;
55
- }
56
- });
57
- for (let [key, schema] of Object.entries(this.export())) {
58
- if (!(0, _Schema.isSchema)(schema)) {
59
- throw new Error(`Key "${key}" must be a schema.`);
60
- }
61
- this.assert('field', async (obj, options) => {
62
- if (obj) {
63
- const {
64
- path = [],
65
- original
66
- } = options;
67
- const {
68
- strip,
69
- required
70
- } = schema.meta;
71
- const val = obj[key];
72
- options = {
80
+ if (schema.meta.strip?.(value, options)) {
81
+ continue;
82
+ }
83
+ try {
84
+ const validateOptions = {
73
85
  ...options,
74
- required,
75
- path: [...path, key]
86
+ path: [...path, key],
87
+ required: schema.meta.required,
88
+ // The root object may be transformed by defaults
89
+ // or returned values so re-pass it here.
90
+ root: {
91
+ ...obj,
92
+ ...result
93
+ },
94
+ // The original root represents the root object
95
+ // before it was transformed.
96
+ originalRoot: original
76
97
  };
77
- if (strip && strip(val, options)) {
78
- delete obj[key];
79
- return;
80
- }
81
- try {
82
- // Do not pass down message into validators
83
- // to allow custom messages to take precedence.
84
- options = (0, _lodash.omit)(options, 'message');
85
- const result = await schema.validate(val, {
86
- ...options,
87
- // The root object may have been transformed here
88
- // by defaults or values returned by custom functions
89
- // so re-pass it here.
90
- root: obj,
91
- // The original root represents the root object
92
- // before it was transformed.
93
- originalRoot: original
94
- });
95
- if (result !== undefined) {
96
- return {
97
- ...obj,
98
- [key]: result
99
- };
98
+ if (allowFlatKeys && !value) {
99
+ // When allowing keys like "profile.name", "profile" will
100
+ // not be passed so expand the passed object and make sure
101
+ // the base validates, but do not transform the result.
102
+ const expanded = expandFlatSyntax(passed);
103
+ await schema.validate(expanded[key], validateOptions);
104
+ } else {
105
+ const transformed = await schema.validate(value, validateOptions);
106
+ if (transformed !== undefined) {
107
+ result[key] = transformed;
100
108
  }
101
- } catch (error) {
102
- const {
103
- message
104
- } = schema.meta;
105
- throw new _errors.FieldError(message, key, error.details);
106
109
  }
110
+ } catch (error) {
111
+ const {
112
+ message
113
+ } = schema.meta;
114
+ errors.push(new _errors.FieldError(message, key, error.details));
107
115
  }
108
- });
109
- }
116
+ }
117
+ if (errors.length) {
118
+ errors = normalizeErrors(errors, options);
119
+ throw new _errors.AggregateError(this.meta.message, errors);
120
+ }
121
+ return result;
122
+ });
110
123
  }
111
124
 
112
125
  /**
@@ -126,11 +139,8 @@ class ObjectSchema extends _TypeSchema.default {
126
139
  path = Array.isArray(path) ? path : path.split('.');
127
140
  const [name, ...rest] = path;
128
141
  const schema = fields[name];
129
- if (!schema) {
130
- throw new Error(`Cannot find field "${name}".`);
131
- }
132
142
  if (rest.length) {
133
- return schema.get(rest);
143
+ return schema?.get(rest);
134
144
  } else {
135
145
  return schema;
136
146
  }
@@ -147,14 +157,15 @@ class ObjectSchema extends _TypeSchema.default {
147
157
  path = Array.isArray(path) ? path.join('.') : path;
148
158
  const field = this.get(path);
149
159
  const {
150
- schemas
160
+ type,
161
+ schema
151
162
  } = field.meta;
152
- if (!schemas) {
163
+ if (type !== 'array') {
153
164
  throw new Error(`Field "${path}" is not an array schema.`);
154
- } else if (schemas.length !== 1) {
155
- throw new Error(`Field "${path}" should contain only one schema.`);
165
+ } else if (!schema) {
166
+ throw new Error(`Field "${path}" does not have an inner schema.`);
156
167
  }
157
- return schemas[0];
168
+ return schema;
158
169
  }
159
170
 
160
171
  /**
@@ -202,7 +213,11 @@ class ObjectSchema extends _TypeSchema.default {
202
213
  }
203
214
  const update = {};
204
215
  for (let field of fields) {
205
- (0, _lodash.set)(update, field, this.get(field).required());
216
+ const schema = this.get(field);
217
+ if (!schema) {
218
+ throw new Error(`Cannot find field "${field}".`);
219
+ }
220
+ (0, _lodash.set)(update, field, schema.required());
206
221
  }
207
222
  return this.append(update);
208
223
  }
@@ -288,6 +303,44 @@ class ObjectSchema extends _TypeSchema.default {
288
303
  return schema;
289
304
  }
290
305
 
306
+ // Options
307
+
308
+ /**
309
+ * Remove properties that are empty strings.
310
+ */
311
+ stripEmpty() {
312
+ return this.options({
313
+ stripEmpty: true
314
+ });
315
+ }
316
+
317
+ /**
318
+ * Remove properties not in the schema.
319
+ */
320
+ stripUnknown() {
321
+ return this.options({
322
+ stripUnknown: true
323
+ });
324
+ }
325
+
326
+ /**
327
+ * Allow flat keys like `profile.name`.
328
+ */
329
+ allowFlatKeys() {
330
+ return this.options({
331
+ allowFlatKeys: true
332
+ });
333
+ }
334
+
335
+ /**
336
+ * Expand flat keys into nested objects.
337
+ */
338
+ expandFlatKeys() {
339
+ return this.options({
340
+ expandFlatKeys: true
341
+ });
342
+ }
343
+
291
344
  /**
292
345
  * `stripEmpty` - Removes properties that are empty strings.
293
346
  * `stripUnknown` - Removes properties not in the schema.
@@ -328,10 +381,7 @@ class ObjectSchema extends _TypeSchema.default {
328
381
  };
329
382
  }
330
383
  }
331
- function expandFlatSyntax(obj, options) {
332
- if (!options.expandFlatKeys) {
333
- return obj;
334
- }
384
+ function expandFlatSyntax(obj) {
335
385
  const result = {
336
386
  ...obj
337
387
  };
@@ -343,66 +393,6 @@ function expandFlatSyntax(obj, options) {
343
393
  }
344
394
  return result;
345
395
  }
346
- function isKnownKey(key, schema, options) {
347
- const {
348
- fields
349
- } = schema.meta;
350
- const {
351
- allowFlatKeys
352
- } = options;
353
- if (!fields) {
354
- // No fields defined -> all keys are "known".
355
- return true;
356
- } else if (key in fields) {
357
- // Exact match -> key is known.
358
- return true;
359
- } else if (allowFlatKeys && key.includes('.')) {
360
- // Flat syntax "foo.bar".
361
- const [base, ...rest] = key.split('.');
362
- let subschema = fields[base];
363
- if (!subschema) {
364
- return false;
365
- }
366
- const {
367
- type,
368
- schemas
369
- } = subschema.meta;
370
- let subkey;
371
- if (type === 'array') {
372
- // If the subschema is an array then take the first of
373
- // its defined schemas as we can safely assume that an
374
- // array of objects will be defined as a single element
375
- // or multiple schemas will only set the base property.
376
- // Test that the element key is valid and take any
377
- // further properties as the subkey. Examples:
378
- // - profiles.0.name (array of objects)
379
- // - profiles.0 (array of stringsmk)
380
- const [index, ...other] = rest;
381
- if (!INTEGER_REG.test(index)) {
382
- return false;
383
- }
384
- subschema = schemas[0];
385
- subkey = other.join('.');
386
- } else if (type === 'object') {
387
- // If the subschema is an object then simply take any
388
- // further properties as the subkey. Example:
389
- // - profile.name
390
- subkey = rest.join('.');
391
- } else {
392
- // If the subschema is anything else then disallow it
393
- // further properties as the subkey. Example:
394
- // - profile.name
395
- return false;
396
- }
397
- if (subschema.meta.type === 'object') {
398
- return isKnownKey(subkey, subschema, options);
399
- } else {
400
- return !subkey;
401
- }
402
- } else {
403
- return false;
404
- }
405
- }
406
396
  function mergeFields(aFields, bFields) {
407
397
  if (!aFields || !bFields) {
408
398
  return aFields || bFields;
@@ -422,6 +412,78 @@ function mergeFields(aFields, bFields) {
422
412
  return result;
423
413
  }
424
414
 
415
+ // Gets the schema for a field allowing for flat
416
+ // keys which may deeply traverse into the object.
417
+ function getSchema(fields, key, options) {
418
+ const {
419
+ allowFlatKeys
420
+ } = options;
421
+ let schema = fields[key];
422
+ if (schema) {
423
+ return schema;
424
+ }
425
+ if (!allowFlatKeys || !key.includes('.')) {
426
+ return;
427
+ }
428
+ schema = fields;
429
+ for (let part of key.split('.')) {
430
+ const {
431
+ type,
432
+ fields
433
+ } = schema?.meta || {};
434
+ if (type === 'array') {
435
+ // If the schema is an array schema then take the first
436
+ // subschema, however only allow integers in this case,
437
+ // for example: profiles.0.name.
438
+
439
+ if (!INTEGER_REG.test(part)) {
440
+ return;
441
+ }
442
+ schema = schema.meta.schema;
443
+ } else if (fields) {
444
+ schema = fields[part];
445
+ } else {
446
+ schema = schema?.[part];
447
+ }
448
+ }
449
+ return schema;
450
+ }
451
+
452
+ // If flat keys are allowed then filter out errors
453
+ // that are the nested duplicates so that they match
454
+ // the actual fields that were passed.
455
+ function normalizeErrors(errors, options) {
456
+ const {
457
+ allowFlatKeys
458
+ } = options;
459
+ if (allowFlatKeys) {
460
+ errors = errors.filter(error => {
461
+ const {
462
+ field
463
+ } = error;
464
+ const flatField = getFlatField(error);
465
+ if (field !== flatField) {
466
+ return !errors.some(error => {
467
+ return error.field === flatField;
468
+ });
469
+ }
470
+ return true;
471
+ });
472
+ }
473
+ return errors;
474
+ }
475
+ function getFlatField(error) {
476
+ const {
477
+ field,
478
+ details
479
+ } = error;
480
+ const path = [field];
481
+ if (details.length === 1 && details[0] instanceof _errors.FieldError) {
482
+ path.push(getFlatField(details[0]));
483
+ }
484
+ return path.join('.');
485
+ }
486
+
425
487
  /**
426
488
  * Creates an [object schema](https://github.com/bedrockio/yada#object).
427
489
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/yada",
3
- "version": "1.10.0",
3
+ "version": "1.10.2",
4
4
  "description": "Validation library inspired by Joi.",
5
5
  "scripts": {
6
6
  "test": "jest",
package/src/Schema.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { omit, uniqBy } from 'lodash';
2
2
 
3
3
  import {
4
+ AggregateError,
4
5
  AllowedError,
5
6
  AssertionError,
6
7
  FormatError,
@@ -177,6 +178,8 @@ export default class Schema {
177
178
  details.push(new FormatError(message, this.meta.format));
178
179
  } else if (error instanceof LocalizedError) {
179
180
  details.push(new AssertionError(message, type));
181
+ } else if (error instanceof AggregateError) {
182
+ details = [...details, ...error.errors];
180
183
  } else {
181
184
  details.push(error);
182
185
  }
package/src/array.js CHANGED
@@ -1,19 +1,16 @@
1
1
  import { omit } from 'lodash';
2
2
 
3
- import Schema from './Schema';
4
3
  import TypeSchema from './TypeSchema';
5
4
  import { ArrayError, ElementError, LocalizedError } from './errors';
6
5
 
7
6
  class ArraySchema extends TypeSchema {
8
- constructor(schemas, meta) {
9
- super(Array, { ...meta, schemas });
7
+ constructor(meta) {
8
+ super(Array, meta);
10
9
  this.setup();
11
10
  }
12
11
 
13
12
  setup() {
14
- const { schemas } = this.meta;
15
- const schema =
16
- schemas.length > 1 ? new Schema().allow(schemas) : schemas[0];
13
+ const { schema } = this.meta;
17
14
 
18
15
  this.assert('type', (val, options) => {
19
16
  if (typeof val === 'string' && options.cast) {
@@ -111,14 +108,15 @@ class ArraySchema extends TypeSchema {
111
108
  * @returns {this}
112
109
  */
113
110
  transform(fn, root = true) {
114
- const { schemas, ...rest } = this.meta;
111
+ const { schema, ...rest } = this.meta;
115
112
 
116
- const newSchemas = schemas.map((schema) => {
117
- return schema.transform(fn, false);
113
+ const transformed = new ArraySchema({
114
+ ...rest,
115
+ ...(schema && {
116
+ schema: schema.transform(fn, false),
117
+ }),
118
118
  });
119
119
 
120
- const transformed = new ArraySchema(newSchemas, rest);
121
-
122
120
  if (root) {
123
121
  // @ts-ignore
124
122
  return transformed;
@@ -134,23 +132,12 @@ class ArraySchema extends TypeSchema {
134
132
  }
135
133
 
136
134
  toJsonSchema(options) {
137
- let other;
138
- const { schemas } = this.meta;
139
- if (schemas.length > 1) {
140
- other = {
141
- anyOf: schemas.map((schema) => {
142
- return schema.toJsonSchema(options);
143
- }),
144
- };
145
- } else if (schemas.length === 1) {
146
- other = {
147
- items: schemas[0].toJsonSchema(options),
148
- };
149
- }
150
-
135
+ const { schema } = this.meta;
151
136
  return {
152
137
  ...super.toJsonSchema(options),
153
- ...other,
138
+ ...(schema && {
139
+ items: schema?.toJsonSchema(options),
140
+ }),
154
141
  };
155
142
  }
156
143
  }
@@ -158,14 +145,16 @@ class ArraySchema extends TypeSchema {
158
145
  /**
159
146
  * Creates an [array schema](https://github.com/bedrockio/yada#array).
160
147
  *
161
- * @param {...Schema} [schemas] Optional schemas to validate
162
- * the different types of elements allowed in the array. If
163
- * no arguments are passed elements may be of any type. Also
164
- * accepts a single array argument.
148
+ * @param {*} [schema] - The schema to validate elements in
149
+ * the array. If not passed then elements may be of any type.
165
150
  */
166
- export default function (...schemas) {
167
- if (Array.isArray(schemas[0])) {
168
- schemas = schemas[0];
151
+ export default function (schema) {
152
+ if (arguments.length > 1) {
153
+ throw new Error(
154
+ 'Arrays may only have a single schema. Use "allow" instead.',
155
+ );
169
156
  }
170
- return new ArraySchema(schemas);
157
+ return new ArraySchema({
158
+ schema,
159
+ });
171
160
  }
package/src/errors.js CHANGED
@@ -46,6 +46,13 @@ export class ValidationError extends Error {
46
46
  }
47
47
  }
48
48
 
49
+ export class AggregateError extends Error {
50
+ constructor(message, errors) {
51
+ super(message);
52
+ this.errors = errors;
53
+ }
54
+ }
55
+
49
56
  export class AssertionError extends ValidationError {
50
57
  constructor(message, type = 'assertion') {
51
58
  super(message);
package/src/object.js CHANGED
@@ -2,7 +2,7 @@ import { omit, pick, set } from 'lodash';
2
2
 
3
3
  import Schema, { isSchema } from './Schema';
4
4
  import TypeSchema from './TypeSchema';
5
- import { FieldError, LocalizedError } from './errors';
5
+ import { AggregateError, FieldError, LocalizedError } from './errors';
6
6
 
7
7
  const APPEND_ASSERTION_TYPES = ['required', 'type', 'custom'];
8
8
 
@@ -15,88 +15,124 @@ const INTEGER_REG = /^\d+$/;
15
15
  class ObjectSchema extends TypeSchema {
16
16
  constructor(meta) {
17
17
  super(Object, meta);
18
+ this.validateInput();
18
19
  this.setup();
19
20
  }
20
21
 
22
+ validateInput() {
23
+ const { fields } = this.meta;
24
+ for (let [key, value] of Object.entries(fields || {})) {
25
+ if (!isSchema(value)) {
26
+ throw new Error(`Key "${key}" must be a schema.`);
27
+ }
28
+ }
29
+ }
30
+
21
31
  setup() {
22
32
  this.assert('type', (val) => {
23
33
  if (val === null || typeof val !== 'object') {
24
34
  throw new LocalizedError('Must be an object.');
25
35
  }
26
36
  });
27
- this.transformValue((obj, options) => {
28
- const { stripUnknown, stripEmpty } = options;
29
- if (obj) {
30
- const result = {};
31
37
 
32
- obj = expandFlatSyntax(obj, options);
38
+ this.assert('fields', async (obj, options) => {
39
+ const {
40
+ path = [],
41
+ original,
42
+ stripEmpty,
43
+ stripUnknown,
44
+ allowFlatKeys,
45
+ expandFlatKeys,
46
+ } = options;
47
+
48
+ const { fields } = this.meta;
49
+
50
+ if (!fields) {
51
+ return;
52
+ }
53
+
54
+ let passed = obj;
55
+
56
+ if (expandFlatKeys) {
57
+ passed = expandFlatSyntax(passed);
58
+ }
59
+
60
+ const keys = new Set([
61
+ ...Object.keys(fields || {}),
62
+ ...Object.keys(passed),
63
+ ]);
64
+
65
+ let errors = [];
66
+ const result = {};
33
67
 
34
- for (let key of Object.keys(obj)) {
35
- const value = obj[key];
36
- const isUnknown = !isKnownKey(key, this, options);
68
+ for (let key of keys) {
69
+ const value = passed[key];
37
70
 
38
- if ((value === '' && stripEmpty) || (isUnknown && stripUnknown)) {
71
+ if (value === '' && stripEmpty) {
72
+ continue;
73
+ }
74
+
75
+ const schema = getSchema(fields, key, options);
76
+
77
+ if (!schema) {
78
+ if (stripUnknown) {
39
79
  continue;
40
- } else if (isUnknown) {
41
- throw new LocalizedError('Unknown field "{key}".', {
42
- key,
43
- type: 'field',
44
- });
45
- } else {
46
- result[key] = obj[key];
47
80
  }
81
+ throw new LocalizedError('Unknown field "{key}".', {
82
+ type: 'field',
83
+ key,
84
+ });
85
+ }
86
+
87
+ if (schema.meta.strip?.(value, options)) {
88
+ continue;
48
89
  }
49
- return result;
50
- }
51
- });
52
- for (let [key, schema] of Object.entries(this.export())) {
53
- if (!isSchema(schema)) {
54
- throw new Error(`Key "${key}" must be a schema.`);
55
- }
56
- this.assert('field', async (obj, options) => {
57
- if (obj) {
58
- const { path = [], original } = options;
59
- const { strip, required } = schema.meta;
60
- const val = obj[key];
61
90
 
62
- options = {
91
+ try {
92
+ const validateOptions = {
63
93
  ...options,
64
- required,
94
+
65
95
  path: [...path, key],
96
+ required: schema.meta.required,
97
+
98
+ // The root object may be transformed by defaults
99
+ // or returned values so re-pass it here.
100
+ root: {
101
+ ...obj,
102
+ ...result,
103
+ },
104
+
105
+ // The original root represents the root object
106
+ // before it was transformed.
107
+ originalRoot: original,
66
108
  };
67
109
 
68
- if (strip && strip(val, options)) {
69
- delete obj[key];
70
- return;
71
- }
110
+ if (allowFlatKeys && !value) {
111
+ // When allowing keys like "profile.name", "profile" will
112
+ // not be passed so expand the passed object and make sure
113
+ // the base validates, but do not transform the result.
114
+ const expanded = expandFlatSyntax(passed);
72
115
 
73
- try {
74
- // Do not pass down message into validators
75
- // to allow custom messages to take precedence.
76
- options = omit(options, 'message');
77
- const result = await schema.validate(val, {
78
- ...options,
79
- // The root object may have been transformed here
80
- // by defaults or values returned by custom functions
81
- // so re-pass it here.
82
- root: obj,
83
- // The original root represents the root object
84
- // before it was transformed.
85
- originalRoot: original,
86
- });
87
- if (result !== undefined) {
88
- return {
89
- ...obj,
90
- [key]: result,
91
- };
116
+ await schema.validate(expanded[key], validateOptions);
117
+ } else {
118
+ const transformed = await schema.validate(value, validateOptions);
119
+ if (transformed !== undefined) {
120
+ result[key] = transformed;
92
121
  }
93
- } catch (error) {
94
- const { message } = schema.meta;
95
- throw new FieldError(message, key, error.details);
96
122
  }
123
+ } catch (error) {
124
+ const { message } = schema.meta;
125
+ errors.push(new FieldError(message, key, error.details));
97
126
  }
98
- });
99
- }
127
+ }
128
+
129
+ if (errors.length) {
130
+ errors = normalizeErrors(errors, options);
131
+ throw new AggregateError(this.meta.message, errors);
132
+ }
133
+
134
+ return result;
135
+ });
100
136
  }
101
137
 
102
138
  /**
@@ -117,12 +153,8 @@ class ObjectSchema extends TypeSchema {
117
153
  const [name, ...rest] = path;
118
154
  const schema = fields[name];
119
155
 
120
- if (!schema) {
121
- throw new Error(`Cannot find field "${name}".`);
122
- }
123
-
124
156
  if (rest.length) {
125
- return schema.get(rest);
157
+ return schema?.get(rest);
126
158
  } else {
127
159
  return schema;
128
160
  }
@@ -138,13 +170,15 @@ class ObjectSchema extends TypeSchema {
138
170
  unwind(path) {
139
171
  path = Array.isArray(path) ? path.join('.') : path;
140
172
  const field = this.get(path);
141
- const { schemas } = field.meta;
142
- if (!schemas) {
173
+ const { type, schema } = field.meta;
174
+
175
+ if (type !== 'array') {
143
176
  throw new Error(`Field "${path}" is not an array schema.`);
144
- } else if (schemas.length !== 1) {
145
- throw new Error(`Field "${path}" should contain only one schema.`);
177
+ } else if (!schema) {
178
+ throw new Error(`Field "${path}" does not have an inner schema.`);
146
179
  }
147
- return schemas[0];
180
+
181
+ return schema;
148
182
  }
149
183
 
150
184
  /**
@@ -195,7 +229,11 @@ class ObjectSchema extends TypeSchema {
195
229
  const update = {};
196
230
 
197
231
  for (let field of fields) {
198
- set(update, field, this.get(field).required());
232
+ const schema = this.get(field);
233
+ if (!schema) {
234
+ throw new Error(`Cannot find field "${field}".`);
235
+ }
236
+ set(update, field, schema.required());
199
237
  }
200
238
 
201
239
  return this.append(update);
@@ -290,6 +328,44 @@ class ObjectSchema extends TypeSchema {
290
328
  return schema;
291
329
  }
292
330
 
331
+ // Options
332
+
333
+ /**
334
+ * Remove properties that are empty strings.
335
+ */
336
+ stripEmpty() {
337
+ return this.options({
338
+ stripEmpty: true,
339
+ });
340
+ }
341
+
342
+ /**
343
+ * Remove properties not in the schema.
344
+ */
345
+ stripUnknown() {
346
+ return this.options({
347
+ stripUnknown: true,
348
+ });
349
+ }
350
+
351
+ /**
352
+ * Allow flat keys like `profile.name`.
353
+ */
354
+ allowFlatKeys() {
355
+ return this.options({
356
+ allowFlatKeys: true,
357
+ });
358
+ }
359
+
360
+ /**
361
+ * Expand flat keys into nested objects.
362
+ */
363
+ expandFlatKeys() {
364
+ return this.options({
365
+ expandFlatKeys: true,
366
+ });
367
+ }
368
+
293
369
  /**
294
370
  * `stripEmpty` - Removes properties that are empty strings.
295
371
  * `stripUnknown` - Removes properties not in the schema.
@@ -330,11 +406,7 @@ class ObjectSchema extends TypeSchema {
330
406
  }
331
407
  }
332
408
 
333
- function expandFlatSyntax(obj, options) {
334
- if (!options.expandFlatKeys) {
335
- return obj;
336
- }
337
-
409
+ function expandFlatSyntax(obj) {
338
410
  const result = { ...obj };
339
411
  for (let [key, value] of Object.entries(result)) {
340
412
  if (key.includes('.')) {
@@ -345,65 +417,6 @@ function expandFlatSyntax(obj, options) {
345
417
  return result;
346
418
  }
347
419
 
348
- function isKnownKey(key, schema, options) {
349
- const { fields } = schema.meta;
350
- const { allowFlatKeys } = options;
351
- if (!fields) {
352
- // No fields defined -> all keys are "known".
353
- return true;
354
- } else if (key in fields) {
355
- // Exact match -> key is known.
356
- return true;
357
- } else if (allowFlatKeys && key.includes('.')) {
358
- // Flat syntax "foo.bar".
359
- const [base, ...rest] = key.split('.');
360
- let subschema = fields[base];
361
-
362
- if (!subschema) {
363
- return false;
364
- }
365
-
366
- const { type, schemas } = subschema.meta;
367
-
368
- let subkey;
369
-
370
- if (type === 'array') {
371
- // If the subschema is an array then take the first of
372
- // its defined schemas as we can safely assume that an
373
- // array of objects will be defined as a single element
374
- // or multiple schemas will only set the base property.
375
- // Test that the element key is valid and take any
376
- // further properties as the subkey. Examples:
377
- // - profiles.0.name (array of objects)
378
- // - profiles.0 (array of stringsmk)
379
- const [index, ...other] = rest;
380
- if (!INTEGER_REG.test(index)) {
381
- return false;
382
- }
383
- subschema = schemas[0];
384
- subkey = other.join('.');
385
- } else if (type === 'object') {
386
- // If the subschema is an object then simply take any
387
- // further properties as the subkey. Example:
388
- // - profile.name
389
- subkey = rest.join('.');
390
- } else {
391
- // If the subschema is anything else then disallow it
392
- // further properties as the subkey. Example:
393
- // - profile.name
394
- return false;
395
- }
396
-
397
- if (subschema.meta.type === 'object') {
398
- return isKnownKey(subkey, subschema, options);
399
- } else {
400
- return !subkey;
401
- }
402
- } else {
403
- return false;
404
- }
405
- }
406
-
407
420
  function mergeFields(aFields, bFields) {
408
421
  if (!aFields || !bFields) {
409
422
  return aFields || bFields;
@@ -422,6 +435,79 @@ function mergeFields(aFields, bFields) {
422
435
  return result;
423
436
  }
424
437
 
438
+ // Gets the schema for a field allowing for flat
439
+ // keys which may deeply traverse into the object.
440
+ function getSchema(fields, key, options) {
441
+ const { allowFlatKeys } = options;
442
+
443
+ let schema = fields[key];
444
+
445
+ if (schema) {
446
+ return schema;
447
+ }
448
+
449
+ if (!allowFlatKeys || !key.includes('.')) {
450
+ return;
451
+ }
452
+
453
+ schema = fields;
454
+
455
+ for (let part of key.split('.')) {
456
+ const { type, fields } = schema?.meta || {};
457
+
458
+ if (type === 'array') {
459
+ // If the schema is an array schema then take the first
460
+ // subschema, however only allow integers in this case,
461
+ // for example: profiles.0.name.
462
+
463
+ if (!INTEGER_REG.test(part)) {
464
+ return;
465
+ }
466
+
467
+ schema = schema.meta.schema;
468
+ } else if (fields) {
469
+ schema = fields[part];
470
+ } else {
471
+ schema = schema?.[part];
472
+ }
473
+ }
474
+
475
+ return schema;
476
+ }
477
+
478
+ // If flat keys are allowed then filter out errors
479
+ // that are the nested duplicates so that they match
480
+ // the actual fields that were passed.
481
+ function normalizeErrors(errors, options) {
482
+ const { allowFlatKeys } = options;
483
+ if (allowFlatKeys) {
484
+ errors = errors.filter((error) => {
485
+ const { field } = error;
486
+ const flatField = getFlatField(error);
487
+
488
+ if (field !== flatField) {
489
+ return !errors.some((error) => {
490
+ return error.field === flatField;
491
+ });
492
+ }
493
+
494
+ return true;
495
+ });
496
+ }
497
+ return errors;
498
+ }
499
+
500
+ function getFlatField(error) {
501
+ const { field, details } = error;
502
+ const path = [field];
503
+
504
+ if (details.length === 1 && details[0] instanceof FieldError) {
505
+ path.push(getFlatField(details[0]));
506
+ }
507
+
508
+ return path.join('.');
509
+ }
510
+
425
511
  /**
426
512
  * Creates an [object schema](https://github.com/bedrockio/yada#object).
427
513
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../src/Schema.js"],"names":[],"mappings":"AAiBA,kDAEC;AAED;IACE,uBAGC;IAFC,kBAAoB;IACpB,SAAgB;IAKlB;;;OAGG;IACH,iBAHW,OAAO,GACL,IAAI,CAUhB;IAED;;;OAGG;IACH,mBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,sBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,uBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,mBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,uBAFa,IAAI,CAIhB;IAED;;;;OAIG;IACH,iBAHW,OAAO,GACL,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,iDAwCC;IAED;;OAEG;IACH,kBAFa,IAAI,CAOhB;IAED;;;OAGG;IACH,qBAFa,MAAM,CAMlB;IAED;;;;;;;;;;OAUG;IACH,uBANG;QAA2B,GAAG;QACH,KAAK,GAAxB,QAAQ;QAGU,eAAe,GAAjC,OAAO;KACjB,OASA;IAED;;;OAGG;IACH,6BAEC;IAED;;OAEG;IACH,cAEC;IAED;;MAWC;IAED;;MAKC;IAED;;;;MASC;IAED,2BAgDC;IAED,2BAmBC;IAED;;;;;OAKG;IACH,oCAFa,IAAI,CAgBhB;IAED,kBAEC;IAED,YAGC;IAID;;OAEG;IACH,kCAFa,IAAI,CAsDhB;IAED;;OAEG;IACH,4BAFa,IAAI,CAUhB;IAED,oCAKC;IAED,gEAQC;IAED;;OAEG;IACH,yBAFa,IAAI,CAShB;IAED,gCAGC;IAED,qEAYC;CACF"}
1
+ {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../src/Schema.js"],"names":[],"mappings":"AAkBA,kDAEC;AAED;IACE,uBAGC;IAFC,kBAAoB;IACpB,SAAgB;IAKlB;;;OAGG;IACH,iBAHW,OAAO,GACL,IAAI,CAUhB;IAED;;;OAGG;IACH,mBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,sBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,uBAFa,IAAI,CAShB;IAED;;;;OAIG;IACH,mBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,sBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,uBAFa,IAAI,CAIhB;IAED;;;;OAIG;IACH,iBAHW,OAAO,GACL,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,iDA0CC;IAED;;OAEG;IACH,kBAFa,IAAI,CAOhB;IAED;;;OAGG;IACH,qBAFa,MAAM,CAMlB;IAED;;;;;;;;;;OAUG;IACH,uBANG;QAA2B,GAAG;QACH,KAAK,GAAxB,QAAQ;QAGU,eAAe,GAAjC,OAAO;KACjB,OASA;IAED;;;OAGG;IACH,6BAEC;IAED;;OAEG;IACH,cAEC;IAED;;MAWC;IAED;;MAKC;IAED;;;;MASC;IAED,2BAgDC;IAED,2BAmBC;IAED;;;;;OAKG;IACH,oCAFa,IAAI,CAgBhB;IAED,kBAEC;IAED,YAGC;IAID;;OAEG;IACH,kCAFa,IAAI,CAsDhB;IAED;;OAEG;IACH,4BAFa,IAAI,CAUhB;IAED,oCAKC;IAED,gEAQC;IAED;;OAEG;IACH,yBAFa,IAAI,CAShB;IAED,gCAGC;IAED,qEAYC;CACF"}
package/types/array.d.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  /**
2
2
  * Creates an [array schema](https://github.com/bedrockio/yada#array).
3
3
  *
4
- * @param {...Schema} [schemas] Optional schemas to validate
5
- * the different types of elements allowed in the array. If
6
- * no arguments are passed elements may be of any type. Also
7
- * accepts a single array argument.
4
+ * @param {*} [schema] - The schema to validate elements in
5
+ * the array. If not passed then elements may be of any type.
8
6
  */
9
- export default function _default(...schemas?: Schema[]): ArraySchema;
10
- import Schema from './Schema';
7
+ export default function _default(schema?: any, ...args: any[]): ArraySchema;
11
8
  declare class ArraySchema extends TypeSchema {
9
+ constructor(meta: any);
12
10
  setup(): void;
13
11
  length(length: any): this;
14
12
  min(length: any): this;
@@ -1 +1 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../src/array.js"],"names":[],"mappings":"AA6JA;;;;;;;GAOG;AACH,8CALc,MAAM,EAAA,eAUnB;mBAxKkB,UAAU;AAI7B;IAME,cAsCC;IAED,0BAUC;IAED,uBAUC;IAED,uBAaC;IAED,eAaC;IAED;;;;;OAKG;IACH,yCAFa,IAAI,CAiBhB;IAID,mBAEC;IAED,gCAmBC;CACF;uBAxJsB,cAAc"}
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../src/array.js"],"names":[],"mappings":"AAgJA;;;;;GAKG;AACH,0CAHW,GAAC,+BAYX;AA1JD;IACE,uBAGC;IAED,cAoCC;IAED,0BAUC;IAED,uBAUC;IAED,uBAaC;IAED,eAaC;IAED;;;;;OAKG;IACH,yCAFa,IAAI,CAkBhB;IAID,mBAEC;IAED,gCAQC;CACF;uBA5IsB,cAAc"}
package/types/errors.d.ts CHANGED
@@ -15,6 +15,10 @@ export class ValidationError extends Error {
15
15
  getMessage(): any;
16
16
  getFullMessage(options: any): any;
17
17
  }
18
+ export class AggregateError extends Error {
19
+ constructor(message: any, errors: any);
20
+ errors: any;
21
+ }
18
22
  export class AssertionError extends ValidationError {
19
23
  constructor(message: any, type?: string);
20
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.js"],"names":[],"mappings":"AAqIA,gEAEC;AApID;IACE,uCAEC;CACF;AAED;IACE,+BAA8C;IAE9C,+CAIC;IAFC,aAAwB;IACxB,eAAsB;IAGxB;;;;MAWC;IAED,kBAOC;IAED,kCAKC;CACF;AAED;IACE,yCAGC;CACF;AAED;IACE,qCAIC;IADC,UAAgB;IAGlB;;;;;MAKC;CACF;AAED;IACE,uCAIC;IADC,YAAoB;IAGtB;;;;;MAKC;CACF;AAED;IAGE,uDAIC;IADC,WAAkB;IAGpB;;;;;MAKC;CACF;AAED;IAGE,uDAIC;IADC,WAAkB;IAGpB;;;;;MAKC;CACF;AAED;IACE,wCAGC;CACF;AAED;IACE,wCAGC;CACF"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.js"],"names":[],"mappings":"AA4IA,gEAEC;AA3ID;IACE,uCAEC;CACF;AAED;IACE,+BAA8C;IAE9C,+CAIC;IAFC,aAAwB;IACxB,eAAsB;IAGxB;;;;MAWC;IAED,kBAOC;IAED,kCAKC;CACF;AAED;IACE,uCAGC;IADC,YAAoB;CAEvB;AAED;IACE,yCAGC;CACF;AAED;IACE,qCAIC;IADC,UAAgB;IAGlB;;;;;MAKC;CACF;AAED;IACE,uCAIC;IADC,YAAoB;IAGtB;;;;;MAKC;CACF;AAED;IAGE,uDAIC;IADC,WAAkB;IAGpB;;;;;MAKC;CACF;AAED;IAGE,uDAIC;IADC,WAAkB;IAGpB;;;;;MAKC;CACF;AAED;IACE,wCAGC;CACF;AAED;IACE,wCAGC;CACF"}
package/types/object.d.ts CHANGED
@@ -14,6 +14,7 @@ export type SchemaMap = {
14
14
  */
15
15
  declare class ObjectSchema extends TypeSchema {
16
16
  constructor(meta: any);
17
+ validateInput(): void;
17
18
  setup(): void;
18
19
  /**
19
20
  * Gets the schema for the given field. Deep fields accept
@@ -83,6 +84,22 @@ declare class ObjectSchema extends TypeSchema {
83
84
  * @param {SchemaMap|Schema} arg Object or schema to append.
84
85
  */
85
86
  append(arg: SchemaMap | Schema): ObjectSchema;
87
+ /**
88
+ * Remove properties that are empty strings.
89
+ */
90
+ stripEmpty(): this;
91
+ /**
92
+ * Remove properties not in the schema.
93
+ */
94
+ stripUnknown(): this;
95
+ /**
96
+ * Allow flat keys like `profile.name`.
97
+ */
98
+ allowFlatKeys(): this;
99
+ /**
100
+ * Expand flat keys into nested objects.
101
+ */
102
+ expandFlatKeys(): this;
86
103
  /**
87
104
  * `stripEmpty` - Removes properties that are empty strings.
88
105
  * `stripUnknown` - Removes properties not in the schema.
@@ -1 +1 @@
1
- {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.js"],"names":[],"mappings":"AAwaA;;;;;;GAMG;AACH,uCAJW,SAAS,gBAQnB;wBAxaY;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,EAAE;AAD3C;;GAEG;AAEH;IACE,uBAGC;IAED,cA+EC;IAED;;;;;;OAMG;IACH,WAFW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,OAsB9B;IAED;;;;;;OAMG;IACH,cAFW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,OAY9B;IAED;;;;OAIG;IACH,gBAFc,MAAM,EAAA,gBASnB;IAED;;;;OAIG;IACH,gBAFc,MAAM,EAAA,gBASnB;IAED;;;;;;;OAOG;IACH,mBAHc,MAAM,EAAA,gBAmBnB;IAED;;OAEG;IACH,2BAQC;IAED;;;;;;OAMG;IACH,yCAFa,IAAI,CAiBhB;IAED;;;;;;OAMG;IACH,cAEC;IAED;;;;;;;;;OASG;IACH,YAFW,SAAS,GAAC,MAAM,gBA+B1B;IAED;;;;;;;;;;;OAWG;IACH,kBALG;QAA0B,UAAU,GAA5B,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,aAAa,GAA/B,OAAO;QACW,cAAc,GAAhC,OAAO;KAA0B,QAI3C;IAID,gCAmBC;CACF;mBAxUgC,UAAU;uBACpB,cAAc"}
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.js"],"names":[],"mappings":"AA8fA;;;;;;GAMG;AACH,uCAJW,SAAS,gBAQnB;wBA9fY;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,EAAE;AAD3C;;GAEG;AAEH;IACE,uBAIC;IAED,sBAOC;IAED,cAyGC;IAED;;;;;;OAMG;IACH,WAFW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,OAkB9B;IAED;;;;;;OAMG;IACH,cAFW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,OAc9B;IAED;;;;OAIG;IACH,gBAFc,MAAM,EAAA,gBASnB;IAED;;;;OAIG;IACH,gBAFc,MAAM,EAAA,gBASnB;IAED;;;;;;;OAOG;IACH,mBAHc,MAAM,EAAA,gBAuBnB;IAED;;OAEG;IACH,2BAQC;IAED;;;;;;OAMG;IACH,yCAFa,IAAI,CAiBhB;IAED;;;;;;OAMG;IACH,cAEC;IAED;;;;;;;;;OASG;IACH,YAFW,SAAS,GAAC,MAAM,gBA+B1B;IAID;;OAEG;IACH,mBAIC;IAED;;OAEG;IACH,qBAIC;IAED;;OAEG;IACH,sBAIC;IAED;;OAEG;IACH,uBAIC;IAED;;;;;;;;;;;OAWG;IACH,kBALG;QAA0B,UAAU,GAA5B,OAAO;QACW,YAAY,GAA9B,OAAO;QACW,aAAa,GAA/B,OAAO;QACW,cAAc,GAAhC,OAAO;KAA0B,QAI3C;IAID,gCAmBC;CACF;mBApZgC,UAAU;uBACpB,cAAc"}