is-my-json-valid
Advanced tools
Comparing version 1.3.3 to 1.3.4
260
compile.js
@@ -0,3 +1,5 @@ | ||
var normalize = require('./normalize') | ||
var formats = require('./formats') | ||
var genobj = require('generate-object-property') | ||
var genfun = require('generate-function') | ||
var genobj = require('generate-object-property') | ||
@@ -22,2 +24,6 @@ var a = function(type) { | ||
types.any = function() { | ||
return 'true' | ||
} | ||
types.null = function() { | ||
@@ -58,9 +64,17 @@ return name+' === null' | ||
var validators = {} | ||
var toType = function(node) { | ||
return node.type | ||
} | ||
var compile = function(schema) { | ||
var scope = {unique:unique, errors:[]} | ||
schema = normalize(schema) | ||
var scope = {unique:unique, formats:formats} | ||
var syms = {} | ||
var gensym = function(name) { | ||
return name+(syms[name] = (syms[name] || 0)+1) | ||
} | ||
var vars = ['i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z'] | ||
var loopVar = function() { | ||
var genloop = function() { | ||
var v = vars.shift() | ||
@@ -72,179 +86,139 @@ vars.push(v+v[0]) | ||
var visit = function(name, node) { | ||
var type = node.type | ||
var enm = node.enum || (type && type.enum) | ||
var lvl = 1 | ||
var error = function(msg) { | ||
var err = { | ||
field: formatName(name), | ||
message: msg | ||
} | ||
return 'errors['+(scope.errors.push(err)-1)+']' | ||
var n = gensym('error') | ||
scope[n] = {field:formatName(name), message:msg} | ||
validate | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', n) | ||
} | ||
var isNullType = [].concat(type).some(function(t) { | ||
return (t.type || t) === 'null' | ||
}) | ||
if (node.required) { | ||
if (isNullType) validate('if (%s === undefined) {', name) | ||
if (node.nullable) validate('if (%s === undefined) {', name) | ||
else validate('if (%s === undefined || %s === null) {', name, name) | ||
validate | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('is required')) | ||
('} else {') | ||
error('is required') | ||
validate('} else {') | ||
} else { | ||
if (isNullType) validate('if (%s !== undefined) {', name) | ||
if (node.nullable) validate('if (%s !== undefined) {', name) | ||
else validate('if (%s !== undefined && %s !== null) {', name, name) | ||
} | ||
if (type) { | ||
var msg = [].concat(type) | ||
.map(function(t) { | ||
return t.type || t | ||
}) | ||
.map(a) | ||
.join(' or ') | ||
node.types.forEach(function(node, i) { | ||
var valid = types[node.type](name) | ||
var invalid = [].concat(type) | ||
.map(function(t) { | ||
return t.type || t | ||
}) | ||
.map(function(t) { | ||
return '!('+types[t](name)+')' | ||
}) | ||
.join(' && ') | ||
if (i) validate('} else if (%s) {', valid) | ||
else validate('if (%s) {', valid) | ||
if (!invalid) invalid = 'true' | ||
if (!node.conditions) validate('// do nothing - just type validate') | ||
lvl++ | ||
validate | ||
('if (%s) {', invalid) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must be '+msg)) | ||
('} else {') | ||
} | ||
if (node.values) { | ||
var toCompare = function(v) { | ||
return name+' !== '+JSON.stringify(v) | ||
} | ||
if (enm) { | ||
var invalid = enm | ||
.map(function(e) { | ||
return name+' !== '+JSON.stringify(e) | ||
}) | ||
.join(' && ') | ||
validate('if (%s) {', node.values.map(toCompare).join(' && ') || 'true') | ||
error('must be one of ['+enm.join(', ')+']') | ||
validate('}') | ||
return | ||
} | ||
if (!invalid) invalid = 'true' | ||
if (node.minimum) { | ||
validate('if (%s < %d) {', name, node.minimum) | ||
error('must be more than '+node.minimum) | ||
validate('}') | ||
} | ||
lvl++ | ||
validate | ||
('if (%s) {', invalid) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must be one of ['+enm.join(', ')+']')) | ||
('} else {') | ||
} | ||
if (node.maximum) { | ||
validate('if (%s > %d) {', name, node.maximum) | ||
error('must be less than '+node.maximum) | ||
validate('}') | ||
} | ||
if (node.minimum) { | ||
validate | ||
('if (%s < %d) {', name, node.minimum) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must be more than '+node.minimum)) | ||
('}') | ||
} | ||
if (node.format && formats[node.format]) { | ||
var n = gensym('format') | ||
scope[n] = formats[node.format] | ||
if (node.maximum) { | ||
validate | ||
('if (%s > %d) {', name, node.maximum) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must be less than '+node.maximum)) | ||
('}') | ||
} | ||
validate('if (!%s.test(%s)) {', n, name) | ||
error('must be '+node.format+' format') | ||
validate('}') | ||
} | ||
if (node.pattern) { | ||
var i = Object.keys(scope).length | ||
var p = new RegExp(node.pattern) | ||
scope['pattern'+i] = p | ||
if (node.pattern) { | ||
var n = gensym('pattern') | ||
scope[n] = new RegExp(node.pattern) | ||
validate | ||
('if (!pattern%d.test(%s)) {', i, name) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must match /'+node.pattern+'/')) | ||
('}') | ||
} | ||
validate('if (!%s.test(%s)) {', n, name) | ||
error('must match /'+node.pattern+'/') | ||
validate('}') | ||
} | ||
var items = node.items | ||
if (items && items[0]) items = items[0] // TODO: this is probably WRONG. investigate | ||
if (node.type === 'array') { | ||
if (node.minItems) { | ||
validate('if (%s.length < %d) {', name, node.minItems) | ||
error('must contain at least '+node.minItems+' item(s)') | ||
validate('}') | ||
} | ||
if (type === 'array') { | ||
if (node.minItems) { | ||
validate | ||
('if (%s.length < %d) {', name, node.minItems) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must contain at least '+node.minItems+' item(s)')) | ||
('}') | ||
if (node.maxItems) { | ||
validate('if (%s.length > %d) {', name, node.maxItems) | ||
error('must contain at most '+node.minItems+' item(s)') | ||
validate('}') | ||
} | ||
if (node.uniqueItems) { | ||
validate('if (!unique(%s)) {', name) | ||
error('must only contain unique values') | ||
validate('}') | ||
} | ||
var i = genloop() | ||
validate('for (var %s = 0; %s < %s.length; %s++) {', i, i, name, i) | ||
visit(name+'['+i+']', node.items) | ||
validate('}') | ||
} | ||
if (node.maxItems) { | ||
if (node.type === 'object' && node.additionalProperties === false) { | ||
var i = genloop() | ||
var keys = gensym('keys') | ||
var toCompare = function(p) { | ||
return keys+'['+i+'] !== '+JSON.stringify(p) | ||
} | ||
validate | ||
('if (%s.length > %d) {', name, node.maxItems) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must contain at most '+node.minItems+' item(s)')) | ||
('var %s = Object.keys(%s)', keys, name) | ||
('for (var %s = 0; %s < %s.length; %s++) {', i, i, keys, i) | ||
('if (%s) {', Object.keys(node.properties).map(toCompare).join(' && ') || 'true') | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push({"field":"%s."+%s[i], "message":"is not defined in the schema"})', formatName(name), keys) | ||
('}') | ||
('}') | ||
} | ||
if (node.uniqueItems) { | ||
validate | ||
('if (!unique(%s)) {', name) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push(%s)', error('must only contain unique values')) | ||
('}') | ||
if (node.type === 'object') { | ||
Object.keys(node.properties).forEach(function(n) { | ||
visit(genobj(name, n), node.properties[n]) | ||
}) | ||
} | ||
}) | ||
var i = loopVar() | ||
validate('for (var '+i+' = 0; '+i+' < %s.length; '+i+'++) {', name) | ||
visit(name+'['+i+']', items) | ||
if (node.types.length) { | ||
validate('} else {') | ||
error('must be '+node.types.map(toType).map(a).join(' or ')) | ||
validate('}') | ||
} | ||
if (node.additionalProperties === false && node.type === 'object') { | ||
var i = loopVar() | ||
var invalid = Object.keys(node.properties || {}) | ||
.map(function(p) { | ||
return 'keys['+i+'] !== '+JSON.stringify(p) | ||
}) | ||
.join(' && ') | ||
if (!invalid) invalid = 'true' | ||
validate('var keys = Object.keys(%s)', name) | ||
('for (var '+i+' = 0; '+i+' < keys.length; '+i+'++) {') | ||
('if (%s) {', invalid) | ||
('if (validate.errors === null) validate.errors = []') | ||
('validate.errors.push({"field":"%s."+keys[i], "message":"is not defined in the schema"})', formatName(name)) | ||
('}') | ||
('}') | ||
} | ||
if (node.properties) { | ||
Object.keys(node.properties).forEach(function(n) { | ||
var pname = genobj(name, n) | ||
var prop = node.properties[n] | ||
if (Array.isArray(node.required)) prop.required = node.required.indexOf(n) > -1 | ||
visit(pname, prop) | ||
}) | ||
} | ||
while (lvl--) validate('}') | ||
validate('}') | ||
} | ||
var validate = genfun() | ||
var validate = genfun | ||
('function validate(data) {') | ||
('validate.errors = null') | ||
schema.required = schema.required !== false | ||
visit('data', schema) | ||
validate() | ||
('return validate.errors === null') | ||
('}') | ||
validate | ||
('return validate.errors === null') | ||
('}') | ||
validate = validate.trim().toFunction(scope) | ||
validate = validate.toFunction(scope) | ||
@@ -251,0 +225,0 @@ validate.errors = null |
{ | ||
"name": "is-my-json-valid", | ||
"version": "1.3.3", | ||
"version": "1.3.4", | ||
"description": "A JSONSchema / orderly validator that uses code generation to be extremely fast", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
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
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
21477
14
460