New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

async-validate

Package Overview
Dependencies
Maintainers
1
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-validate - npm Package Compare versions

Comparing version 0.3.6 to 0.4.0

test/spec/iterator.js

2

doc/readme/guide.md

@@ -126,3 +126,3 @@ ## Guide

{type: "string", required: true},
function(opts, cb) {
function(cb) {
// test if email address already exists in a database

@@ -129,0 +129,0 @@ // and add a validation error to the errors array if it does

@@ -5,7 +5,5 @@ /**

function ValidationError(msg) {
this.name = ValidationError.name;
Error.call(this);
//if(!(this instanceof ValidationError)) {
//return new ValidationError(msg);
//}
this.message = msg || this.name;
this.message = msg;
}

@@ -12,0 +10,0 @@

@@ -21,2 +21,3 @@ function format(fmt) {

}
args.unshift(arg);
return match;

@@ -28,4 +29,8 @@ })

if(args.length) {
fmt += args.join(' ');
fmt += ' ' + args.join(' ');
}
// update escaped %% values
fmt = fmt.replace(/%{2,2}/g, '%');
return '' + fmt;

@@ -32,0 +37,0 @@ }

@@ -6,2 +6,3 @@ function mapSeries(list, cb, complete) {

cb(item, function(err, result) {
/* istanbul ignore next: not going to mock this */
if(err) {

@@ -28,2 +29,3 @@ return complete(err, out);

cb(item, function(err, result) {
/* istanbul ignore next: not going to mock this */
if(err) {

@@ -30,0 +32,0 @@ return complete(err, out);

@@ -16,2 +16,3 @@ var iterator = require('./iterator')

this.rules = {};
this.keys = [];
this.messages(opts.messages || require('../messages'));

@@ -55,5 +56,41 @@ this.define(descriptor);

}
this.keys = Object.keys(this.rules);
}
/**
* Collates the errors arrays and maps field names to errors
* specific to the field.
*/
function complete(results, options, callback) {
var i, field, errors = [], fields = {};
function add(e) {
if((e instanceof Error)) {
errors.push(e);
}else if(Array.isArray(e)) {
errors = errors.concat.apply(errors, e);
}
}
for(i = 0;i < results.length;i++) {
add(results[i]);
}
if(!errors.length) {
errors = null, fields = null;
}else{
if(options.single) {
errors = errors.slice(0,1);
}
for(i = 0;i < errors.length;i++) {
field = errors[i].field;
fields[field] = fields[field] || [];
fields[field].push(errors[i]);
}
}
callback(errors, fields);
}
/**
* Validate an object against this schema.

@@ -63,66 +100,52 @@ *

* @param options Validation options.
* @param callback A callback to invoke when validation is complete.
* @param cb Callback to invoke when validation is complete.
*/
function validate(source, options, callback) {
if(!this.rules) {
throw new Error('Cannot validate with no rules.');
}
function validate(source, options, cb) {
options = options || {};
if(typeof options == 'function') {
callback = options;
cb = options;
options = {};
}
var complete = function(results) {
var i, field, errors = [], fields = {};
var add = function(e) {
if((e instanceof Error)) {
errors.push(e);
}else if(Array.isArray(e)) {
errors = errors.concat.apply(errors, e);
}
}
for(i = 0;i < results.length;i++) {
add(results[i]);
}
if(!errors.length) {
errors = null, fields = null;
}else{
if(options.single) {
errors = errors.slice(0,1);
}
for(i = 0;i < errors.length;i++) {
field = errors[i].field;
fields[field] = fields[field] || [];
fields[field].push(errors[i]);
}
}
callback(errors, fields);
if(!this.keys.length) {
throw new Error('Cannot validate with no rules.');
}else if(!source) {
throw new Error('Cannot validate with no source.');
}else if(typeof cb !== 'function') {
throw new Error('Cannot validate with no callback.');
}
var messages = options.messages || this.messages();
options.messages = messages;
var j, z, arr, value, i, rule, validator, series = [];
var keys = options.keys || Object.keys(this.rules);
var func = options.parallel ? iterator.map : iterator.mapSeries;
for(j = 0;j < keys.length;j++) {
z = keys[j]; arr = this.rules[z]; value = source[z];
//console.log('validate on key %s', z);
z = keys[j];
arr = this.rules[z];
value = source[z];
for(i = 0;i < arr.length;i++) {
rule = arr[i];
//console.log('validate on rule %j', rule);
if(typeof(rule.transform) == 'function') {
// handle transformation
if(typeof(rule.transform) === 'function') {
value = source[z] = rule.transform(value);
}
if(typeof(rule) == 'function') {
// wrap inline functions
if(typeof(rule) === 'function') {
rule = {validator: rule};
}
rule.field = z;
rule.type = this.getType(rule);
rule.validator = this.getValidationMethod(rule);
if(!rule.validator) {
continue;
}
series.push({rule: rule, value: value, source: source, field: z});
}
}
var func = options.parallel ? iterator.map : iterator.mapSeries;
func(series, function(data, callback) {

@@ -134,10 +157,19 @@ var rule = data.rule;

rule.field = data.field;
var cb = function(errors) {
function onValidate(errors) {
// bail on first error
if(options.first && errors && errors.length) {
return complete(errors);
return complete(errors, options, cb);
}
// not deep so continue on to next in series
if(!deep) {
callback(null, errors);
// generate temp schema for nested rules
}else{
/* istanbul ignore next: always testing with errors array */
errors = errors || [];
// if rule is required but the target object

@@ -152,2 +184,3 @@ // does not exist fail at the rule level and don't

}
var schema = new Schema(data.rule.fields);

@@ -165,6 +198,5 @@ schema.messages(options.messages);

var opts = getValidationOptions(rule, data, options);
rule.validator.call(opts, cb);
rule.validator.call(getValidationOptions(rule, data, options), onValidate);
}, function(err, results) {
complete(results);
complete(results, options, cb);
});

@@ -217,3 +249,3 @@ }

}
return validators[rule.type] || false;
return validators[rule.type];
}

@@ -220,0 +252,0 @@

@@ -1,2 +0,2 @@

var plugsys = require('zephyr')
var plugin = require('zephyr')
, format = require('./format')

@@ -30,5 +30,5 @@ , types = require('./type-test')

if(arguments.length > 1) {
var args = Array.prototype.slice.call(arguments);
msg = format.apply(null, args);
if(arguments.length > 1 && !this.rule.message) {
var args = Array.prototype.slice.call(arguments, 1);
msg = format.apply(null, [msg].concat(args));
}

@@ -43,11 +43,8 @@ var err = new ValidationError(msg);

*/
function raise(message, parameters) {
if(arguments.length > 1
&& !Array.isArray(parameters)) {
function raise(message) {
var parameters = [];
if(arguments.length > 1) {
parameters = Array.prototype.slice.call(arguments, 1);
}
if(typeof message === 'string' && Array.isArray(parameters)) {
message = format.apply(null, [message].concat(parameters));
}
var err = this.error(message);
var err = this.error.apply(this, [message].concat(parameters));
this.errors.push(err);

@@ -61,3 +58,3 @@ }

if(this.rule.required
&& (!this.source.hasOwnProperty(this.rule.field)
&& (!this.source.hasOwnProperty(this.field)
|| this.value === undefined || this.value === null)) {

@@ -81,3 +78,3 @@ this.raise(this.messages.required, this.field);

function enumerable() {
var list = Array.isArray(this.rule.enum) ? this.rule.enum : [];
var list = this.rule.enum;
if(list.indexOf(this.value) === -1) {

@@ -132,9 +129,9 @@ this.raise(this.messages.enum, this.field, list.join(', '));

if(len && (val !== rule.len)) {
this.raise(this.messages[key].len, rule.field, rule.len);
this.raise(this.messages[key].len, this.field, rule.len);
}else if( min && !max && val < rule.min ) {
this.raise(this.messages[key].min, rule.field, rule.min);
this.raise(this.messages[key].min, this.field, rule.min);
}else if( max && !min && val > rule.max ) {
this.raise(this.messages[key].max, rule.field, rule.max);
this.raise(this.messages[key].max, this.field, rule.max);
}else if(min && max && (val < rule.min || val > rule.max) ) {
this.raise(this.messages[key].range, rule.field, rule.min, rule.max);
this.raise(this.messages[key].range, this.field, rule.min, rule.max);
}

@@ -193,2 +190,2 @@ }

module.exports = plugsys({type: Validator});
module.exports = plugin({type: Validator});

@@ -11,3 +11,2 @@ /**

format: "%s date %s is invalid for format %s",
parse: "%s date could not be parsed, %s is invalid ",
invalid: "%s date %s is invalid"

@@ -14,0 +13,0 @@ },

{
"name": "async-validate",
"description": "Asynchronous validation for object properties.",
"version": "0.3.6",
"version": "0.4.0",
"author": "muji <noop@xpm.io>",

@@ -60,5 +60,5 @@ "license": "MIT",

"guide.md",
"transform.md",
"messages.md",
"standard-rules.md"
"standard-rules.md",
"transform.md"
]

@@ -65,0 +65,0 @@ },

@@ -9,7 +9,4 @@ /**

this.required();
if(this.rule.required || this.value !== undefined) {
this.type();
this.range();
}
this.type();
this.range();
}

@@ -16,0 +13,0 @@ cb(this.errors);

@@ -8,29 +8,15 @@ var format = require('../lib/format')

function validator() {
if(!this.rule.required
&& (this.value === undefined || this.value === '')) {
return false;
}
var mmt = this.rule.local ? moment : moment.utc;
var dt = !this.rule.format
? mmt(new Date(this.value)) : mmt(this.value, this.rule.format);
//console.log('value %s', value);
//console.log('format %s', rule.format);
//console.log('date %s', dt);
//console.log('date valid %s', dt.isValid());
if(!dt) {
this.raise(
format(this.messages.date.parse, this.rule.field, this.value));
}else if(!dt.isValid()) {
if(!dt.isValid()) {
if(this.rule.format) {
this.raise(
format(this.messages.date.format,
this.rule.field, this.value, this.rule.format));
this.field, this.value, this.rule.format));
}else{
this.raise(
format(this.messages.date.invalid, this.rule.field, this.value));
format(this.messages.date.invalid, this.field, this.value));
}
}
return true;
}

@@ -45,4 +31,4 @@

var validate = this.rule.required
|| (!this.rule.required && this.source.hasOwnProperty(this.rule.field)
&& this.source[this.rule.field]);
|| (!this.rule.required && this.source.hasOwnProperty(this.field)
&& this.source[this.field]);
if(validate) {

@@ -49,0 +35,0 @@ this.required();

@@ -9,5 +9,3 @@ /**

this.required();
if(this.rule.required || this.value !== undefined) {
this.type();
}
this.type();
}

@@ -14,0 +12,0 @@ cb(this.errors);

@@ -20,3 +20,2 @@ Table of Contents

* [Deep Rules](#deep-rules)
* [Transform](#transform)
* [Messages](#messages)

@@ -28,2 +27,3 @@ * [Standard Rules](#standard-rules)

* [Hex](#hex)
* [Transform](#transform)
* [API](#api)

@@ -204,3 +204,3 @@ * [Validate](#validate)

{type: "string", required: true},
function(opts, cb) {
function(cb) {
// test if email address already exists in a database

@@ -275,8 +275,2 @@ // and add a validation error to the errors array if it does

### Transform
Sometimes it is necessary to transform a value before validation, possibly to coerce the value or to sanitize it in some way. To do this add a `transform` function to the validation rule. The property is transformed prior to validation and re-assigned to the source object to mutate the value of the property in place.
Without the `transform` function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.
### Messages

@@ -367,2 +361,8 @@

### Transform
Sometimes it is necessary to transform a value before validation, possibly to coerce the value or to sanitize it in some way. To do this add a `transform` function to the validation rule. The property is transformed prior to validation and re-assigned to the source object to mutate the value of the property in place.
Without the `transform` function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.
```javascript

@@ -369,0 +369,0 @@ var schema = require('..')

function id(cb) {
var re = /^[^-][a-zA-Z0-9-]+$/;
if(!re.test(this.value)) {
this.raise('%s is not a valid identifier', this.rule.field);
this.raise('%s is not a valid identifier', this.field);
}

@@ -6,0 +6,0 @@ cb(this.errors);

@@ -71,2 +71,15 @@ var util = require('util');

});
it("should validate date value using a format and local", function(done) {
var descriptor = {
active: {type: "date", format: "YYYY-MM-DD", local: true}
}
var validator = new schema(descriptor);
validator.validate({active: "2013-06-24"}, function(errors, fields) {
assert.isNull(errors);
assert.isNull(fields);
done();
});
});
it("should validate date value no format (ISO 8601)", function(done) {

@@ -73,0 +86,0 @@ var descriptor = {

@@ -6,2 +6,9 @@ var expect = require('chai').expect

it("should use format string", function(done) {
var res = format('foo');
expect(res).to.eql('foo');
done();
});
it("should format string (%s)", function(done) {

@@ -43,2 +50,8 @@ var res = format('%s', 'foo');

it("should format escaped string (%s)", function(done) {
var res = format('%%s', 'foo');
expect(res).to.eql('%s foo');
done();
});
});

@@ -1,6 +0,8 @@

var util = require('util');
var assert = require('chai').assert;
var assert = require('chai').assert
, expect = require('chai').expect;
var schema = require('../../index');
describe("async-validate:", function() {
it("should allow undefined integer field if not required", function(done) {

@@ -20,2 +22,3 @@ var descriptor = {

});
it("should allow undefined integer field if not required (first)",

@@ -37,2 +40,3 @@ function(done) {

);
it("should error on invalid integer field if not required (first/single)",

@@ -55,2 +59,147 @@ function(done) {

);
it("should allow undefined array field if not required", function(done) {
var descriptor = {
mock: {type: 'array', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined boolean field if not required", function(done) {
var descriptor = {
mock: {type: 'boolean', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined date field if not required", function(done) {
var descriptor = {
mock: {type: 'date', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined enum field if not required", function(done) {
var descriptor = {
mock: {type: 'enum', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined float field if not required", function(done) {
var descriptor = {
mock: {type: 'float', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined method field if not required", function(done) {
var descriptor = {
mock: {type: 'method', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined number field if not required", function(done) {
var descriptor = {
mock: {type: 'number', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined object field if not required", function(done) {
var descriptor = {
mock: {type: 'object', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined pattern field if not required", function(done) {
var descriptor = {
mock: {type: 'pattern', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined regexp field if not required", function(done) {
var descriptor = {
mock: {type: 'regexp', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
it("should allow undefined string field if not required", function(done) {
var descriptor = {
mock: {type: 'string', required: false}
}
var validator = new schema(descriptor);
var source = {mock: undefined};
var opts = {};
validator.validate(source, opts, function(errors, fields) {
expect(errors).to.eql(null);
done();
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc