accurized
Version:
Verify the validity and accuracy of data as it enters your system.
222 lines (196 loc) • 6.45 kB
JavaScript
(function() {
var Errors, Field, Form, FormField, eachSeries, get, isFunction, 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;
isFunction = require('lodash').isFunction;
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) {
this.req = req1;
this.res = res1;
this.next = next1;
this.reporter = reporter;
this.redirect = redirect;
this.errors = new Errors();
this.fields = {};
this.custom = function(pass, fail) {
return pass();
};
}
Form.prototype.field = function(name, message, ctx) {
var base;
if (ctx == null) {
ctx = 'body';
}
return (base = this.fields)[name] != null ? base[name] : base[name] = new FormField(this.req[ctx], name, message);
};
Form.prototype.get = function(name) {
var ref;
return (ref = this.fields[name]) != null ? ref.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;
return eachSeries((function() {
var ref, results;
ref = this.fields;
results = [];
for (name in ref) {
field = ref[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, ref;
if (form.req.flash != null) {
ref = form.fields;
for (name in ref) {
field = ref[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);
configurator(form, req, res, next);
if (options.auto) {
return form.validate();
}
};
};
}).call(this);