UNPKG

accurized

Version:

Verify the validity and accuracy of data as it enters your system.

248 lines (222 loc) 7.43 kB
(function() { var Errors, Field, Form, FormField, compact, eachSeries, get, isFunction, isPlainObject, omit, ref, reporters, set, slice = [].slice, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; ref = require('lodash'), compact = ref.compact, isFunction = ref.isFunction, isPlainObject = ref.isPlainObject, omit = ref.omit; eachSeries = require('async').eachSeries; Errors = require('./errors'); Field = require('./field'); set = function() { var ctx, head, i, tail, val; ctx = arguments[0], head = arguments[1], tail = 4 <= arguments.length ? slice.call(arguments, 2, i = arguments.length - 1) : (i = 2, []), val = arguments[i++]; if (!tail.length) { return ctx[head] = val; } return set.apply(null, [(ctx[head] != null ? ctx[head] : ctx[head] = {})].concat(slice.call(tail), [val])); }; get = function() { var ctx, head, tail; ctx = arguments[0], head = arguments[1], tail = 3 <= arguments.length ? slice.call(arguments, 2) : []; if (ctx == null) { return void 0; } if (!tail.length) { return ctx[head]; } return get.apply(null, [ctx[head]].concat(slice.call(tail))); }; FormField = (function(superClass) { extend(FormField, superClass); function FormField(ctx1, name1, message, type) { this.ctx = ctx1; this.name = name1; this.type = type != null ? type : 'string'; this.hidden = false; FormField.__super__.constructor.call(this, message); } FormField.prototype.hide = function() { this.hidden = true; return this; }; FormField.prototype.value = function(val) { var path; path = this.name.split('.'); if (val != null) { return set.apply(null, [this.ctx].concat(slice.call(path), [val])); } return get.apply(null, [this.ctx].concat(slice.call(path))); }; FormField.prototype.as = function(type, custom) { this.type = type; if (custom) { this.custom = custom; } return this; }; FormField.prototype.validate = function(pass, fail) { return this.constructor.__super__.as.call(this, this.type, this.custom)(this.value(), pass, fail); }; return FormField; })(Field); Form = (function() { function Form(req1, res1, next1, reporter, redirect, whitelist) { this.req = req1; this.res = res1; this.next = next1; this.reporter = reporter; this.redirect = redirect; this.whitelist = whitelist; this.errors = new Errors(); this.fields = {}; this.paths = []; this.custom = function(pass, fail) { return pass(); }; } Form.prototype.field = function(name, message, ctx) { var base; if (ctx == null) { ctx = 'body'; } if (ctx === 'body') { this.paths.push(name); } return (base = this.fields)[name] != null ? base[name] : base[name] = new FormField(this.req[ctx], name, message); }; Form.prototype.get = function(name) { var ref1; return (ref1 = this.fields[name]) != null ? ref1.value() : void 0; }; Form.prototype.report = function(errors) { return this.reporter(errors.value, this); }; Form.prototype.then = function(custom) { var failed; if (custom.length === 1) { failed = false; return this.custom = function(pass, fail) { custom(function() { var args; args = 1 <= arguments.length ? slice.call(arguments, 0) : []; failed = true; return fail.apply(null, args); }); if (!failed) { return pass(); } }; } else { return this.custom = custom; } }; Form.prototype.validate = function() { var field, name, visit; visit = (function(_this) { return function(extra, path) { var name, results, value; if (path == null) { path = void 0; } if (isPlainObject(extra)) { results = []; for (name in extra) { value = extra[name]; results.push(visit(value, compact([path, name]).join('.'))); } return results; } else { return _this.errors.add(path, "The '" + path + "' field is not allowed."); } }; })(this); if (this.whitelist) { visit(omit.apply(null, [this.req.body].concat(slice.call(this.paths)))); } return eachSeries((function() { var ref1, results; ref1 = this.fields; results = []; for (name in ref1) { field = ref1[name]; results.push([name, field]); } return results; }).call(this), (function(_this) { return function(arg, callback) { var field, name; name = arg[0], field = arg[1]; return field.validate(function(value) { field.value(value); return callback(); }, function(error, ns) { _this.errors.add(ns != null ? ns : name, error); return callback(); }); }; })(this), (function(_this) { return function() { if (!_this.errors.empty) { return _this.report(_this.errors); } return _this.custom(function() { return _this.next(); }, function(error, ns) { _this.errors.add(ns != null ? ns : 'global', error); return _this.report(_this.errors); }); }; })(this)); }; return Form; })(); reporters = { json: function(errors, form) { var field, info, name; for (name in errors) { info = errors[name]; field = form.field(name); if (!field.hidden) { info.value = field.value(); } } return form.res.status(422).json(errors); }, form: function(errors, form) { var field, info, name, ref1; if (form.req.flash != null) { ref1 = form.fields; for (name in ref1) { field = ref1[name]; if (!field.hidden) { form.req.flash(field.name + "_value", field.value()); } } for (name in errors) { info = errors[name]; form.req.flash((name === 'global' ? 'error' : name + "_error"), info.errors[0]); } } else { console.warn('The connect-flash middleware must preceed the validator middleware when this reporter is used.'); } if (form.redirect != null) { return form.res.redirect_to(form.redirect); } else { return form.res.redirect('back'); } } }; module.exports = function(options, configurator) { if (!isFunction(options.report)) { options.report = reporters[options.report]; } return function(req, res, next) { var form; form = new Form(req, res, next, options.report, options.redirect, options.whitelist); configurator(form, req, res, next); if (options.auto) { return form.validate(); } }; }; }).call(this);