summaryrefslogtreecommitdiff
path: root/app/node_modules/okview/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/node_modules/okview/index.js')
-rw-r--r--app/node_modules/okview/index.js148
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);
});
}