UNPKG

@unclepaul/allcountjs

Version:

The open source framework for rapid business application development with Node.js

146 lines (126 loc) 4.91 kB
var util = require('util'); var _ = require('underscore'); var Q = require('q'); module.exports = function (injection, ValidationError) { function CompileError () { this.message = util.format.apply(util.format, arguments); this.name = "CompileError"; Error.captureStackTrace(this, arguments.callee); } util.inherits(CompileError, Error); function ForbiddenError (message) { this.message = message; Error.captureStackTrace(this, arguments.callee); } util.inherits(ForbiddenError, Error); function ConflictError (message) { this.message = message; Error.captureStackTrace(this, arguments.callee); } util.inherits(ConflictError, Error); function ConfigObject(obj) { this.obj = obj; } function evaluateNext(next) { if (_.isArray(next)) { return next.map(evaluateNext); } else if (next && next.obj) { var result = {}; for (var prop in next.obj) { if (next.obj.hasOwnProperty(prop)) { result[prop] = evaluateNext(next.propertyValue(prop)); } } return result; } else { return next; } } ConfigObject.prototype = { propertyValue: function (name) { return appUtil.evaluateObject(this.obj[name], this.obj.__proto__, name); }, hasPropertyValue: function (name) { return !!this.obj[name]; }, hasOwnPropertyValue: function (name) { return this.obj.hasOwnProperty(name); }, propertyValues: function () { var self = this; var results = {}; _.forEach(this.obj, function (prop, name) { results[name] = self.propertyValue(name); }); return results; }, evaluateProperties: function () { return evaluateNext(this); }, withParent: function (configObject) { function ViewConfigConstructor() {} ViewConfigConstructor.prototype = configObject.obj; var objWithParent = new ViewConfigConstructor(); return new ConfigObject(_.extend(objWithParent, this.obj)); }, arrayPropertyValue: function (name) { return this.assertPropertyValue(name, _.isArray, 'Property value "%s" expected to be an array'); }, stringPropertyValue: function (name) { return this.assertPropertyValue(name, _.isString, 'Property value "%s" expected to be a string'); }, evaluatedValue: function (name) { return evaluateNext(this.propertyValue(name)); }, assertPropertyValue: function (name, assertFun, errorMsg) { var propertyValue = this.propertyValue(name); if (!propertyValue) { return propertyValue; } if (!assertFun(propertyValue)) { throw new appUtil.CompileError(errorMsg, name); } return propertyValue; }, invokePropertiesOn: function (invokeOn) { var self = this; _.forEach(invokeOn, function (method, name) { self.hasPropertyValue(name) && invokeOn[name](self.propertyValue(name)); }); } }; var appUtil = { CompileError: CompileError, ValidationError: ValidationError, ConfigObject: ConfigObject, ForbiddenError: ForbiddenError, ConflictError: ConflictError, evaluateObject: function (object, parent, name) { var self = this; var result; if (_.isFunction(object)) { result = self.evaluateObject(injection.resolveFuncArgs(object, function (dependency) { if (dependency === '$parentProperty') { return parent && name && self.evaluateObject(parent[name], parent.__proto__, name).obj; } else { return injection.lookup(dependency); } })); } else if (_.isArray(object)) { result = object.map(function (i) { return self.evaluateObject(i) }); } else if (_.isDate(object)) { return object; } else if (Q.isPromise(object) || object && object.then) { result = Q(object); //TODO .then(evaluateObject) ? } else if (_.isObject(object)) { result = new self.ConfigObject(object); } else { result = object; } return result; } }; return appUtil; };