UNPKG

realm-router

Version:

Realm router is a bleeding edge restful framework (ec7 + decorators), based on realm dependency injection.

169 lines (150 loc) 4.47 kB
"use realm backend"; import Collection, Decoration, Traceback, RequestInjectors from realm.router; import path2exp, Promise, logger, lodash as _ from realm.router.utils; let PRETTY_TRACE = false; /** * Router */ class Dispatcher extends Decoration { /** * constructor - description * * @param {type} req description * @param {type} res description * @param {type} next description * @return {type} description */ constructor(req, res, next) { super(); this.req = req; this.res = res; this.next = next; } /** * dispatch - dispatches a route * * @return {type} description */ dispatch() { var item = this.getCandidate(this.req.path); if (!item) { return this.next(); } return this.invoke(item); } /** * error - sends error directly to express * * @param {type} code description * @param {type} message description * @return {type} description */ error(code, message) { this.res.status(code).send({ error: code, message: message }); } /** * Invokes a handler */ invoke(item, opts) { opts = opts || {}; var self = this; var method = opts.method || self.req.method.toLowerCase(); var target = item.target[method || "$$notImplemented"]; if (!item.$$notImplemented) { item.$$notImplemented = () => { return this.error(501, "Not implemented"); } } self.services = { $req: self.req, $res: self.res, $params: opts.params || self._compactParams(item) } var localInjectors = RequestInjectors.getInjectors() _.each(localInjectors, function(fn, name) { self.services[name] = fn(self); }); return self.decorate(item.target, method) .then(function() { if (self.intercepted !== undefined) { return self.res.send(self.intercepted) } return realm.require(item.target[method], self.services) .then(function(response) { if (response !== undefined) { if (response.prototype) { // Dealing with chains var props = Object.getOwnPropertyNames(response.prototype); if (_.indexOf(props, 'constructor') === 0) { return realm.chain(response); } } return response; } }) }).then(function(response) { return response !== undefined ? self.res.send(response) : undefined; }).catch(function(e) { return Traceback.handle(e, self.res, PRETTY_TRACE); }); } /** * Gets suitable candidate */ getCandidate() { let routes = Collection.getMap(); let self = this; for (var item in routes) { var info = routes[item]; var handler = info.target; let keys = []; var re = path2exp(info.path, keys); var params = re.exec(self.req.path); if (params) { return { params: params, keys: keys, target: handler }; } } } /** * _compactParams - description * * @param {type} item description * @return {type} description */ _compactParams(item) { var params = {}; _.each(item.keys, function(i, index) { if (item.params[index + 1] !== undefined) { params[i.name] = item.params[index + 1]; } }); return params; } /** * static - init routes * Require all classes * @param {type} _package description * @return {type} description */ static initRoutes(_package, opts) { opts = opts || {}; PRETTY_TRACE = opts.prettyTrace; Dispatcher.usePrettyTrace = opts.prettyTrace; var packages = [].concat(_package); return realm.each(packages, function(pkg) { return realm.requirePackage(pkg).then(function(_packages) { logger.info("Package '%s' has been successfully required", pkg); logger.info("Injested %s routes", _.keys(_packages).length); // }).catch(function(e) { console.log(e.stack) }); }) } } export Dispatcher;