isvalid 3.1.0 → 3.1.3
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/lib/formalize.js +11 -9
- package/lib/plugins.js +4 -4
- package/lib/validate.js +30 -13
- package/package.json +1 -1
- package/test/index.js +7 -5
- package/test/validate.js +13 -2
package/lib/formalize.js
CHANGED
|
@@ -27,7 +27,9 @@ const formalizeObject = (formalizedSchema, nonFormalizedSchema, options) => {
|
|
|
27
27
|
|
|
28
28
|
formalizedSchema.schema = formalizedSchema.schema || {};
|
|
29
29
|
|
|
30
|
-
if (utils.instanceTypeName(formalizedSchema.schema) !== 'object')
|
|
30
|
+
if (utils.instanceTypeName(formalizedSchema.schema) !== 'object') {
|
|
31
|
+
throw new SchemaError(formalizedSchema.schema, 'Object schemas must be an object.');
|
|
32
|
+
}
|
|
31
33
|
|
|
32
34
|
// Build new formalized schema into this.
|
|
33
35
|
let formalizedSubSchema = {};
|
|
@@ -38,7 +40,7 @@ const formalizeObject = (formalizedSchema, nonFormalizedSchema, options) => {
|
|
|
38
40
|
formalizedSubSchema[key] = formalizeAny(formalizedSchema.schema[key], options);
|
|
39
41
|
});
|
|
40
42
|
|
|
41
|
-
formalizedSchema.schema = formalizedSubSchema;
|
|
43
|
+
formalizedSchema.schema = finalize(formalizedSubSchema, nonFormalizedSchema.schema);
|
|
42
44
|
|
|
43
45
|
if (typeof formalizedSchema.required === 'undefined') {
|
|
44
46
|
if (Object.keys(formalizedSubSchema).some((key) => formalizedSubSchema[key].required === true || formalizedSubSchema[key].required === 'implicit')) {
|
|
@@ -50,13 +52,13 @@ const formalizeObject = (formalizedSchema, nonFormalizedSchema, options) => {
|
|
|
50
52
|
|
|
51
53
|
};
|
|
52
54
|
|
|
53
|
-
const formalizeArray = (formalizedSchema,
|
|
55
|
+
const formalizeArray = (formalizedSchema, options) => {
|
|
54
56
|
|
|
55
57
|
// formalizedSchema has been pre-processed by formalizeAny, so
|
|
56
58
|
// we only need to formalize the sub-schema.
|
|
57
59
|
|
|
58
60
|
// If no sub-schema is provided we consider the schema final.
|
|
59
|
-
if (typeof formalizedSchema.schema === 'undefined') return
|
|
61
|
+
if (typeof formalizedSchema.schema === 'undefined') return formalizedSchema;
|
|
60
62
|
|
|
61
63
|
formalizedSchema.schema = formalizeAny(formalizedSchema.schema, options);
|
|
62
64
|
|
|
@@ -76,14 +78,14 @@ const formalizeAny = (schema, options = {}) => {
|
|
|
76
78
|
|
|
77
79
|
if (!schema.type && !schema.post && !schema.pre && !schema.equal) {
|
|
78
80
|
if ('object' == utils.instanceTypeName(schema)) {
|
|
79
|
-
return formalizeAny({ type: Object, schema: schema },
|
|
81
|
+
return formalizeAny({ type: Object, schema: schema }, options);
|
|
80
82
|
}
|
|
81
83
|
if ('array' == utils.instanceTypeName(schema)) {
|
|
82
|
-
if (schema.length === 0) return formalizeAny({ type: Array },
|
|
83
|
-
return formalizeAny({ type: Array, schema: schema[0] },
|
|
84
|
+
if (schema.length === 0) return formalizeAny({ type: Array }, options);
|
|
85
|
+
return formalizeAny({ type: Array, schema: schema[0] }, options);
|
|
84
86
|
}
|
|
85
87
|
if ((typeof schema === 'string' && schema.length) || (typeof schema === 'function' && utils.typeName(schema) !== undefined)) {
|
|
86
|
-
return formalizeAny({ type: schema },
|
|
88
|
+
return formalizeAny({ type: schema }, options);
|
|
87
89
|
}
|
|
88
90
|
throw new SchemaError(schema, 'Schemas must have at least on validator of `type`, `post`/`pre` and/or `equal`.');
|
|
89
91
|
}
|
|
@@ -269,7 +271,7 @@ const formalizeAny = (schema, options = {}) => {
|
|
|
269
271
|
formalizedSchema = formalizeObject(formalizedSchema, schema, options);
|
|
270
272
|
}
|
|
271
273
|
else if (utils.isSameType('array', utils.typeName(formalizedSchema.type))) {
|
|
272
|
-
formalizedSchema = formalizeArray(formalizedSchema,
|
|
274
|
+
formalizedSchema = formalizeArray(formalizedSchema, options);
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
|
package/lib/plugins.js
CHANGED
|
@@ -23,9 +23,9 @@ exports.use = function(plugin) {
|
|
|
23
23
|
}));
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
exports.validatorsForType = function(type) {
|
|
26
|
+
exports.validatorsForType = function(type, phase) {
|
|
27
27
|
return Object.fromEntries(Object.entries(merge(...this._plugins
|
|
28
|
-
.filter((plugin) => plugin.supportsType(type))
|
|
28
|
+
.filter((plugin) => (!phase || (plugin.phase || 'post') === phase) && plugin.supportsType(type))
|
|
29
29
|
.map((plugin) => plugin._validatorsForType(type)))));
|
|
30
30
|
|
|
31
31
|
};
|
|
@@ -36,7 +36,7 @@ exports.formalizeValidator = function(type, identifier, config) {
|
|
|
36
36
|
.filter((plugin) => Object.keys(plugin._validatorsForType(type)).includes(identifier))
|
|
37
37
|
.reduce((config, plugin) => {
|
|
38
38
|
if (typeof plugin.formalizeValidator !== 'function') return config;
|
|
39
|
-
return plugin.formalizeValidator(
|
|
39
|
+
return plugin.formalizeValidator(config, identifier, type);
|
|
40
40
|
}, config);
|
|
41
41
|
};
|
|
42
42
|
|
|
@@ -46,7 +46,7 @@ exports.validate = async function(type, identifier, config, data) {
|
|
|
46
46
|
.filter((plugin) => plugin.supportsType(type));
|
|
47
47
|
|
|
48
48
|
for (const plugin of plugins) {
|
|
49
|
-
data = await plugin.validate(
|
|
49
|
+
data = await plugin.validate(data, config, identifier, type);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
return data;
|
package/lib/validate.js
CHANGED
|
@@ -299,16 +299,38 @@ const validateOther = async (data, schema, options, keyPath) => {
|
|
|
299
299
|
|
|
300
300
|
};
|
|
301
301
|
|
|
302
|
-
const validateCustom = async (
|
|
302
|
+
const validateCustom = async (phase, data, schema, options, keyPath, validatedData) => {
|
|
303
303
|
|
|
304
|
-
if (!schema[
|
|
304
|
+
if (!schema[phase]) return data;
|
|
305
305
|
|
|
306
|
-
for (let idx = 0 ; idx < schema[
|
|
306
|
+
for (let idx = 0 ; idx < schema[phase].length ; idx++) {
|
|
307
307
|
try {
|
|
308
|
-
let result = await Promise.resolve(schema[
|
|
308
|
+
let result = await Promise.resolve(schema[phase][idx](data, schema, { options, keyPath, data: validatedData }));
|
|
309
309
|
if (typeof result !== 'undefined') data = result;
|
|
310
310
|
} catch (error) {
|
|
311
|
-
throw ValidationError.fromError(keyPath, schema._nonFormalizedSchema,
|
|
311
|
+
throw ValidationError.fromError(keyPath, schema._nonFormalizedSchema, phase, error);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return data;
|
|
316
|
+
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const validatePlugins = async (phase, data, schema, options, keyPath) => {
|
|
320
|
+
|
|
321
|
+
const pluginValidators = Object.keys(plugins.validatorsForType(schema.type, phase))
|
|
322
|
+
.filter((validator) => typeof schema[validator] !== 'undefined');
|
|
323
|
+
|
|
324
|
+
for (const pluginValidator of pluginValidators) {
|
|
325
|
+
try {
|
|
326
|
+
data = await plugins.validate(schema.type, pluginValidator, schema[pluginValidator], data);
|
|
327
|
+
} catch (error) {
|
|
328
|
+
throw new ValidationError(
|
|
329
|
+
keyPath,
|
|
330
|
+
schema._nonFormalizedSchema,
|
|
331
|
+
pluginValidator,
|
|
332
|
+
(schema.errors || {})[pluginValidator] || customErrorMessage((options.errorMessages || {})[pluginValidator] || error.message)
|
|
333
|
+
);
|
|
312
334
|
}
|
|
313
335
|
}
|
|
314
336
|
|
|
@@ -317,10 +339,12 @@ const validateCustom = async (type, data, schema, options, keyPath, validatedDat
|
|
|
317
339
|
};
|
|
318
340
|
|
|
319
341
|
const validatePre = async (data, schema, options, keyPath, validatedData) => {
|
|
320
|
-
|
|
342
|
+
data = await validateCustom('pre', data, schema, options, keyPath, validatedData);
|
|
343
|
+
return await validatePlugins('pre', data, schema, options, keyPath);
|
|
321
344
|
};
|
|
322
345
|
|
|
323
346
|
const validatePost = async (data, schema, options, keyPath, validatedData) => {
|
|
347
|
+
data = await validatePlugins('post', data, schema, options, keyPath);
|
|
324
348
|
return await validateCustom('post', data, schema, options, keyPath, validatedData);
|
|
325
349
|
};
|
|
326
350
|
|
|
@@ -404,13 +428,6 @@ const validateAny = async (data, schema, options, keyPath, validatedData) => {
|
|
|
404
428
|
}
|
|
405
429
|
}
|
|
406
430
|
|
|
407
|
-
const pluginValidators = Object.keys(plugins.validatorsForType(schema.type))
|
|
408
|
-
.filter((validator) => typeof schema[validator] !== 'undefined');
|
|
409
|
-
|
|
410
|
-
for (const pluginValidator of pluginValidators) {
|
|
411
|
-
data = await plugins.validate(schema.type, pluginValidator, schema[pluginValidator], data);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
431
|
return await validatePost(data, schema, options, keyPath, validatedData);
|
|
415
432
|
|
|
416
433
|
};
|
package/package.json
CHANGED
package/test/index.js
CHANGED
|
@@ -10,12 +10,14 @@ chai.use(chaiAsPromised);
|
|
|
10
10
|
isvalid.plugins.use(function (utils) {
|
|
11
11
|
return {
|
|
12
12
|
supportsType: (type) => utils.isSameType(type, String),
|
|
13
|
-
validatorsForType: () => { return {
|
|
14
|
-
formalizeValidator: (
|
|
15
|
-
if (!config)
|
|
16
|
-
if (!caseit.supported.includes(config)) throw new Error(`Only case types: ${caseit.supported.map((casing) => `\`${casing}\``).join(', ')} are supported.`);
|
|
13
|
+
validatorsForType: () => { return { ensureCase: String }; },
|
|
14
|
+
formalizeValidator: (config) => {
|
|
15
|
+
if (config && !caseit.supported.includes(config)) throw new Error(`Only case types: ${caseit.supported.map((casing) => `\`${casing}\``).join(', ')} are supported.`);
|
|
17
16
|
},
|
|
18
|
-
validate: (
|
|
17
|
+
validate: (data, config) => {
|
|
18
|
+
if (caseit(data, config) !== data) throw new Error(`Is not ${config} case.`);
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
19
21
|
};
|
|
20
22
|
});
|
|
21
23
|
|
package/test/validate.js
CHANGED
|
@@ -757,8 +757,19 @@ describe('validate', function() {
|
|
|
757
757
|
commonTests.all(Test, new Test(), 123);
|
|
758
758
|
});
|
|
759
759
|
describe('plugin validators', function() {
|
|
760
|
-
it ('should
|
|
761
|
-
return expect(isvalid('my-string', { type: String,
|
|
760
|
+
it ('should throw error if casing does not match.', function() {
|
|
761
|
+
return expect(isvalid('my-string', { type: String, ensureCase: 'camel' }))
|
|
762
|
+
.to.eventually.rejectedWith(ValidationError)
|
|
763
|
+
.and.to.have.property('message', 'Is not camel case.');
|
|
764
|
+
});
|
|
765
|
+
it ('should throw error with custom message if casing does not match.', function() {
|
|
766
|
+
return expect(isvalid('my-string', { type: String, ensureCase: ['camel', 'Something is not right!'] }))
|
|
767
|
+
.to.eventually.rejectedWith(ValidationError)
|
|
768
|
+
.and.to.have.property('message', 'Something is not right!');
|
|
769
|
+
});
|
|
770
|
+
it ('should come back with correct value.', function() {
|
|
771
|
+
return expect(isvalid('myString', { type: String, ensureCase: 'camel' }))
|
|
772
|
+
.to.eventually.equal('myString');
|
|
762
773
|
});
|
|
763
774
|
});
|
|
764
775
|
});
|