UNPKG

fusion-plugin-http-router

Version:

Registers http routes and handlers on the server.

321 lines (266 loc) 12.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var fusionCore = require('fusion-core'); var pathToRegexp = require('path-to-regexp'); var bodyParser = _interopDefault(require('koa-body')); var browserPlugin = null; var HttpRouterToken = fusionCore.createToken('HttpRouter'); var HttpHandlersToken = fusionCore.createToken('HttpHandlersToken'); var BodyParserOptionsToken = fusionCore.createToken('BodyParserOptionsToken'); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function matchUri(url, patternedPath) { var path = patternedPath.path, keys = patternedPath.keys, pattern = patternedPath.pattern; var match = pattern.exec(url); if (!match) { return { isExact: false, params: {}, path: path }; } var values = match.slice(1); var params = keys.reduce(function (final, name, index) { var _objectSpread2; return _objectSpread({}, final, (_objectSpread2 = {}, _objectSpread2[name] = values[index], _objectSpread2)); }, {}); return { isExact: true, params: params, path: path }; } function matchPath(url, paths) { if (!(paths instanceof Array)) { return matchUri(url, paths); } return paths.reduce(function (final, path) { var match = matchUri(url, path); if (match.isExact && !final.isExact) { return match; } return final; }, { isExact: false, params: {}, path: '' }); } function getPatternedPaths(paths) { return paths.map(function (path) { var keys = []; var pattern = pathToRegexp.pathToRegexp(path, keys); return { path: path, pattern: pattern, keys: keys.map(function (_ref) { var name = _ref.name; return name; }) }; }); } function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$1(Object(source), true).forEach(function (key) { _defineProperty$1(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty$1(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var methods = new Set(['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE']); function dive(currentKey, into, target) { Object.keys(into).forEach(function (key) { if (methods.has(key.toUpperCase())) { target[currentKey] = Object.keys(into).reduce(function (final, key) { if (methods.has(key.toUpperCase())) { var _objectSpread2; return _objectSpread$1({}, final, (_objectSpread2 = {}, _objectSpread2[key.toUpperCase()] = into[key], _objectSpread2)); } return final; }, _objectSpread$1({}, target[currentKey])); } else { var newKey = key; var newVal = into[key]; if (currentKey.length > 0) { newKey = currentKey + key; } if (newVal instanceof Object) { dive(newKey, newVal, target); } else { target[newKey] = newVal; } } }); } function flattenHandlers(handlers) { var flatHandlers = {}; dive('', handlers, flatHandlers); return flatHandlers; } function getHandler(ctx, paths, handlers) { var match = matchPath(ctx.path, paths); var handler = handlers[match.path] && handlers[match.path][ctx.method]; return match.isExact ? { handler: handler, match: match } : { match: {} }; } function findInvalidPath(handlers) { function findInvalidMethod(path) { return Object.keys(handlers[path]).find(function (method) { return typeof handlers[path][method] !== 'function'; }); } var paths = Object.keys(handlers); var invalidPath = paths.find(function (path) { if (handlers[path] instanceof Object) { return findInvalidMethod(path); } return true; }); if (invalidPath) { var invalidMethod = findInvalidMethod(invalidPath); return invalidMethod ? "method \"" + invalidMethod + "\" of path \"" + invalidPath + "\"" : "path \"" + invalidPath + "\""; } return ''; } function ownKeys$2(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread$2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$2(Object(source), true).forEach(function (key) { _defineProperty$2(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$2(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty$2(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } /* eslint-env node */ function comparator(a, b) { var aLength = a.split(':').length; var bLength = b.split(':').length; return aLength < bLength ? -1 : 1; } var plugin = fusionCore.createPlugin({ deps: { bodyParserOptions: BodyParserOptionsToken.optional, handlers: HttpHandlersToken }, provides: function provides(deps) { var handlers = deps.handlers, _deps$bodyParserOptio = deps.bodyParserOptions, bodyParserOptions = _deps$bodyParserOptio === void 0 ? {} : _deps$bodyParserOptio; if (!handlers || _typeof(handlers) !== 'object') { throw new Error('Missing/incorrect handlers registered to HttpHandlersToken'); } var flatHandlers = flattenHandlers(handlers); var paths = Object.keys(flatHandlers).sort(comparator); // eslint-disable-next-line no-console console.log('\x1b[36m\x1b[1m', 'Registered Paths:\x1b[0m'); paths.forEach(function (path, index) { var methods = Object.keys(flatHandlers[path]).join(', '); // eslint-disable-next-line no-console console.log('\x1b[36m', index + 1 + ". " + path + " -> { " + methods + " }", '\x1b[0m'); }); var invalidPath = findInvalidPath(flatHandlers); if (invalidPath) { throw new Error("Missing/incorrect handler registered against " + invalidPath + "."); } var parseBody = bodyParser(_objectSpread$2({}, bodyParserOptions, { multipart: true })); var patternedPaths = getPatternedPaths(paths); var from = fusionCore.memoize(function (ctx) { return new Promise(function ($return, $error) { var query, _getHandler, _handler, match, _ctx$request, body, _ctx$request$files, files; query = ctx.query; _getHandler = getHandler(ctx, patternedPaths, flatHandlers), _handler = _getHandler.handler, match = _getHandler.match; if (typeof _handler !== 'function') { return $return({ handler: null, match: match }); } return Promise.resolve(parseBody(ctx, function () { return Promise.resolve(); })).then(function ($await_3) { try { _ctx$request = ctx.request, body = _ctx$request.body, _ctx$request$files = _ctx$request.files, files = _ctx$request$files === void 0 ? {} : _ctx$request$files; return $return({ handler: function handler() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _handler.apply(void 0, [{ params: match.params, query: query, body: body, files: files }].concat(args)); }, match: match }); } catch ($boundEx) { return $error($boundEx); } }, $error); }); }); return { from: from }; }, middleware: function middleware(deps, service) { return function (ctx, next) { return new Promise(function ($return, $error) { var _ref, handler; var $Try_1_Post = function () { try { return $return(next()); } catch ($boundEx) { return $error($boundEx); } }; var $Try_1_Catch = function (error) { try { ctx.body = { status: 'failure', data: { code: error.code, message: error.message, stack: error.stack, meta: error.meta } }; return $Try_1_Post(); } catch ($boundEx) { return $error($boundEx); } }; try { return Promise.resolve(service.from(ctx)).then(function ($await_4) { try { _ref = $await_4, handler = _ref.handler; if (typeof handler === 'function') { return Promise.resolve(handler(ctx)).then(function ($await_5) { try { ctx.body = $await_5; return $If_2.call(this); } catch ($boundEx) { return $Try_1_Catch($boundEx); } }.bind(this), $Try_1_Catch); } function $If_2() { return $Try_1_Post(); } return $If_2.call(this); } catch ($boundEx) { return $Try_1_Catch($boundEx); } }.bind(this), $Try_1_Catch); } catch (error) { $Try_1_Catch(error); } }); }; } }); var index = browserPlugin; exports.default = index; exports.BodyParserOptionsToken = BodyParserOptionsToken; exports.HttpHandlersToken = HttpHandlersToken; exports.HttpRouterToken = HttpRouterToken;