revalidator
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -45,3 +45,3 @@ // | ||
req.method = req.method.toUpperCase(); | ||
// | ||
@@ -51,3 +51,3 @@ // Log the requests | ||
console.log(req.method, req.url); | ||
// | ||
@@ -60,3 +60,3 @@ // Buffer the request so it can be parsed as JSON | ||
}); | ||
// | ||
@@ -66,3 +66,3 @@ // Once the request has ended work with the body | ||
req.on('end', function dealWithRest () { | ||
// | ||
@@ -85,3 +85,3 @@ // Parse the JSON | ||
} | ||
// | ||
@@ -95,3 +95,3 @@ // If this was sent to a url but the body url was not declared | ||
} | ||
// | ||
@@ -105,3 +105,3 @@ // Don't let users override the main API endpoint | ||
} | ||
// | ||
@@ -117,3 +117,3 @@ // See if our request and target are out of sync | ||
} | ||
// | ||
@@ -128,3 +128,3 @@ // Validate the schema | ||
} | ||
// | ||
@@ -147,3 +147,3 @@ // Grab the current value from storage and | ||
} | ||
// | ||
@@ -157,3 +157,3 @@ // Check our challenge | ||
} | ||
// | ||
@@ -168,3 +168,3 @@ // Since revalidator only checks and does not manipulate | ||
} | ||
// | ||
@@ -175,3 +175,3 @@ // Use REST to determine how to manipulate the stored | ||
switch (req.method) { | ||
case "GET": | ||
@@ -178,0 +178,0 @@ res.writeHead(200); |
(function (exports) { | ||
exports.validate = validate; | ||
exports.mixin = mixin; | ||
// | ||
@@ -38,3 +38,3 @@ // ### function validate (object, schema, options) | ||
// | ||
return { | ||
@@ -45,3 +45,3 @@ valid: !(errors.length), | ||
}; | ||
/** | ||
@@ -88,10 +88,15 @@ * Default validation options. Defaults can be overridden by | ||
validate.messages = { | ||
required: "", | ||
pattern: "", | ||
maximum: "", | ||
minimum: "", | ||
maxLength: "", | ||
minLength: "", | ||
dependencies: "", | ||
unique: "" | ||
required: "is required", | ||
minLength: "is too short (minimum is %{expected} characters)", | ||
maxLength: "is too long (maximum is %{expected} characters)", | ||
pattern: "invalid input", | ||
minimum: "must be greater than or equal to %{expected}", | ||
maximum: "must be less than or equal to %{expected}", | ||
exclusiveMinimum: "must be greater than %{expected}", | ||
exclusiveMaximum: "must be less than %{expected}", | ||
divisibleBy: "must be divisible by %{expected}", | ||
minItems: "must contain more than %{expected} items", | ||
maxItems: "must contain less than %{expected} items", | ||
uniqueItems: "must hold a unique set of values", | ||
format: "is not a valid %{expected}" | ||
}; | ||
@@ -102,7 +107,7 @@ | ||
*/ | ||
validate.formats = { | ||
validate.formats = { | ||
'email': /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, | ||
'ip-address': /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i, | ||
'ipv6': /^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/, | ||
'date-time': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, | ||
'ip-address': /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i, | ||
'ipv6': /^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/, | ||
'date-time': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d{1,3})?Z$/, | ||
'date': /^\d{4}-\d{2}-\d{2}$/, | ||
@@ -115,13 +120,13 @@ 'time': /^\d{2}:\d{2}:\d{2}$/, | ||
//'host-name': (not supported) | ||
'utc-millisec': { | ||
test: function (value) { | ||
return typeof(value) === 'number' && value >= 0; | ||
'utc-millisec': { | ||
test: function (value) { | ||
return typeof(value) === 'number' && value >= 0; | ||
} | ||
}, | ||
'regex': { | ||
test: function (value) { | ||
try { new RegExp(value) } | ||
catch (e) { return false } | ||
return true; | ||
}, | ||
'regex': { | ||
test: function (value) { | ||
try { new RegExp(value) } | ||
catch (e) { return false } | ||
return true; | ||
} | ||
@@ -134,6 +139,6 @@ } | ||
*/ | ||
validate.formatExtensions = { | ||
'url': /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i | ||
validate.formatExtensions = { | ||
'url': /^(https?|ftp|git):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i | ||
}; | ||
function mixin(obj) { | ||
@@ -144,7 +149,7 @@ var sources = Array.prototype.slice.call(arguments, 1); | ||
if (!source) { continue } | ||
if (typeof(source) !== 'object') { | ||
throw new TypeError('mixin non-object'); | ||
} | ||
for (var p in source) { | ||
@@ -156,3 +161,3 @@ if (source.hasOwnProperty(p)) { | ||
} | ||
return obj; | ||
@@ -216,9 +221,8 @@ }; | ||
if (options.formatExtensions) { spec = validate.formatExtensions[format] } | ||
if (options.validateFormatExtensions) { spec = validate.formatExtensions[format] } | ||
if (!spec) { spec = validate.formats[format] } | ||
if (!spec) { | ||
spec = validate.formats[format]; | ||
if (options.validateFormatsStrict) { | ||
return error('format', property, value, schema, errors); | ||
} | ||
} | ||
@@ -235,3 +239,3 @@ else { | ||
} | ||
// Dependencies (see 5.8) | ||
@@ -258,2 +262,4 @@ if (typeof schema.dependencies === 'string' && | ||
constrain('conform', value, function (a, e) { return e(a) }); | ||
switch (type || (isArray(value) ? 'array' : typeof value)) { | ||
@@ -275,3 +281,7 @@ case 'string': | ||
constrain('exclusiveMaximum', value, function (a, e) { return a < e }); | ||
constrain('divisibleBy', value, function (a, e) { return a % e === 0 }); | ||
constrain('divisibleBy', value, function (a, e) { | ||
var multiplier = Math.max((a - Math.floor(a)).toString().length - 2, (e - Math.floor(e)).toString().length - 2); | ||
multiplier = multiplier > 0 ? Math.pow(10, multiplier) : 1; | ||
return (a * multiplier) % (e * multiplier) === 0 | ||
}); | ||
break; | ||
@@ -337,3 +347,5 @@ case 'array': | ||
function error(attribute, property, actual, schema, errors) { | ||
var message = validate.messages && validate.messages[property] || "no default message"; | ||
var lookup = { expected: schema[attribute], attribute: attribute, property: property }; | ||
var message = schema.messages && schema.messages[attribute] || validate.messages[attribute] || "no default message"; | ||
message = message.replace(/%\{([a-z]+)\}/ig, function (_, match) { return lookup[match.toLowerCase()] || ''; }); | ||
errors.push({ | ||
@@ -340,0 +352,0 @@ attribute: attribute, |
{ | ||
"name": "revalidator", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "A cross-browser / node.js validator used by resourceful", | ||
@@ -13,6 +13,6 @@ "author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
"type": "git", | ||
"url": "http://github.com/flatiron/revalidator.git" | ||
"url": "http://github.com/flatiron/revalidator.git" | ||
}, | ||
"devDependencies": { | ||
"vows": "0.5.x >=0.5.11" | ||
"vows": "0.6.x" | ||
}, | ||
@@ -19,0 +19,0 @@ "main": "./lib/revalidator", |
@@ -1,2 +0,2 @@ | ||
# revalidator | ||
# revalidator [![Build Status](https://secure.travis-ci.org/flatiron/revalidator.png)](http://travis-ci.org/flatiron/revalidator) | ||
@@ -30,3 +30,3 @@ A cross-browser / node.js validator used by resourceful and flatiron. | ||
} | ||
}); | ||
})); | ||
``` | ||
@@ -69,2 +69,2 @@ | ||
[0]: http://vowsjs.org | ||
[1]: http://npmjs.org | ||
[1]: http://npmjs.org |
@@ -1,7 +0,2 @@ | ||
var path = require('path'), | ||
sys = require('sys'), | ||
assert = require('assert'), | ||
events = require('events'), | ||
http = require('http'), | ||
fs = require('fs'), | ||
var assert = require('assert'), | ||
vows = require('vows'), | ||
@@ -37,2 +32,11 @@ revalidator = require('../lib/revalidator'); | ||
function assertHasErrorMsg(attr, msg) { | ||
return function (res) { | ||
assert.notEqual(res.errors.length, 0); | ||
assert.ok(res.errors.some(function (e) { | ||
return e.attribute === attr && e.message === msg; | ||
})); | ||
}; | ||
} | ||
function assertValidates(passingValue, failingValue, attributes) { | ||
@@ -54,3 +58,3 @@ var schema = { | ||
var attr = Object.keys(attributes)[0]; | ||
revalidator.mixin(schema.properties.field, attributes); | ||
revalidator.mixin(schema.properties.field, attributes); | ||
@@ -81,20 +85,22 @@ var result = { | ||
"Validating": { | ||
"with <type>:'string'": assertValidates ('hello', 42, { type: "string" }), | ||
"with <type>:'number'": assertValidates (42, 'hello', { type: "number" }), | ||
"with <type>:'integer'": assertValidates (42, 42.5, { type: "integer" }), | ||
"with <type>:'array'": assertValidates ([4, 2], 'hi', { type: "array" }), | ||
"with <type>:'object'": assertValidates ({}, [], { type: "object" }), | ||
"with <type>:'boolean'": assertValidates (false, 42, { type: "boolean" }), | ||
"with <types>:bool,num": assertValidates (false, 'hello', { type: ["boolean", "number"] }), | ||
"with <types>:bool,num": assertValidates (544, null, { type: ["boolean", "number"] }), | ||
"with <type>:'null'": assertValidates (null, false, { type: "null" }), | ||
"with <type>:'any'": assertValidates (9, { type: "any" }), | ||
"with <pattern>": assertValidates ("kaboom", "42", { pattern: /^[a-z]+$/ }), | ||
"with <maxLength>": assertValidates ("boom", "kaboom", { maxLength: 4 }), | ||
"with <minLength>": assertValidates ("kaboom", "boom", { minLength: 6 }), | ||
"with <minimum>": assertValidates ( 512, 43, { minimum: 473 }), | ||
"with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }), | ||
"with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }), | ||
"with <divisibleBy>": assertValidates ( 10, 9, { divisibleBy: 5 }), | ||
"with <enum>": assertValidates ("orange", "cigar", { enum: ["orange", "apple", "pear"] }), | ||
"with <type>:'string'": assertValidates ('hello', 42, { type: "string" }), | ||
"with <type>:'number'": assertValidates (42, 'hello', { type: "number" }), | ||
"with <type>:'integer'": assertValidates (42, 42.5, { type: "integer" }), | ||
"with <type>:'array'": assertValidates ([4, 2], 'hi', { type: "array" }), | ||
"with <type>:'object'": assertValidates ({}, [], { type: "object" }), | ||
"with <type>:'boolean'": assertValidates (false, 42, { type: "boolean" }), | ||
"with <types>:bool,num": assertValidates (false, 'hello', { type: ["boolean", "number"] }), | ||
"with <types>:bool,num": assertValidates (544, null, { type: ["boolean", "number"] }), | ||
"with <type>:'null'": assertValidates (null, false, { type: "null" }), | ||
"with <type>:'any'": assertValidates (9, { type: "any" }), | ||
"with <pattern>": assertValidates ("kaboom", "42", { pattern: /^[a-z]+$/ }), | ||
"with <maxLength>": assertValidates ("boom", "kaboom", { maxLength: 4 }), | ||
"with <minLength>": assertValidates ("kaboom", "boom", { minLength: 6 }), | ||
"with <minimum>": assertValidates ( 512, 43, { minimum: 473 }), | ||
"with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }), | ||
"with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }), | ||
"with <divisibleBy>": assertValidates ( 10, 9, { divisibleBy: 5 }), | ||
"with <divisibleBy> decimal": assertValidates ( 0.2, 0.009, { divisibleBy: 0.01 }), | ||
"with <enum>": assertValidates ("orange", "cigar", { enum: ["orange", "apple", "pear"] }), | ||
"with <format>:'url'": assertValidates ('http://test.com/', 'hello', { format: 'url' }), | ||
"with <dependencies>": { | ||
@@ -183,3 +189,3 @@ topic: { | ||
}, | ||
date: { type: 'string', format: 'date' }, | ||
date: { type: 'string', format: 'date', messages: { format: "must be a valid %{expected} and nothing else" } }, | ||
body: { type: 'string' }, | ||
@@ -195,5 +201,16 @@ tags: { | ||
}, | ||
author: { type: 'string', pattern: /^[\w ]+$/i, required: true}, | ||
tuple: { | ||
type: 'array', | ||
minItems: 2, | ||
maxItems: 2, | ||
items: { | ||
type: ['string', 'number'] | ||
} | ||
}, | ||
author: { type: 'string', pattern: /^[\w ]+$/i, required: true, messages: { required: "is essential for survival" } }, | ||
published: { type: 'boolean', 'default': false }, | ||
category: { type: 'string' } | ||
category: { type: 'string' }, | ||
palindrome: {type: 'string', conform: function(val) { | ||
return val == val.split("").reverse().join(""); } | ||
} | ||
}, | ||
@@ -209,8 +226,10 @@ patternProperties: { | ||
title: 'Gimme some Gurus', | ||
date: new(Date)().toUTCString(), | ||
date: '2012-02-04', | ||
body: "And I will pwn your codex.", | ||
tags: ['energy drinks', 'code'], | ||
tuple: ['string0', 103], | ||
author: 'cloudhead', | ||
published: true, | ||
category: 'misc', | ||
palindrome: 'dennis sinned', | ||
_flag: true | ||
@@ -223,3 +242,3 @@ }, | ||
}, | ||
"return an object with the `valid` property set to true": assertValid, | ||
"return an object with the `valid` property set to true": assertValid, | ||
"return an object with the `errors` property as an empty array": function (res) { | ||
@@ -237,3 +256,4 @@ assert.isArray(res.errors); | ||
"return an object with `valid` set to false": assertInvalid, | ||
"and an error concerning the 'required' attribute": assertHasError('required') | ||
"and an error concerning the 'required' attribute": assertHasError('required'), | ||
"and the error message defined": assertHasErrorMsg('required', "is essential for survival") | ||
}, | ||
@@ -280,2 +300,19 @@ "and if it has a missing non-required property": { | ||
}, | ||
"and if it has a incorrect format (date)": { | ||
topic: function (object, schema) { | ||
object = clone(object); | ||
object.date = 'bad date'; | ||
return revalidator.validate(object, schema); | ||
}, | ||
"return an object with `valid` set to false": assertInvalid, | ||
"and the error message defined": assertHasErrorMsg('format', "must be a valid date and nothing else") | ||
}, | ||
"and if it is not a palindrome (conform function)": { | ||
topic: function (object, schema) { | ||
object = clone(object); | ||
object.palindrome = 'bad palindrome'; | ||
return revalidator.validate(object, schema); | ||
}, | ||
"return an object with `valid` set to false": assertInvalid | ||
}, | ||
"and if it didn't validate a pattern": { | ||
@@ -282,0 +319,0 @@ topic: function (object, schema) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
43290
8
818
69
2