UNPKG

file-routing-expressjs

Version:

A dependency-free, flexible, system-based file routing for Express.

172 lines 6.4 kB
var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; var import_meta = {}; import { fileURLToPath } from "url"; import path from "path"; var getFilename = () => fileURLToPath(import_meta.url); var getDirname = () => path.dirname(getFilename()); var __dirname = /* @__PURE__ */ getDirname(); var __filename = /* @__PURE__ */ getFilename(); import fs from "fs"; import path2 from "path"; import { extractDirContext, extractEndpointName, extractFileContext } from "../helpers/extractors"; import { buildRoutePattern, buildRouteWithOneLeadingSlash } from "../helpers/builders"; import { filenameIsJSorTS, functionIsExceptionHandler, functionIsRequestHandler, methodIsExpressMethod } from "../helpers/validators"; class FileBasedRouting { constructor({ app, target }) { this.base = target || path2.resolve(__dirname, "src", "routes"); this._app = app; this.endpoints = []; this._currentDepth = 0; } createRoutes() { return __async(this, null, function* () { this.mapRoutes({ target: this.base, route: "/", parentConfig: void 0 }); }); } mapRoutes(_0) { return __async(this, arguments, function* ({ target, route, parentConfig }) { var _a; if (!fs.existsSync(target)) { return; } let parent = ((_a = parentConfig == null ? void 0 : parentConfig.route) == null ? void 0 : _a.trim()) || "/"; const targetStat = fs.statSync(target); const basename = path2.basename(target.replace(this.base, "")); const { name, isParam } = extractEndpointName(path2.parse(basename).name); route = buildRouteWithOneLeadingSlash(route); if (targetStat.isDirectory()) { return this.handleDir({ route, parent, name, basename, target, isParam }); } if (targetStat.isFile()) { return this.handleFile({ route, name, basename, target, isParam }); } }); } handleDir({ route, parent, name, basename, target, isParam }) { parent = path2.join(parent, basename); const routes = fs.readdirSync(target); const { config, middlewares, errorHandler } = extractDirContext(target); const endpoint = buildRoutePattern(route, name, isParam, typeof (config == null ? void 0 : config.pattern) === "string" || config.pattern instanceof RegExp ? config.pattern : void 0); middlewares.forEach((middleware) => this._app.use(endpoint, middleware)); this.endpoints.push({ depth: this._currentDepth++, name, endpoint, method: "-", middlewares: middlewares.map((item) => item.name), errorHandler: (errorHandler == null ? void 0 : errorHandler.name) || "-" }); routes.forEach((item) => { if (item.startsWith("_")) return; const newTarget = path2.join(target, item); if (!fs.existsSync(newTarget)) return; this.mapRoutes({ target: newTarget, route: endpoint, parentConfig: { route: parent } }); }); this._currentDepth--; if (errorHandler) this._app.use(endpoint, errorHandler); } handleFile(_0) { return __async(this, arguments, function* ({ route, name, basename, target, isParam }) { var _a, _b; if (!filenameIsJSorTS(basename)) return; const module = yield import(target); if (!module) return; const handlers = { get: module._get, post: module._post, delete: module._delete, put: module._put, patch: module._patch, all: module._all }; let { config, middlewares, errorHandler } = extractFileContext(target); const entries = Object.entries(handlers); for (const [method, handler] of entries) { if (!methodIsExpressMethod(method) || !functionIsRequestHandler(handler)) continue; const endpoint = buildRoutePattern( route, name, isParam, config.pattern instanceof RegExp || typeof config.pattern === "string" ? config.pattern : ((_a = config.pattern) == null ? void 0 : _a[method]) || ((_b = config.pattern) == null ? void 0 : _b.all), true ); const routerEndpoint = { depth: this._currentDepth, name, endpoint, method, middlewares: [], errorHandler: "-" }; const routeMiddlewares = []; if (Array.isArray(middlewares)) { middlewares.forEach((middleware) => { routeMiddlewares.push(middleware); routerEndpoint.middlewares.push(middleware.name); }); } else if (typeof middlewares === "object") { const methodMiddlwares = middlewares[method] || middlewares.all; if (!Array.isArray(methodMiddlwares)) { if (methodMiddlwares) { routeMiddlewares.push(methodMiddlwares); routerEndpoint.middlewares.push(methodMiddlwares.name); } } else { methodMiddlwares == null ? void 0 : methodMiddlwares.forEach((middleware) => { routeMiddlewares.push(middleware); routerEndpoint.middlewares.push(middleware.name); }); } } else { routeMiddlewares.push(middlewares); routerEndpoint.middlewares.push(middlewares.name); } this._app[method](endpoint, ...routeMiddlewares, handler); if (errorHandler) { if (typeof errorHandler !== "function") { errorHandler = errorHandler[method] && errorHandler.all; } if (functionIsExceptionHandler(errorHandler)) { this._app.use(endpoint, errorHandler); routerEndpoint.errorHandler = errorHandler.name; } } this.endpoints.push(routerEndpoint); } }); } } var fileBasedRouting_default = FileBasedRouting; export { fileBasedRouting_default as default }; //# sourceMappingURL=fileBasedRouting.mjs.map