UNPKG

@tunframework/tun-rest-router

Version:
171 lines (170 loc) 6.34 kB
"use strict"; // @ts-check var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadRestifyRoutes = exports.RestifyRouter = void 0; const tun_1 = require("@tunframework/tun"); const route_utils_js_1 = require("./route-utils.js"); class RestifyRouter { _routes = []; // temp prefix, consumed in addRoute() _prefix = ''; _methods; constructor({ prefix = '', methods } = {}) { this.prefix(prefix); this._methods = methods; } prefix(_prefix) { this._prefix = _prefix || ''; return this; } routes() { return (ctx, next) => { let route = (0, route_utils_js_1.matchRoute)(ctx.req.method, ctx.req.path, this._routes); if (!route) { return next(); } ctx.state.matchedRoute = route; if (ctx.res.status === 404) { ctx.res.status = 200; } let slugs = route.slugNames.reduce((p, n, nIndex) => { p[n] = route.slugValues[nIndex]; return p; }, {}); ctx.req.slugs = slugs; return route.handler.call(null, ctx, next); }; } addRoute(methods, pathname, handler) { this._routes.push({ // ...pathToRegexp(pathname), ...(0, route_utils_js_1.pathToRegexp)((this._prefix || '') + pathname), methods: Array.isArray(methods) ? methods : [methods], slugValues: [], handler }); return this; } get(pathname, handler) { return this.addRoute('GET', pathname, handler); } head(pathname, handler) { return this.addRoute('HEAD', pathname, handler); } post(pathname, handler) { return this.addRoute('POST', pathname, handler); } put(pathname, handler) { return this.addRoute('PUT', pathname, handler); } delete(pathname, handler) { return this.addRoute('DELETE', pathname, handler); } // connect(pathname: string, handler: TunComposable<TunContext>) { // return this.addRoute('CONNECT', pathname, handler); // } options(pathname, handler) { return this.addRoute('OPTIONS', pathname, handler); } // trace(pathname: string, handler: TunComposable<TunContext>) { // return this.addRoute('TRACE', pathname, handler); // } patch(pathname, handler) { return this.addRoute('PATCH', pathname, handler); } /** * Fufill response header if all middleware resolved and `ctx.status` is empty or 404(not_found). */ allowedMethods(options = {}) { const implemented = this._methods || Object.keys(tun_1.HttpMethod); return async function allowedMethods(ctx, next) { await next(); if (ctx.res.status || ctx.res.status !== 404) { return; } const allowed = {}; const matchedRoute = ctx.state.matchedRoute; if (matchedRoute) { matchedRoute.methods.forEach((method) => { allowed[method] = method; }); } const allowedArr = Object.keys(allowed); if (implemented.indexOf(ctx.req.method) > -1) { if (options.throw) { let throwable = null; if (typeof options.notImplemented === 'function') { throwable = options.notImplemented(); } else { throwable = new tun_1.HttpError({ status: 501 }); } throw throwable; } else { ctx.res.status = 501; ctx.res.set('Allow', allowedArr); } } else if (allowedArr.length) { if (ctx.req.method === 'OPTIONS') { ctx.res.status = 200; ctx.body = ''; ctx.res.set('Allow', allowedArr); } else if (!allowed[ctx.req.method]) { if (options.throw) { let throwable = null; if (typeof options.notImplemented === 'function') { throwable = options.notImplemented(); } else { throwable = new tun_1.HttpError({ status: 405 }); } throw throwable; } else { ctx.res.status = 405; ctx.res.set('Allow', allowedArr); } } } }; } } exports.RestifyRouter = RestifyRouter; let loadRestifyRoutes = async (pathname) => { let M = await Promise.resolve().then(() => __importStar(require(pathname))); let list = Object.keys(M) .filter((k) => M[k] instanceof RestifyRouter) .map((k) => M[k]); if (list.length === 1) { return list[0]; } // compose let r = new RestifyRouter(); for (const item of list) { r._routes.push(...item._routes); } return r; }; exports.loadRestifyRoutes = loadRestifyRoutes;