schemasaurus.js
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.schemasaurus = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var CurrentObject = require('./int/context');
var Context = CurrentObject;
var Generator = require('./int/gen');
var Shared = require('./int/shared');
var SchemaPartProcessor = require('./int/processor');
var CodeComposer = require('./int/code');
var resolveRef = require('./int/references');
var createMatcher = require('./int/matchers');
function toFactory(Ctor) {
if (Object.keys(Ctor.prototype).length !== 0) {
return function () { return new Ctor(); };
}
return Ctor;
}
function SchemaPart(schema, varName, next) {
this.schema = schema;
this.varName = varName;
this.next = next;
}
function Compiler(userSchema, selectorCtor, options, path) {
if (!selectorCtor || typeof selectorCtor !== 'function') {
throw new Error("selectorCtor shall be a function");
}
this.schemaRoot = userSchema;
this.selectorCtor = toFactory(selectorCtor);
this.options = options || {};
this.options.ignoreAdditionalItems = this.options.ignoreAdditionalItems === undefined ? false : this.options.ignoreAdditionalItems;
this.ctx = new Context(path);
this.codeComposer = new CodeComposer();
this.shared = new Shared();
this.gen = new Generator("var");
this.processor = new SchemaPartProcessor(this.gen, this.codeComposer, this.options);
this.selector = this.selectorCtor();
this.prepareMatchers();
this.prepareContext();
}
Compiler.prototype = {
code: function () {
this.codeComposer.code.apply(this.codeComposer, arguments);
},
subCompile: function (s, path) {
return new Compiler(s, this.selectorCtor, this.options, path).compile();
},
prepareContext: function () {
this.ctx.compile = function (subschema, newFnName) {
var ins;
if (Array.isArray(subschema)) {
this.ctx[newFnName] = subschema.map(function (s) {
return this.subCompile(s);
}.bind(this));
} else {
this.ctx[newFnName] = this.subCompile(subschema, this.ctx.path.slice());
}
ins = this.shared.inner(this.ctx[newFnName]);
this.code("ctx.%% = %%", newFnName, ins);
}.bind(this);
},
prepareMatchers: function () {
var m, ma;
this.matchers = [];
//noinspection JSLint
for (m in this.selector) {
//noinspection JSUnfilteredForInLoop
ma = createMatcher(m);
if (ma) {
this.matchers.push(ma);
}
}
},
callback: function (schemaPart, attr) {
var i, self = this, clabel = this.gen.next(), matched = false;
this.code("%%: {", clabel);
function onMatch(name) {
matched = true;
self.addFn(name, schemaPart, clabel);
}
for (i = 0; i < this.matchers.length; i++) {
this.matchers[i](schemaPart.schema, attr, onMatch);
}
if (!matched) {
this.codeComposer.pop();
} else {
this.code("}");
}
},
addFn: function (name, schemaPart, stopLabel) {
var fn = this.selector[name];
this.code("//call %%", name);
if (fn.prepare) {
this.addFn2(fn.prepare(schemaPart.schema, this.ctx), schemaPart, null, stopLabel);
} else if (fn.length === 1 || fn.length === 2) {
this.addFn2(fn.call(this.selector, schemaPart.schema, this.ctx), schemaPart, null, stopLabel);
} else {
this.addFn2(fn, schemaPart, name, stopLabel);
}
},
addFn2: function (fn, schemaPart, directCallName, stopLabel) {
if (fn === undefined || fn === null) {
return;
}
if (typeof fn.inline === 'function' && this.options.noinline) {
this.code("this['%%'].inline.call(this, %%, ctx)", directCallName, schemaPart.varName);
} else if (fn.inline) {
this.codeComposer.inline(fn.inline, schemaPart.varName, stopLabel);
return; //to skip checking stop
} else if (directCallName) {
this.code("this['%%'](%%, %%, ctx)", directCallName, this.shared.schema(schemaPart.schema), schemaPart.varName);
} else {
this.code("%%.call(this, %%, %%, ctx)", this.shared.inner(fn), this.shared.schema(schemaPart.schema), schemaPart.varName);
}
if (!this.options.noreplace) {
this.code("if (ctx.wasReplaced()) %% = ctx.replacement()", schemaPart.varName);
}
this.code("if (ctx.isStopped()) break %%", stopLabel);
},
step: function (schema, varName, opts) {
if (schema.$$visited) {
//TODO: this is solution only for root recursion - to pass official suite :)
this.code("if (%% !== undefined) self(%%,ctx.path);", varName, varName);
return;
}
Object.defineProperty(schema, "$$visited", {value: true, enumerable: false, configurable: true});
if (schema.$ref) {
return this.step(resolveRef(this.options.loader, this.schemaRoot, schema.$ref), varName, opts);
}
this.stepProcess(new SchemaPart(schema, varName, function (cldSchema, cldVarName, sProp, prop, attr) {
this.ctx.push(sProp, schema, cldSchema);
this.code("ctx.push(%%, %%, %%)", prop || JSON.stringify(sProp), varName, cldVarName);
this.step(cldSchema, cldVarName, {attr: attr});
this.ctx.pop();
this.code("ctx.pop()");
}.bind(this)), opts);
delete schema.$$visited;
},
stepProcess: function (schemaPart, opts) {
var callback = this.callback.bind(this, schemaPart);
this.processAggregate(schemaPart.schema);
if (opts && opts.attr) {
callback(opts.attr);
}
callback("start");
callback();
this.processor.execute(schemaPart);
callback("end");
if (opts && opts.attr) {
callback(opts.attr + "-end");
}
},
processAggregate: function (schema) {
["oneOf", "anyOf", "allOf", "not"].forEach(function (inner) {
if (schema[inner]) {
this.ctx.compile(schema[inner], inner);
}
}.bind(this));
},
addEnd: function () {
var end = this.selector.end;
if (end) {
if (end.inline && (typeof end.inline === 'string' || !this.options.noinline)) {
this.codeComposer.inline(end.inline, "val", null, true);
} else {
this.codeComposer.code("return this.%%", end.inline ? "end.inline.call(this)" : "end()");
}
}
},
compile: function () {
var fnbody, fnout;
this.step(this.schemaRoot, "val");
this.addEnd();
fnbody = this.codeComposer.prettify().map(function (line) {
return "{};".indexOf(line[line.length - 1]) === -1 ? line + ";" : line;
}).join("\n");
fnbody = ["var self; selector._f = function(val, path) { var nil = undefined, schemaOnly = val === undefined"]
.concat(this.gen.generated).join(",") + ";\nctx.reset(path, val);" +
fnbody + "}; self = function (val, path) {" + (this.selector.begin ? "selector.begin();" : "") + " return selector._f(val, path) }; self.fn = selector._f; return self; ";
try {
fnout = new Function("selector", "schemas", "innerFns", "ctx", fnbody);
} catch (e) {
console.error(fnbody);
throw e;
}
return fnout(this.selector, this.shared.schemas, this.shared.innerFns, new CurrentObject());
}
};
function compile(userSchema, selectorCtor, options, path) {
return new Compiler(userSchema, selectorCtor, options, path).compile();
}
module.exports = compile;
},{"./int/code":2,"./int/context":3,"./int/gen":5,"./int/matchers":6,"./int/processor":7,"./int/references":8,"./int/shared":9}],2:[function(require,module,exports){
"use strict";
var Generator = require('./gen');
var interpolate = require('../interpolate');
function CodeComposer() {
this.codeLines = [];
this.labelgen = new Generator('clabel');
}
function prettifyCode(codeLines) {
var offset = "", step = " ", line, idx, openBrace, closeBrace;
for (idx = 0; idx < codeLines.length; idx = idx + 1) {
line = codeLines[idx].trim();
openBrace = line.indexOf("{") !== -1;
closeBrace = line.indexOf("}") !== -1;
if (closeBrace && !openBrace) {
offset = offset.substring(0, offset.length - step.length);
}
line = offset + line;
if (openBrace && !closeBrace) {
offset = offset + step;
}
codeLines[idx] = line;
}
return codeLines;
}
CodeComposer.prototype = {
pop: function () {
this.codeLines.pop();
},
code: function (template) {
this.codeLines.push(interpolate(template).apply(null, [].slice.call(arguments, 1)));
},
prettify: function () {
return prettifyCode(this.codeLines);
},
inline: function (fnInline, varName, stopLabel, allowReturn) {
var fnbody = fnInline.toString()
.replace(/^function\s*\([^)]*\)/, "")
.replace(/_/g, varName),
label = this.labelgen.next(),
needLabel = fnbody.indexOf('return') !== -1;
fnbody = fnbody.replace(/ctx\.stop\(\)/, "break " + stopLabel);
if (!allowReturn) {
fnbody = fnbody.replace(/return/g, "break " + label);
}
if (needLabel) {
this.code("%%:{%%}", label, fnbody);
} else {
this.code(fnbody);
}
}
};
module.exports = CodeComposer;
},{"../interpolate":10,"./gen":5}],3:[function(require,module,exports){
"use strict";
function CurrentObject(path) {
this.path = path ? path.slice() : [];
this.stack = new Array(100);
this.si = 0;
this.parent = null;
this.property = null;
this.self = null;
}
CurrentObject.prototype = {
reset: function (path, self) {
if (path) {
this.path = path.slice();
}
this.self = self;
},
replace: function (newVal) {
if (!this.parent) {
throw new Error("Cannot replace top-level object. Check in your iterator that `ctx.parent` is defined");
}
this.parent[this.property] = newVal;
this.replaced = true;
},
wasReplaced: function () {
var val = this.replaced;
this.replaced = false;
return val;
},
replacement: function () {
return this.parent[this.property];
},
remove: function () {
delete this.parent[this.property];
},
push: function (prop, parent, self) {
this.path.push(prop);
this.stack[this.si] = [prop, parent, self];
this.si = this.si + 1;
this.property = prop;
this.parent = parent;
this.self = self;
},
stop: function () {
this.stopped = true;
},
isStopped: function () {
if (this.stopped) {
this.stopped = false;
return true;
}
return false;
},
pop: function () {
this.si = this.si - 1;
this.path.pop();
var last = this.stack[this.si];
if (last) {
this.parent = last[0];
this.property = last[1];
this.self = last[2];
}
}
};
module.exports = CurrentObject;
},{}],4:[function(require,module,exports){
"use strict";
module.exports = function fillDefaultFormats(formats) {
formats.email = formats.email || {
regexp: /^[^@]+@[^@]+$/,
message: "shall be valid email"
};
formats["date-time"] = formats["date-time"] || {
regexp: /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(\.\d+)?([zZ]|[+\-]\d{2}:\d{2})$/,
message: "shall be valid date"
};
formats.ipv4 = formats.ipv4 || {
regexp: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
message: "shall be valid ipv4 address"
};
formats.ipv6 = formats.ipv6 || {
regexp: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
message: "shall be valid ipv6 address"
};
formats.uri = formats.uri || {
regexp: /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/,
message: "shall be valid URI"
};
formats.hostname = formats.hostname || {
regexp: /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/,
message: "shall be valid host name"
};
};
},{}],5:[function(require,module,exports){
"use strict";
function Generator(prefix) {
this.i = 0;
this.prefix = prefix;
this.generated = [];
}
Generator.prototype = {
next: function () {
this.i = this.i + 1;
var nv = this.prefix + this.i;
this.generated.push(nv);
return nv;
}
};
module.exports = Generator;
},{}],6:[function(require,module,exports){
"use strict";
var attrRe = /(\[(\^?[\-_\w]+)(=[\-_\w]+)?\])/g;
var modRe = /:([\-\w]+)$/;
function parseValue(valAsStr) {
if (valAsStr === null) {
return null;
}
var val = parseFloat(valAsStr);
if (!isNaN(val)) {
return val;
}
if (valAsStr === "true") {
return true;
}
if (valAsStr === "false") {
return false;
}
return valAsStr;
}
function matchEq(value1, value2) {
return value1 !== undefined && (value1 === value2 || value2 === undefined);
}
function matchNotEq(value1, value2) {
return value1 === undefined || (value1 !== value2 && value2 !== undefined);
}
function createMatcher(expr) {
var ma = modRe.exec(expr), props = [], attr, not, i;
if (ma) {
attr = ma[1];
}
ma = attrRe.exec(expr);
while (ma) {
not = ma[2][0] === '^';
props.push({
name: not ? ma[2].substring(1) : ma[2],
matcher: not ? matchNotEq : matchEq,
value: ma[3] ? parseValue(ma[3].substring(1)) : undefined
});
ma = attrRe.exec(expr);
}
return function (schema, att, cb) {
var sv, found = true;
if (att !== attr) {
return false;
}
for (i = 0; i < props.length; i = i + 1) {
sv = schema[props[i].name];
if (!props[i].matcher(sv, props[i].value)) {
found = false;
break;
}
}
if (found) {
return cb(expr);
}
};
}
module.exports = function (expr) {
if (expr.indexOf(":") !== -1 || expr.indexOf("[") !== -1) {
return createMatcher(expr);
}
};
},{}],7:[function(require,module,exports){
"use strict";
var Generator = require('./gen');
function SchemaPartProcessor(vargen, codeComposer, options) {
this.vargen = vargen;
this.labelgen = new Generator('label');
this.codeComposer = codeComposer;
this.options = options;
}
SchemaPartProcessor.prototype = {
processors: ['processItems', 'processProperties'],
execute: function (step) {
this.processors.forEach(function (p) {
this[p](step);
}.bind(this));
},
createVar: function () {
return this.vargen.next();
},
code: function () {
this.codeComposer.code.apply(this.codeComposer, arguments);
}
};
SchemaPartProcessor.prototype.processItems = function (step) {
if (!step.schema.items && !step.schema.additionalItems) {
return;
}
var idxvar, newvar, k;
if (!Array.isArray(step.schema.items)) {
idxvar = this.createVar();
this.codeComposer.code("for (%% = 0; %% < (%% ? %%.length : 0); %%++) {", idxvar, idxvar, step.varName, step.varName, idxvar);
newvar = this.createVar();
this.codeComposer.code("%% = %%[%%]", newvar, step.varName, idxvar);
step.next(step.schema.items, newvar, "[]", idxvar, "item");
this.code("}");
if (!this.options.ignoreSchemaOnly) {
this.code("if (schemaOnly) {");
step.next(step.schema.items, 'nil', "[]", undefined, "item");
this.code("}");
}
} else {
for (k = 0; k < step.schema.items.length; k = k + 1) {
newvar = this.createVar();
this.code("%% = %% ? %%[%%] : undefined", newvar, step.varName, step.varName, k);
step.next(step.schema.items[k], newvar, k);
}
if (!this.options.ignoreAdditionalItems) {
idxvar = this.createVar();
this.code("for (%% = %%; %% < (%% ? %%.length : 0); %%++) {", idxvar, step.schema.items.length, idxvar, step.varName, step.varName, idxvar);
newvar = this.createVar();
this.code("%% = %%[%%]", newvar, step.varName, idxvar);
this.processAdditional(step, "additionalItems", "additionalItem", idxvar, newvar);
this.code("}");
}
}
};
SchemaPartProcessor.prototype.processProperties = function (step) {
if (!step.schema.properties && !step.schema.additionalProperties && !step.schema.patternProperties) {
return;
}
var propsVar, newvar, k;
if (!this.options.ignoreAdditionalItems) {
propsVar = this.createVar();
this.code("%% = {}", propsVar);
}
for (k in step.schema.properties) {
if (step.schema.properties.hasOwnProperty(k)) {
newvar = this.createVar();
this.code("%% = %% ? %%.%% : undefined", newvar, step.varName, step.varName, k);
if (!this.options.ignoreAdditionalItems) {
this.code("%%.%% = true", propsVar, k);
}
step.next(step.schema.properties[k], newvar, k);
}
}
if (!this.options.ignoreAdditionalItems) {
this.processAdditionalProperties(step, propsVar);
}
};
SchemaPartProcessor.prototype.processAdditionalProperties = function (step, propsVar) {
var idxvar, newvar, k, patternProperties;
idxvar = this.createVar();
newvar = this.createVar();
this.code("if (typeof %% === 'object' && !Array.isArray(%%)) for (%% in %%) if (%%.hasOwnProperty(%%)) {",
step.varName, step.varName, idxvar, step.varName, step.varName, idxvar
);
this.code("%% = %%[%%]", newvar, step.varName, idxvar);
patternProperties = step.schema.patternProperties || {};
for (k in patternProperties) {
if (patternProperties.hasOwnProperty(k)) {
this.code("if (/%%/.test(%%)) {", k, idxvar);
step.next(step.schema.patternProperties[k], newvar, k, idxvar);
this.code("%%[%%] = true", propsVar, idxvar);
this.code("}");
}
}
this.code("if (!%%[%%]) {", propsVar, idxvar);
this.processAdditional(step, "additionalProperties", "additionalProperty", idxvar, newvar);
this.code("}");
this.code("}");
};
SchemaPartProcessor.prototype.processAdditional = function (step, schemaProp, cbProp, idxvar, newvar) {
var stubSchema = {};
stubSchema[cbProp] = false;
if (step.schema[schemaProp] === false) {
step.next(stubSchema, newvar, "*", idxvar);
} else if (typeof step.schema[schemaProp] === 'object') {
step.next(step.schema[schemaProp], newvar, "*", idxvar);
} else {
stubSchema[cbProp] = "allowed";
step.next(stubSchema, newvar, "*", idxvar);
}
};
module.exports = SchemaPartProcessor;
},{"./gen":5}],8:[function(require,module,exports){
"use strict";
function defaultLoader() {
throw new Error("Remote refs are not supported for now :(");
}
function detilde(s) {
return s.replace(/~0/g, "~").replace(/~1/g, "/"); //do not know how to parse it other way
}
function resolveRef(loader, schemaNode, ref) {
var remLoc = decodeURI(ref).split("#"), rem = remLoc[0], loc = remLoc[1].split("/").map(detilde), st = schemaNode, i;
if (rem !== '') {
st = (loader || defaultLoader)(rem);
}
for (i = 0; i < loc.length; i = i + 1) {
if (loc[i] === '') {
//noinspection JSLint
continue;
}
st = st[loc[i]];
if (st === undefined) {
throw new Error("Cannot find ref '" + ref + "' in schema");
}
}
return st;
}
module.exports = resolveRef;
},{}],9:[function(require,module,exports){
"use strict";
function Shared() {
this.innerFns = [];
this.schemas = [];
}
Shared.prototype = {
inner: function (fn) {
this.innerFns.push(fn);
return "innerFns[" + (this.innerFns.length - 1) + "]";
},
schema: function (s) {
this.schemas.push(s);
return "schemas[" + (this.schemas.length - 1) + "]";
}
};
module.exports = Shared;
},{}],10:[function(require,module,exports){
"use strict";
var compiled = {};
function interpolate(template) {
if (compiled[template]) {
return compiled[template];
}
var list = template.split("%%"),
code = "return " + ["list[0]", "a", "list[1]", "b", "list[2]", "c", "list[3]", "d", "list[4]", "e", "list[5]", "f", "list[6]", "g", "list[7]"].slice(0, list.length * 2 - 1).join("+"),
fn = (new Function("list", "return function(a,b,c,d,e,f,g){" + code + "};"))(list);
compiled[template] = fn;
return fn;
}
module.exports = interpolate;
},{}],11:[function(require,module,exports){
"use strict";
var compile = require('./compiler');
var Validator = require('./v4validator');
var Normalizer = require('./normalizer');
var extend = require('./validator_extend');
extend(Validator);
module.exports = {
Validator: Validator,
Normalizer: Normalizer,
compile: compile,
newIterator: compile,
newValidator: function (schema, voptions) {
voptions = voptions || {};
voptions.noreplace = true;
return compile(schema, Validator.factory(voptions), voptions);
},
newNormalizer: function (schema) {
return compile(schema, Normalizer.factory);
}
};
},{"./compiler":1,"./normalizer":13,"./v4validator":14,"./validator_extend":15}],12:[function(require,module,exports){
"use strict";
module.exports = function messages(gettext) {
return {
"string": gettext("shall be a string"),
"null": gettext("shall be null"),
"minLength": gettext("shall have length at least %d"),
"maxLength": gettext("shall have length no more than %d"),
"pattern": gettext("shall match pattern %s"),
"integer": gettext("shall be an integer"),
"multipleOf": gettext("shall be multiple of %d"),
"number": gettext("shall be a number"),
"minimum": gettext("shall be >= %d"),
"minimum.exclusive": gettext("shall be > %d"),
"maximum": gettext("shall be <= %d"),
"maximum.exclusive": gettext("shall be < %d"),
"boolean": gettext("shall be boolean"),
"object": gettext("shall be object"),
"additionalProperties": gettext("shall not have additional properties"),
"minProperties": gettext("shall have at least %d properties"),
"maxProperties": gettext("shall have no more than %d properties"),
"array": gettext("shall be array"),
"additionalItems": gettext("shall not have additional items"),
"minItems": gettext("shall have at least %d items"),
"maxItems": gettext("shall have no more %d items"),
"uniqueItems": gettext("shall have unique items"),
"enum": gettext("shall be one of values %s"),
"required": gettext("is required"),
"dependency": gettext("does not meet additional requirements for %s"),
"not": gettext("does not meet 'not' requirement"),
"oneOf": gettext("does not meet exactly one requirement"),
"oneOf.zero": gettext("does not meet any requirement"),
"allOf": gettext("does not meet all requirements"),
"anyOf": gettext("does not meet any requirement"),
"custom": gettext("is not valid")
};
};
},{}],13:[function(require,module,exports){
"use strict";
function Normalizer() {
}
function notDefined(o) {
return o === null || o === undefined;
}
Normalizer.prototype = {
"[default]": function (schema, object, ctx) {
if (notDefined(object)) {
ctx.replace(schema.default);
}
},
"[properties]": function (schema, object, ctx) {
if (ctx.parent && notDefined(object)) {
ctx.replace({});
}
},
"[additionalProperty]": function (schema, object, ctx) {
ctx.remove();
},
"[type]": function (schema, object, ctx) {
var isTrue, isFalse;
if (notDefined(object)) {
return;
}
switch (schema.type) {
case 'null':
ctx.replace(null);
break;
case 'string':
ctx.replace(object.toString());
break;
case 'integer':
ctx.replace(parseInt(object, 10));
break;
case 'number':
ctx.replace(parseFloat(object));
break;
case 'boolean':
isTrue = object === true || ['true', 'on'].indexOf(object.toString().toLowerCase()) !== -1;
isFalse = object === false || ['false', 'off'].indexOf(object.toString().toLowerCase()) !== -1;
ctx.replace(isTrue ? true : (isFalse ? false : !!object));
break;
case 'array':
if (!Array.isArray(object)) {
ctx.replace([object]);
}
break;
case 'object':
break;
}
},
end: {inline: "return _"}
};
Normalizer.factory = function () {
return new Normalizer();
};
module.exports = Normalizer;
},{}],14:[function(require,module,exports){
"use strict";
var messages = require('./messages');
var fillDefaultFormats = require('./int/default_formats');
function isObject(o) {
return typeof o === 'object' && !Array.isArray(o) && o !== null;
}
function nonUnicodeLength(str) {
return str.length;
}
function V4Validator(options) {
this.options = options || {};
if (!this.options.gettext) {
this.options.gettext = function (s) { return s; };
}
if (!this.options.messages) {
this.options.messages = messages(this.options.gettext);
}
this.options.custom = this.custom = this.options.custom || {};
this.options.formats = this.formats = this.options.formats || {};
this.options.strLength = this.strLength = this.options.strLength || nonUnicodeLength;
fillDefaultFormats(this.formats);
this.errors = [];
this.res = {
valid: true,
errors: this.errors
};
}
function throwUnknownMessage(code) {
throw new Error("There is no message registered for error '" + code + "'");
}
V4Validator.prototype = {
toComparable: function (o) {
return typeof o === 'object' ? JSON.stringify(o) : o;
},
error: function (code, ctx, arg, pathReplacement) {
var msg = (this.$cm && this.$cm[code]) ? this.options.gettext(this.$cm[code]) : this.options.messages[code] || arg;
if (!msg) {
return throwUnknownMessage(code);
}
this.errors.push({
code: code,
message: msg,
value: ctx.self,
arg: arg,
path: pathReplacement || ctx.path.slice()
});
},
copyErrors: function (anotherErrors) {
this.errors.splice.apply(this.errors, [this.errors.length, 0].concat(anotherErrors));
},
"[messages]": function (s) {
this.$messages = this.$messages || [];
this.$messages.push(s.messages);
return {inline: "this.$cm = this.$messages[" + (this.$messages.length - 1) + "]"};
},
"[messages]:end": {inline: "this.$cm = undefined;"},
////////////// type & common
processBoolRequired: function (s, ctx) {
if (!ctx.parent) {
return null;
}
return {inline: "if (_ === undefined) ctx.stop()"};
},
"[^required]": function (schema, ctx) {
return this.processBoolRequired(schema, ctx);
},
"[required=false]": function (schema, ctx) {
return this.processBoolRequired(schema, ctx);
},
"[required=true]": {inline: "if (_ === undefined) { this.error('required', ctx); ctx.stop(); }"},
"[type=string]": {inline: "if (typeof _ !== 'string') this.error('string', ctx)"},
"[type=number]": {inline: "if (typeof _ !== 'number') this.error('number', ctx)"},
"[type=integer]": {inline: "if ((typeof _ !== 'number') || (_ % 1 !== 0)) this.error('integer', ctx)"},
"[type=null]": {inline: "if (_ !== null) this.error('null', ctx);"},
"[type=boolean]": {inline: "if (typeof _ !== 'boolean') this.error('boolean', ctx)"},
"[type=array]": {inline: "if (!Array.isArray(_)) this.error('array', ctx)"},
"[type=object]": {inline: "if (Array.isArray(_) || typeof _ !== 'object' || _ === null) this.error('object', ctx);"},
"[type]": function (schema) {
if (Array.isArray(schema.type)) {
var fns = [], i;
for (i = 0; i < schema.type.length; i++) {
fns.push(this["[type=" + schema.type[i] + "]"].inline);
}
return {inline: ["{var oldlength = this.errors.length, iferr = this.errors.length + " + fns.length]
.concat(fns)
.concat(['if (this.errors.length !== iferr) this.errors.splice(oldlength, iferr);}'])
.join(";")
};
}
},
//////////////// dependencies
"[dependencies]": function (schema, ctx) {
var prop, icode = [], dep, fnName;
for (prop in schema.dependencies) {
if (schema.dependencies.hasOwnProperty(prop)) {
dep = schema.dependencies[prop];
if (Array.isArray(dep)) {
dep = {required: dep};
}
fnName = 'dep' + prop;
ctx.compile(dep, fnName);
icode.push("if (_.hasOwnProperty('" + prop + "')) {");
icode.push("var res = ctx." + fnName + "(_);");
icode.push("if (!res.valid) { this.error('dependency', ctx, " + JSON.stringify(schema.dependencies[prop]) + "); this.copyErrors(res.errors); }");
icode.push("}");
}
}
return {inline: icode.join("\n")};
},
//////////////// combining
"[allOf]": function (s, _, ctx) {
var i, res;
for (i = 0; i < ctx.allOf.length; i++) {
res = ctx.allOf[i](_, ctx.path);
if (!res.valid) {
this.error("allOf", ctx);
this.copyErrors(res.errors);
}
}
},
"[anyOf]": function (s, _, ctx) {
var allErrors = [], res, i;
for (i = 0; i < ctx.anyOf.length; i++) {
res = ctx.anyOf[i](_, ctx.path);
allErrors = allErrors.concat(res.errors);
if (res.valid) {
break;
}
}
if (!res.valid) {
this.error("anyOf", ctx);
this.copyErrors(allErrors);
}
},
"[oneOf]": function (s, _, ctx) {
var count = 0, allErrors = [], res, i;
for (i = 0; i < ctx.oneOf.length; i++) {
res = ctx.oneOf[i](_, ctx.path);
allErrors = allErrors.concat(res.errors);
if (res.valid) {
count++;
}
}
if (count === 0) {
this.error("oneOf.zero", ctx);
this.copyErrors(allErrors);
} else if (count !== 1) {
this.error("oneOf", ctx);
}
},
"[not]": function (s, _, ctx) {
var res = ctx.not(_, ctx.path);
if (res.valid) {
this.error("not", ctx);
}
},
///////////////// enum
"[enum]": function (schema) {
this.$enums = this.$enums || [];
var $enum = {}, i, e;
for (i = 0; i < schema.enum.length; i++) {
e = schema.enum[i];
$enum[this.toComparable(e)] = 1;
}
this.$enums.push($enum);
return {inline: "if(!this.$enums[" + (this.$enums.length - 1) + "][this.toComparable(_)]) this.error('enum', ctx, " + JSON.stringify(schema.enum) + ")"};
},
//////////////// string
"xLength": function (op, count, code) {
return {inline: "if (typeof _ === 'string' && this.strLength(_) " + op + count + ") this.error('" + code + "', ctx, " + count + ")"};
},
"[maxLength]": function (schema) {
return this.xLength(">", schema.maxLength, 'maxLength');
},
"[minLength]": function (schema) {
return this.xLength("<", schema.minLength, 'minLength');
},
"[pattern]": function (schema) {
return {inline: "if (typeof _ === 'string' && !_.match(/" + schema.pattern + "/)) this.error('pattern', ctx, " + JSON.stringify(schema.pattern) + ")"};
},
"[format]": function (schema) {
var fmt = this.formats[schema.format];
if (!fmt) {
throw new Error("Unknown format '" + schema.format + "'. Did you forget to register it?");
}
return {inline: "if (typeof _ === 'string' && !_.match(" + fmt.regexp + ")) this.error('format." + schema.format + "', ctx, " + JSON.stringify(fmt.message) + ")"};
},
////////////////// array
"[additionalItem=false]": {inline: "this.error('additionalItems', ctx);"},
"xItems": function (op, count, code) {
return {
inline: "if(Array.isArray(_) && _.length " + op + count + ") this.error('" + code + "', ctx)"
};
},
"[minItems]": function (schema) {
return this.xItems("<", schema.minItems, "minItems");
},
"[maxItems]": function (schema) {
return this.xItems(">", schema.maxItems, "maxItems");
},
"[uniqueItems]": function (s, _, ctx) {
if (!Array.isArray(_)) {
return;
}
var its = {}, i, o;
for (i = 0; i < _.length; i = i + 1) {
o = this.toComparable(_[i]);
if (its[o]) {
this.error("uniqueItems", ctx, _[i]);
}
its[o] = true;
}
},
processRequired: function (reqs) {
if (Array.isArray(reqs)) {
return function (s, o, ctx) {
if (!isObject(o)) {
return;
}
var i;
for (i = 0; i < reqs.length; i++) {
if (!o.hasOwnProperty(reqs[i])) {
this.error("required", ctx, null, ctx.path.slice().concat(reqs[i]));
}
}
};
}
},
///////////////// object
"[required][^properties]": function (schema) {
return this.processRequired(schema.required);
},
"[properties]": function (schema) {
return this.processRequired(schema.required);
},
"xProperties": function (op, count, code) {
return {inline: "if (typeof _ === 'object' && Object.keys(_).length " + op + " " + count + ") this.error('" + code + "', ctx, " + count + ")"};
},
"[maxProperties]": function (schema) {
return this.xProperties(">", schema.maxProperties, 'maxProperties');
},
"[minProperties]": function (schema) {
return this.xProperties("<", schema.minProperties, 'minProperties');
},
"[additionalProperty=false]": {inline: "this.error('additionalProperties', ctx)"},
///////////////// number
"[multipleOf]": function (schema) {
return {inline: "if (typeof _ === 'number' && (_ / " + schema.multipleOf + ") % 1 !== 0) this.error('multipleOf', ctx, " + schema.multipleOf + ")" };
},
"ximum": function (op, excl, count, code) {
return {inline: "if (_ " + op + (excl ? "=" : "") + count + ") this.error('" + code + (excl ? ".exclusive" : "") + "', ctx, " + count + ")"};
},
"[minimum]": function (schema) {
return this.ximum("<", schema.exclusiveMinimum, schema.minimum, 'minimum');
},
"[maximum]": function (schema) {
return this.ximum(">", schema.exclusiveMaximum, schema.maximum, 'maximum');
},
///////////////// custom
"[conform]": function (schema) {
this.$custom = this.$custom || [];
if (typeof schema.conform === 'function') {
this.$custom.push(schema.conform);
return {inline: "if (!this.$custom[" + (this.$custom.length - 1) + "](_, ctx)) this.error('custom', ctx)"};
}
var inlines = [];
var k, fn, args;
for (k in schema.conform) {
if (schema.conform.hasOwnProperty(k)) {
fn = this.custom[k];
args = schema.conform[k] === true ? "" : schema.conform[k].map(JSON.stringify).concat([""]).join(',');
this.$custom.push(fn);
inlines.push("if (!this.$custom[" + (this.$custom.length - 1) + "](_, " + args + " ctx)) this.error('custom." + k + "', ctx, this.options.messages.custom)");
}
}
return {inline: inlines.join('\n')};
},
///////////////// result
end: {inline: "this.res.valid = this.errors.length === 0; return this.res;"},
begin: function () {
this.errors = this.res.errors = [];
this.res.valid = true;
}
};
V4Validator.prototype.constructor = V4Validator;
V4Validator.factory = function (options) {
return function () {
return new V4Validator(options);
};
};
module.exports = V4Validator;
},{"./int/default_formats":4,"./messages":12}],15:[function(require,module,exports){
"use strict";
module.exports = function addExtender(ValidatorClass) {
ValidatorClass.extend = function (override, ctor) {
function NewValidator(options) {
ValidatorClass.call(this, options);
if (ctor) {
ctor.call(this, options);
}
}
NewValidator.prototype = new ValidatorClass();
NewValidator.prototype.constructor = NewValidator;
var k;
for (k in override) {
if (override.hasOwnProperty(k)) {
NewValidator.prototype[k] = override[k];
}
}
NewValidator.factory = function (options) {
return function () {
return new NewValidator(options);
};
};
return NewValidator;
};
};
},{}]},{},[11])(11)
});