var QueryCallbacks = function (options) { if (utils.isString(options)) { options = { then: options }; } else { options = options || {}; } this.callbacks = {}; if (options.err) this.callbacks.err = options.err; if (options.none) this.callbacks.none = options.none; if (options.then) this.callbacks.then = options.then; return this; };
exports.set = function(key, value) { if (arguments.length === 1) { return this._options[key]; } switch (key) { // handle special settings case 'cloudinary config': if (_.isString(value)) { var parts = url.parse(value, true); var auth = parts.auth ? parts.auth.split(':') : []; value = { cloud_name: parts.host, api_key: auth[0], api_secret: auth[1], private_cdn: parts.pathname != null, secure_distribution: parts.pathname && parts.pathname.substring(1) }; } if (_.isObject(value)) { cloudinary.config(value); } value = cloudinary.config(); break; case 'auth': if (value === true && !this.get('session')) { debug('setting session for auth'); this.set('session', true); } break; case 'nav': debug('setting nav'); this.nav = this.initNav(value); break; case 'mongo': if ('string' !== typeof value) { if (Array.isArray(value) && (value.length === 2 || value.length === 3)) { console.log('\nWarning: using an array for the `mongo` option has been deprecated.\nPlease use a mongodb connection string, e.g. mongodb://localhost/db_name instead.\n\n' + 'Support for arrays as the `mongo` setting will be removed in a future version.'); value = (value.length === 2) ? 'mongodb://' + value[0] + '/' + value[1] : 'mongodb://' + value[0] + ':' + value[2] + '/' + value[1]; } else { console.error('\nInvalid Configuration:\nThe `mongo` option must be a mongodb connection string, e.g. mongodb://localhost/db_name\n'); process.exit(1); } } break; case 'module root': // if relative path is used, resolve it based on the caller's path if (!isAbsolutePath(value)) { var caller = callerId.getData(); value = path.resolve(path.dirname(caller.filePath), value); } break; case 'app': this.app = value; break; case 'mongoose': this.mongoose = value; break; case 'frame guard': var validFrameGuardOptions = ['deny', 'sameorigin']; if (value === true) { value = 'deny'; } if (utils.isString(value)) { value = value.toLowerCase(); if (validFrameGuardOptions.indexOf(value) < 0) { value = false; } } else if ('boolean' !== typeof value) { value = false; } break; } this._options[key] = value; return this; };
View.prototype.on = function (on) { var req = this.req; var callback = arguments[1]; if (typeof on === 'function') { /* If the first argument is a function that returns truthy then add the second * argument to the action queue * * Example: * * view.on(function() { * var thing = true; * return thing; * }, * function(next) { * console.log('thing is true!'); * next(); * } * ); */ if (on()) { this.actionQueue.push(callback); } } else if (utils.isObject(on)) { /* Do certain actions depending on information in the response object. * * Example: * * view.on({ 'user.name.first': 'Admin' }, function(next) { * console.log('Hello Admin!'); * next(); * }); */ var check = function (value, path) { var ctx = req; var parts = path.split('.'); for (var i = 0; i < parts.length - 1; i++) { if (!ctx[parts[i]]) { return false; } ctx = ctx[parts[i]]; } path = _.last(parts); return (value === true && path in ctx) ? true : (ctx[path] === value); }; if (_.every(on, check)) { this.actionQueue.push(callback); } } else if (on === 'get' || on === 'post' || on === 'put' || on === 'delete') { /* Handle HTTP verbs * * Example: * view.on('get', function(next) { * console.log('GOT!'); * next(); * }); */ if (req.method !== on.toUpperCase()) { return this; } if (arguments.length === 3) { /* on a POST and PUT requests search the req.body for a matching value * on every other request search the query. * * Example: * view.on('post', { action: 'theAction' }, function(next) { * // respond to the action * next(); * }); * * Example: * view.on('get', { page: 2 }, function(next) { * // do something specifically on ?page=2 * next(); * }); */ callback = arguments[2]; var values = {}; if (utils.isString(arguments[1])) { values[arguments[1]] = true; } else { values = arguments[1]; } var ctx = (on === 'post' || on === 'put') ? req.body : req.query; if (!_.every(values || {}, function (value, path) { return (value === true && path in ctx) ? true : (ctx[path] === value); })) { return this; } } this.actionQueue.push(callback); } else if (on === 'init') { /* Init events are always fired in series, before any other actions * * Example: * view.on('init', function (next) { * // do something before any actions or queries have run * }); */ this.initQueue.push(callback); } else if (on === 'render') { /* Render events are always fired last in parallel, after any other actions * * Example: * view.on('render', function (next) { * // do something after init, action and query middleware has run * }); */ this.renderQueue.push(callback); } // TODO: Should throw if we didn't recognise the first argument! return this; };
View.prototype.on = function(on) { var req = this.req, callback = arguments[1], values; if ('function' == typeof on) { if (on()) { this.actionQueue.push(callback); } } else if (utils.isObject(on)) { var check = function(value, path) { var ctx = req, parts = path.split('.'); for (var i = 0; i < parts.length - 1; i++) { if (!ctx[parts[i]]) { return false; } ctx = ctx[parts[i]]; } return (value === true && path in ctx) ? true : (ctx[path] == value); } if (_.every(on, check)) { this.actionQueue.push(callback); } } else if (on == 'post' || on == 'get') { if (req.method != on.toUpperCase()) { return; } if (arguments.length == 3) { if (utils.isString(callback)) { values = {}; values[callback] = true; } else { values = callback; } callback = arguments[2]; var ctx = (on == 'post') ? req.body : req.query; if (_.every(values || {}, function(value, path) { return (value === true && path in ctx) ? true : (ctx[path] == value); })) { this.actionQueue.push(callback); } } else { this.actionQueue.push(callback); } } else if (on == 'init') { this.initQueue.push(callback); } else if (on == 'render') { this.renderQueue.push(callback); } return this; }