isvalid 3.0.2 → 3.1.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/lib/formalize.js CHANGED
@@ -3,7 +3,8 @@
3
3
  const merge = require('merge'),
4
4
  SchemaError = require('./errors/schema.js'),
5
5
  utils = require('./utils.js'),
6
- ranges = require('./ranges.js');
6
+ ranges = require('./ranges.js'),
7
+ plugins = require('./plugins');
7
8
 
8
9
  const finalize = (formalizedSchema, nonFormalizedSchema) => {
9
10
 
@@ -45,7 +46,7 @@ const formalizeObject = (formalizedSchema, nonFormalizedSchema, options) => {
45
46
  }
46
47
  }
47
48
 
48
- return finalize(formalizedSchema, nonFormalizedSchema);
49
+ return formalizedSchema;
49
50
 
50
51
  };
51
52
 
@@ -64,7 +65,7 @@ const formalizeArray = (formalizedSchema, nonFormalizedSchema, options) => {
64
65
  if (formalizedSchema.schema.required === true) formalizedSchema.required = true;
65
66
  }
66
67
 
67
- return finalize(formalizedSchema, nonFormalizedSchema);
68
+ return formalizedSchema;
68
69
 
69
70
  };
70
71
 
@@ -75,11 +76,11 @@ const formalizeAny = (schema, options = {}) => {
75
76
 
76
77
  if (!schema.type && !schema.post && !schema.pre && !schema.equal) {
77
78
  if ('object' == utils.instanceTypeName(schema)) {
78
- return formalizeObject({ type: Object, schema: schema }, schema, options);
79
+ return formalizeAny({ type: Object, schema: schema }, schema, options);
79
80
  }
80
81
  if ('array' == utils.instanceTypeName(schema)) {
81
82
  if (schema.length === 0) return formalizeAny({ type: Array }, schema. options);
82
- return formalizeArray({ type: Array, schema: schema[0] }, schema, options);
83
+ return formalizeAny({ type: Array, schema: schema[0] }, schema, options);
83
84
  }
84
85
  if ((typeof schema === 'string' && schema.length) || (typeof schema === 'function' && utils.typeName(schema) !== undefined)) {
85
86
  return formalizeAny({ type: schema }, schema, options);
@@ -131,6 +132,10 @@ const formalizeAny = (schema, options = {}) => {
131
132
  });
132
133
  }
133
134
 
135
+ const pluginValidators = plugins.validatorsForType(type);
136
+
137
+ merge(validators, pluginValidators);
138
+
134
139
  // If post validator is provided allow for options.
135
140
  if (formalizedSchema.pre !== undefined || formalizedSchema.post !== undefined) {
136
141
  merge(validators, { 'options': 'any' });
@@ -150,6 +155,7 @@ const formalizeAny = (schema, options = {}) => {
150
155
 
151
156
  // Test for - and transform - errors in validator.
152
157
  if (Array.isArray(test) &&
158
+
153
159
  test.length === 2 &&
154
160
  validator.includes(utils.instanceTypeName(test[0]))) {
155
161
 
@@ -260,10 +266,21 @@ const formalizeAny = (schema, options = {}) => {
260
266
  // Finalize objects and arrays if necessary.
261
267
  if (formalizedSchema.type) {
262
268
  if (utils.isSameType('object', utils.typeName(formalizedSchema.type))) {
263
- return formalizeObject(formalizedSchema, schema, options);
269
+ formalizedSchema = formalizeObject(formalizedSchema, schema, options);
264
270
  }
265
- if (utils.isSameType('array', utils.typeName(formalizedSchema.type))) {
266
- return formalizeArray(formalizedSchema, schema, options);
271
+ else if (utils.isSameType('array', utils.typeName(formalizedSchema.type))) {
272
+ formalizedSchema = formalizeArray(formalizedSchema, schema, options);
273
+ }
274
+ }
275
+
276
+ for (const validator of Object.keys(pluginValidators)) {
277
+ try {
278
+ const result = plugins.formalizeValidator(type, validator, formalizedSchema[validator]) || formalizedSchema[validator];
279
+ if (typeof result !== 'undefined') formalizedSchema[validator] = result;
280
+ } catch (error) {
281
+ throw new SchemaError(
282
+ schema,
283
+ error.message);
267
284
  }
268
285
  }
269
286
 
package/lib/index.js CHANGED
@@ -5,3 +5,4 @@ exports.formalize = require('./formalize.js');
5
5
  exports.validate = require('./middleware.js');
6
6
  exports.keyPaths = require('./key-paths');
7
7
  exports.merge = require('./merge');
8
+ exports.plugins = require('./plugins');
package/lib/plugins.js ADDED
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const
4
+ merge = require('merge'),
5
+ utils = require('./utils');
6
+
7
+ exports = module.exports = {
8
+ _plugins: []
9
+ };
10
+
11
+ exports.use = function(plugin) {
12
+ this._plugins.push(merge(plugin(utils), {
13
+ _validatorsForType: function(type) {
14
+ return Object.fromEntries(
15
+ Object.entries(
16
+ this.validatorsForType(type))
17
+ .map(([key, value]) => {
18
+ if (typeof value !== 'string') value = utils.typeName(value);
19
+ return [key, !Array.isArray(value) ? [value] : value];
20
+ })
21
+ );
22
+ }
23
+ }));
24
+ };
25
+
26
+ exports.validatorsForType = function(type) {
27
+ return Object.fromEntries(Object.entries(merge(...this._plugins
28
+ .filter((plugin) => plugin.supportsType(type))
29
+ .map((plugin) => plugin._validatorsForType(type)))));
30
+
31
+ };
32
+
33
+ exports.formalizeValidator = function(type, identifier, config) {
34
+ return this._plugins
35
+ .filter((plugin) => plugin.supportsType(type))
36
+ .filter((plugin) => Object.keys(plugin._validatorsForType(type)).includes(identifier))
37
+ .reduce((config, plugin) => {
38
+ if (typeof plugin.formalizeValidator !== 'function') return config;
39
+ return plugin.formalizeValidator(type, identifier, config);
40
+ }, config);
41
+ };
42
+
43
+ exports.validate = async function(type, identifier, config, data) {
44
+
45
+ const plugins = this._plugins
46
+ .filter((plugin) => plugin.supportsType(type));
47
+
48
+ for (const plugin of plugins) {
49
+ data = await plugin.validate(type, identifier, config, data);
50
+ }
51
+
52
+ return data;
53
+
54
+ };
package/lib/utils.js CHANGED
@@ -13,5 +13,5 @@ exports.isSameType = function(obj1, obj2) {
13
13
  if (typeof obj1 === 'undefined' || typeof obj2 === 'undefined') {
14
14
  return typeof obj1 === typeof obj2;
15
15
  }
16
- return obj1.toLowerCase() == obj2.toLowerCase();
16
+ return exports.typeName(obj1).toLowerCase() == exports.typeName(obj2).toLowerCase();
17
17
  };
package/lib/validate.js CHANGED
@@ -5,7 +5,8 @@ const ValidationError = require('./errors/validation.js'),
5
5
  unique = require('./unique.js'),
6
6
  formalize = require('./formalize.js'),
7
7
  utils = require('./utils.js'),
8
- equals = require('./equals.js');
8
+ equals = require('./equals.js'),
9
+ plugins = require('./plugins.js');
9
10
 
10
11
  const checkBoolValue = (name, schema, defaults) => {
11
12
  if (schema[name] === undefined) return defaults[name] === true;
@@ -403,6 +404,13 @@ const validateAny = async (data, schema, options, keyPath, validatedData) => {
403
404
  }
404
405
  }
405
406
 
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
+
406
414
  return await validatePost(data, schema, options, keyPath, validatedData);
407
415
 
408
416
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isvalid",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "Async JSON validation library for node.js.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -18,6 +18,7 @@
18
18
  "merge": "^2.1.1"
19
19
  },
20
20
  "devDependencies": {
21
+ "@trenskow/caseit": "^1.2.0",
21
22
  "body-parser": "^1.20.0",
22
23
  "chai": "^4.3.6",
23
24
  "chai-as-promised": "^7.1.1",
package/test/formalize.js CHANGED
@@ -179,5 +179,11 @@ describe('schema', function() {
179
179
  it ('should throw error if array len is negative.', () => {
180
180
  expect(f({ type: Array, len: '-2-' })).to.throw(SchemaError);
181
181
  });
182
+ it ('should throw error if validator is not supported', () => {
183
+ expect(f({ type: String, nonExistingValidator: 'myValue' })).to.throw(SchemaError);
184
+ });
185
+ it ('should throw error if plugin validator fails formalizing.', () => {
186
+ expect(f({ type: String, casing: 'not-supported' })).to.throw(SchemaError);
187
+ });
182
188
  });
183
189
  });
package/test/index.js CHANGED
@@ -1,10 +1,24 @@
1
1
  'use strict';
2
2
 
3
3
  const chai = require('chai'),
4
- chaiAsPromised = require('chai-as-promised');
4
+ chaiAsPromised = require('chai-as-promised'),
5
+ caseit = require('@trenskow/caseit'),
6
+ isvalid = require('../');
5
7
 
6
8
  chai.use(chaiAsPromised);
7
9
 
10
+ isvalid.plugins.use(function (utils) {
11
+ return {
12
+ supportsType: (type) => utils.isSameType(type, String),
13
+ validatorsForType: () => { return { casing: String }; },
14
+ formalizeValidator: (_, __, config) => {
15
+ if (!config) return;
16
+ if (!caseit.supported.includes(config)) throw new Error(`Only case types: ${caseit.supported.map((casing) => `\`${casing}\``).join(', ')} are supported.`);
17
+ },
18
+ validate: (_, __, config, data) => caseit(data, config)
19
+ };
20
+ });
21
+
8
22
  require('./ranges.js');
9
23
  require('./equals.js');
10
24
  require('./unique.js');
package/test/validate.js CHANGED
@@ -756,4 +756,9 @@ describe('validate', function() {
756
756
  describe('other validator', function() {
757
757
  commonTests.all(Test, new Test(), 123);
758
758
  });
759
+ describe('plugin validators', function() {
760
+ it ('should come back with correct case value.', function() {
761
+ return expect(isvalid('my-string', { type: String, casing: 'camel' })).to.eventually.eql('myString');
762
+ });
763
+ });
759
764
  });