diff options
Diffstat (limited to 'app/node_modules/okview')
| -rw-r--r-- | app/node_modules/okview/index.js | 148 |
1 files changed, 67 insertions, 81 deletions
diff --git a/app/node_modules/okview/index.js b/app/node_modules/okview/index.js index 6eebe6e..5f99d59 100644 --- a/app/node_modules/okview/index.js +++ b/app/node_modules/okview/index.js @@ -21,11 +21,14 @@ function OKView(options) { if (!options.template) throw new Error('No template provided to OKView.'); if (!options.meta) - throw new Error('No meta resource provided to OKView'); + throw new Error('No metadata provided to OKView'); if (!options.route) throw new Error('No route provided to OKView'); + if (!options.errorHandler) + throw new Error('No error handler provided to OKView'); var route = options.route; var mount = options.mount || 'get'; + var error = this._error = options.errorHandler; this._template = options.template; var meta = this._meta = options.meta; var queries = this._queries = options.queries || []; @@ -47,16 +50,9 @@ function OKView(options) { enumerable: true }); - this._middleware = createMiddleware(this); - this._fetchTemplateData = unbound ? fetchUnbound : fetchBound; - - function fetchUnbound(id) { - return fetchTemplateData(meta, queries, id) - } - - function fetchBound() { - return fetchTemplateData(meta, queries); - } + this._middleware = unbound + ? unboundMiddleware(this, meta, queries, error) + : boundMiddleware(this, meta, queries, error); } OKView.prototype.middleware = function() { @@ -66,39 +62,20 @@ OKView.prototype.middleware = function() { OKView.prototype.render = function(req, res, data) { this._template.render(data).then(function(html) { res.send(html); - }).fail(errorHandler(req, res, data)); -}; - -OKView.prototype.fetchTemplateData = function() { - return this._fetchTemplateData.apply(this, arguments); + }).fail(this._error(req, res, 500)); }; /** - * Unbound views need different middleware to resolve requests - */ -function createMiddleware(view) { - if (view.unbound) { - return unboundMiddleware(view); - } else { - return boundMiddleware(view); - } -} - -// Note that these middleware do not call next -// and should thus always be added at the end of the -// middleware chain. - -/** * Creates middleware for a view which does not * yet have a resource id associated with it */ -function unboundMiddleware(view) { +function unboundMiddleware(view, meta, queries, error) { var paramName = getParamName(view.route); return function(req, res, next) { var id = req.params[paramName]; - view.fetchTemplateData(id).then(function(data) { + fetchTemplateData(meta, queries, id).then(function(data) { view.render(req, res, data); - }).fail(errorHandler(req, res, next)); + }).fail(failHandler(req, res, error)); }; } @@ -106,20 +83,22 @@ function unboundMiddleware(view) { * Creates middleware for a view which already * has a resource id associated with it */ -function boundMiddleware(view) { +function boundMiddleware(view, meta, queries, error) { return function(req, res, next) { - view.fetchTemplateData().then(function(data) { + fetchTemplateData(meta, queries).then(function(data) { view.render(req, res, data); - }).fail(errorHandler(req, res, next)); + }).fail(failHandler(req, res, error)); }; } -/** - * TODO BS error handling for now - */ -function errorHandler(req, res, next) { - return function(err) { - res.send(err.stack); +function failHandler(req, res, error) { + return function (err) { + // TODO Use custom exception type + if (err.message === 'No resource found') { + error(req, res, 404)(err); + } else { + error(req, res, 500)(err); + } } } @@ -138,49 +117,56 @@ function getParamName(route) { * and returns a promise for an object merging all queried * data, pluralizing keys where necessary. * - * Lil bit convoluted, sorry. + * Pretty convoluted, sorry. */ function fetchTemplateData(meta, queries, id) { + // If there's only one query, we assume it is for a single + // resource and will resolve errors if no data is found + var single = queries && queries.length === 1; return Q.promise(function(resolve, reject) { - return Q.all( - [meta.get()].concat(queries.map(function(query) { - return query.get(id); - }))) - .then(function(results) { - var metadata = results.shift(); - var normalized = results.reduce(function(cache, result, i) { - // Could be just some rogue request - if (!result) { - return cache; - } - var resource = queries[i].resource; - var type = queries[i].type; - var manyResult = isarray(result); - // Inform template of ID in generic field - if (manyResult) { - result = result.map(function(data) { - return assign({}, data, {id: data[resource.idField]}) - }); - } else { - result = assign({}, result, {id: result[resource.idField]}); - } - // If we have a lot of results for a certain type, - // we pluralize the key and yield an array of results - if (cache[type] || manyResult) { - var plural = pluralize(type); - delete cache[type]; - cache[plural] = []; - if (manyResult) { - cache[plural] = cache[plural].concat(result); + return Q.all(queries.map(function(query) { + return query.get(id); + })).then(function(results) { + if (single && !results[0]) { + reject(new Error('No resource found')); + } else { + var normalized = results.reduce(function(cache, result, i) { + // Could be just some rogue request + if (!result) { + return cache; + } + var query = queries[i] + var resource = query.resource; + var type = query.as || query.type; + var manyResult = isarray(result); + var groupBy = query.groupBy + // If we have a lot of results for a certain type, + // we pluralize the key and yield an array of results + if (cache[type] || manyResult || groupBy) { + var plural = pluralize(type); + delete cache[type]; + cache[plural] = []; + // Pluralize grouped field + if (query.groupBy) { + result = Object.keys(result).reduce(function(acc, key) { + acc[pluralize(key)] = result[key] + return acc + }, {}) + } + if (manyResult) { + cache[plural] = cache[plural].concat(result); + } else if (groupBy) { + cache[plural] = result + } else { + cache[plural].push(result); + } } else { - cache[plural].push(result); + cache[type] = result; } - } else { - cache[type] = result; - } - return cache; - }, {meta: metadata}); - resolve(normalized); + return cache; + }, {meta: meta}); + resolve(normalized); + } }).fail(reject); }); } |
