This repository has been archived on 2020-11-15. You can view files and clone it, but cannot push or open issues or pull requests.
schemajs/lib/schema.js

121 lines
3.2 KiB
JavaScript

var _ = require('underscore');
var rules = require('./rules.js');
var Schema = function(schema) {
this.schema = schema;
};
var checkArray = function(schema, key, errors, values) {
var valid = true;
values.forEach(function(value, index) {
try {
if(schema.schema.schema) {
// if array has another schema, then we want objects!
value = rules.create(key, {type:'object'}).apply(value);
var results = (new Schema(schema.schema.schema)).validate(value);
if(!results.valid)
{
errors[key] = errors[key] || [];
errors[key][index] = results.errors;
} else {
values[index] = results.data;
}
}
else
values[index] = rules.create(key + "[" + index + "]", schema.schema).apply(value);
} catch (error) {
valid = false;
if (!_.isArray(errors[key])) errors[key] = [];
errors[key][index] = error;
}
});
return valid;
};
/*jshint loopfunc:true*/
Schema.prototype.validate = function(data, opts) {
var params = _.keys(this.schema);
var errors = {};
var values = {};
var value;
var get = typeof(data) == "function" ? data : function(p) {
return data[p];
};
for (var i = 0; i < params.length; i++) {
var schema = this.schema[params[i]];
try {
// if undefined, don't store it.
value = rules.create(params[i], schema).apply(get(params[i]));
// does this rule contain embedded schemas
if (typeof(schema.schema) == "object" &&
!_.isArray(schema.schema) &&
_.keys(schema.schema).length &&
!_.isUndefined(value)) {
if(schema.allownull && _.isNull(value)) {
values[params[i]] = null;
} else {
if (schema.type == "object") {
var results = (new Schema(schema.schema)).validate(value);
if(!results.valid) {
errors[params[i]] = results.errors;
} else {
values[params[i]] = results.data;
}
} else if (schema.type == "array") {
if( checkArray(schema, params[i], errors, value, get)){
values[params[i]] = value;
}
}
}
} else if (!_.isUndefined(value)) {
values[params[i]] = value;
}
} catch (error) {
errors[params[i]] = error;
}
}
if(opts && opts.strict) {
var origKeys = Object.keys(data);
var diff = origKeys.filter(function(i) {
return params.indexOf(i) < 0;
});
diff.forEach(function(field) {
errors[field] = "Additional key not defined in schema";
});
}
return {
data: values,
errors: errors,
valid: _.keys(errors).length === 0
};
};
exports.types = rules.types;
exports.test = function(value, schema) {
return (new Schema({
input: schema
})).validate({
input: value
});
};
exports.properties = rules.properties;
exports.filters = rules.filters;
exports.create = function(schema) {
return new Schema(schema);
};
exports.middleware = function(schema) {
return function(req, res, next) {
req.form = new Schema(schema).validate((req.method || req.route.method || '').toLowerCase() == "post" ? req.body : req.query);
next();
};
};