UNPKG

file-routing-expressjs

Version:

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

1 lines 24.3 kB
{"version":3,"sources":["../../src/models/file-based-routing.ts"],"sourcesContent":["import {\n RouteGroupEntryConfig,\n FileBasedRoutingOptions,\n RouteEntryConfig,\n RouteMappingOptions,\n RouteEndpoint,\n RouteEndpoints,\n RouteHandlersMap,\n Plugin,\n RouteMiddleware,\n ExpressMethod,\n RoutePlugins\n} from \"../types\";\n\nimport { Express, RequestHandler } from \"express\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport {\n extractDirContext,\n extractEndpointName,\n extractFileContext\n} from \"../helpers/extractors\";\n\nimport {\n buildRoutePattern,\n buildRouteWithOneLeadingSlash\n} from \"../helpers/builders\";\n\nimport {\n filenameIsJSorTS,\n isDefined,\n isErrorHandler,\n isFunction,\n isNotDefined,\n isRequestHandler,\n methodIsExpressMethod\n} from \"../helpers/validators\";\n\nimport { pathToFileURL } from \"url\";\nimport { errorGuardMiddleware } from \"../guards/exception\";\nimport { InvalidPluginError, InvalidRouteHandler, RoutesRootNotFound, UnknownPluginError } from \"../types/exceptions\";\nimport { tracingMiddleware } from \"../guards/tracing\";\nimport { logger } from \"../helpers/logging\";\n\nclass FileBasedRouting {\n public readonly base: string;\n public readonly endpoints: RouteEndpoints;\n\n private readonly endpointsQueue: RouteEndpoints;\n\n private _app: Express;\n private readonly errorGuard: typeof errorGuardMiddleware | undefined;\n private readonly plugins: Map<string, Plugin> = new Map();\n private readonly collectEndpoints: boolean = false;\n\n constructor({ app, target, errorGuard, plugins, collectEndpoints }: FileBasedRoutingOptions) {\n this.base = target || path.resolve(process.cwd(), \"src\", \"routes\");\n this.endpoints = [];\n this.endpointsQueue = [];\n this.plugins = this.buildPluginMap(plugins ?? []);\n this.collectEndpoints = collectEndpoints ?? false;\n\n this._app = app;\n\n if (isFunction(errorGuard)) {\n this.errorGuard = errorGuard;\n } else if (errorGuard === true) {\n this.errorGuard = errorGuardMiddleware;\n }\n }\n\n public async createRoutes() {\n await this.mapRoutes({\n target: this.base,\n route: \"/\",\n parentGroup: undefined\n });\n }\n\n private async mapRoutes({ target, route, parentGroup }: RouteMappingOptions) {\n if (!fs.existsSync(target)) throw new RoutesRootNotFound(target);\n\n let parent = parentGroup?.route?.trim() || \"/\";\n\n const targetStat = fs.statSync(target);\n const basename = path.basename(target.replace(this.base, \"\"));\n const { name, isParam } = extractEndpointName(path.parse(basename).name);\n\n route = buildRouteWithOneLeadingSlash(route);\n\n if (targetStat.isDirectory()) {\n return this.handleDir({\n route,\n parent,\n name,\n basename,\n target,\n isParam,\n });\n }\n\n if (targetStat.isFile()) {\n return this.handleFile({\n route,\n name,\n basename,\n target,\n isParam,\n });\n }\n }\n\n private async handleDir({ route, parent, name, basename, target, isParam }: RouteGroupEntryConfig) {\n parent = path.join(parent, basename);\n\n const routes = fs.readdirSync(target);\n const { config, middlewares, errorHandler } = extractDirContext(target);\n\n const endpoint = buildRoutePattern(\n route,\n name,\n isParam,\n typeof config?.pattern === \"string\" || config.pattern instanceof RegExp\n ? config.pattern\n : undefined\n );\n\n middlewares.forEach(middleware => this._app.use(endpoint, middleware));\n\n if(this.collectEndpoints) {\n const routeEndpoint: RouteEndpoint = {\n depth: this.endpointsQueue.length,\n name,\n endpoint,\n method: \"-\",\n middlewares: middlewares.map(item => item.name),\n errorHandler: errorHandler?.name || \"-\",\n plugins: [],\n children: []\n };\n\n const parent = this.endpointsQueue.at(this.endpointsQueue.length - 1)?.children ?? this.endpoints;\n parent.push(routeEndpoint);\n this.endpointsQueue.push(routeEndpoint);\n }\n\n for(const item of routes) {\n if (item.startsWith(\"_\")) return;\n\n const newTarget = path.join(target, item);\n if (!fs.existsSync(newTarget)) return;\n\n await this.mapRoutes({\n target: newTarget,\n route: endpoint,\n parentGroup: {\n route: parent,\n }\n });\n }\n\n if(this.collectEndpoints) {\n this.endpointsQueue.pop();\n }\n\n if (errorHandler) this._app.use(endpoint, errorHandler);\n }\n\n private async handleFile({ route, name, basename, target, isParam }: RouteEntryConfig) {\n if (!filenameIsJSorTS(basename)) return;\n\n const targetAbsolutePath = pathToFileURL(path.resolve(target)).href;\n const module = await import(targetAbsolutePath);\n\n if (!module) return;\n\n const handlers: RouteHandlersMap = {\n get: module._get ?? module.default?._get,\n post: module._post ?? module.default?._post,\n delete: module._delete ?? module.default?._delete,\n put: module._put ?? module.default?._put,\n patch: module._patch ?? module.default?._patch,\n all: module._all ?? module.default?._all\n };\n\n let { config, middlewares, errorHandler } = extractFileContext(target);\n\n for (const [method, handler] of Object.entries(handlers)) {\n if (!methodIsExpressMethod(method) || isNotDefined(handler)) continue;\n\n this.isRequestHandlerOrThrow(handler, method)\n const endpoint = buildRoutePattern(\n route,\n name,\n isParam,\n config.pattern instanceof RegExp || typeof config.pattern === \"string\"\n ? config.pattern\n : config.pattern?.[method] || config.pattern?.all,\n true\n );\n\n const routeMiddlewares = this.pushMiddlewares(middlewares, method);\n const methodPlugins = config.plugins?.[method] ?? config.plugins?.all ?? {};\n\n const wrappedHandler = this.bindPlugins(handler, route, methodPlugins);\n this._app[method](\n endpoint, \n tracingMiddleware, \n ...routeMiddlewares, \n this.errorGuard?.(wrappedHandler) ?? wrappedHandler\n );\n \n let routerEndpoint: RouteEndpoint | undefined;\n if(this.collectEndpoints) {\n routerEndpoint = {\n depth: this.endpointsQueue.length,\n name,\n endpoint,\n method,\n middlewares: [],\n errorHandler: \"-\",\n plugins: Object.keys(methodPlugins),\n children: []\n };\n \n routerEndpoint.middlewares.push(...routeMiddlewares.map(middleware => middleware.name));\n }\n\n if (errorHandler) {\n let resolvedError = errorHandler as typeof errorHandler | undefined;\n\n if (typeof resolvedError !== \"function\") {\n resolvedError = resolvedError?.[method] || resolvedError?.all;\n }\n\n if (isErrorHandler(resolvedError)) {\n this._app.use(endpoint, resolvedError);\n if(isDefined(routerEndpoint)) routerEndpoint.errorHandler = resolvedError.name;\n }\n }\n\n if(isDefined(routerEndpoint)){\n const parent = this.endpointsQueue.at(this.endpointsQueue.length - 1)?.children ?? this.endpoints;\n parent.push(routerEndpoint);\n };\n }\n }\n\n private pushMiddlewares(middlewares: RouteMiddleware, method: ExpressMethod): RequestHandler[] {\n const routeMiddlewares: RequestHandler[] = [];\n\n if (Array.isArray(middlewares)) {\n middlewares.forEach(middleware => {\n this.isRequestHandlerOrThrow(middleware, method);\n routeMiddlewares.push(this.errorGuard?.(middleware) ?? middleware);\n });\n } else if (middlewares && typeof middlewares === \"object\") {\n const methodMiddlewares = middlewares[method] || middlewares.all;\n\n if (Array.isArray(methodMiddlewares)) {\n methodMiddlewares.forEach(middleware => {\n this.isRequestHandlerOrThrow(middleware, method);\n routeMiddlewares.push(this.errorGuard?.(middleware) ?? middleware);\n });\n } else if (methodMiddlewares) {\n this.isRequestHandlerOrThrow(methodMiddlewares, method);\n routeMiddlewares.push(this.errorGuard?.(methodMiddlewares) ?? methodMiddlewares);\n }\n } else if (middlewares) {\n this.isRequestHandlerOrThrow(middlewares, method);\n routeMiddlewares.push(this.errorGuard?.(middlewares) ?? middlewares);\n }\n\n return routeMiddlewares;\n }\n\n private bindPlugins(\n handler: RequestHandler,\n route: string,\n routePlugins: RoutePlugins | undefined\n ): RequestHandler {\n if (isNotDefined(routePlugins)) return handler;\n \n const active: {\n plugin: Plugin<any>;\n config: any;\n }[] = [];\n \n for (const [name, value] of Object.entries(routePlugins)) {\n const plugin = this.plugins.get(name);\n\n if (isNotDefined(plugin)) {\n if (this.collectEndpoints) {\n logger.warn(`Unknown plugin \"${name}\" in route \"${route}\"`);\n continue;\n }\n\n throw new UnknownPluginError(\n name,\n route,\n [...this.plugins.keys()]\n );\n }\n \n let enabled = true;\n let config: any = undefined;\n \n if (typeof value === \"boolean\") {\n enabled = value;\n } else {\n enabled = value.enabled ?? true;\n config = value.config;\n }\n \n if (!enabled) continue;\n \n plugin.validateConfig?.(config);\n active.push({ plugin, config });\n }\n\n let wrapped = handler;\n for (const { plugin, config } of active) {\n wrapped = plugin.wrap?.(wrapped, config) ?? wrapped;\n }\n\n return async (req, res, next)=> {\n const ctx = {\n req,\n res,\n state: {},\n config: undefined as any\n };\n\n const executed: typeof active = [];\n const delegate = async (i: number)=> {\n if(i >= active.length) {\n await wrapped(req, res, next);\n return;\n };\n\n let called = false;\n const nextFn = async ()=> {\n if(called) return;\n called = true;\n await delegate(i + 1)\n }\n \n const entry = active[i];\n const { plugin, config } = entry;\n \n executed.push(entry);\n\n ctx.config = config;\n if(isDefined(plugin.onRequest)) {\n await plugin.onRequest(ctx, nextFn);\n } else {\n await delegate(i + 1);\n }\n\n }\n\n try {\n await delegate(0);\n \n while(executed.length > 0) {\n const { config, plugin } = executed[executed.length - 1];\n\n ctx.config = config;\n \n if (isDefined(plugin.onResponse)) {\n await plugin.onResponse(ctx);\n }\n executed.pop();\n }\n } catch (err) {\n while(executed.length > 0) {\n const { config, plugin } = executed.pop()!;\n\n ctx.config = config;\n \n if (isDefined(plugin.onError)) {\n await plugin.onError(err, ctx);\n }\n }\n \n throw err;\n }\n }\n }\n\n private isRequestHandlerOrThrow(handler: RequestHandler, method: ExpressMethod): void {\n if(!isRequestHandler(handler)) throw new InvalidRouteHandler(method, handler);\n }\n\n private buildPluginMap(plugins: Plugin[]): Map<string, Plugin> {\n const map = new Map<string, Plugin>();\n\n for (const plugin of plugins) {\n if (!plugin || typeof plugin !== \"object\") {\n throw new InvalidPluginError(`Invalid plugin: expected object`);\n }\n \n if (typeof plugin.name !== \"string\" || plugin.name.trim() === \"\") {\n throw new InvalidPluginError(`Plugin must have a valid name`);\n }\n \n if (map.has(plugin.name)) {\n throw new InvalidPluginError(`Duplicate plugin name \"${plugin.name}\"`);\n }\n \n if (isDefined(plugin.wrap) && !isFunction(plugin.wrap)) {\n throw new InvalidPluginError(`Plugin \"${plugin.name}\": wrap must be a function`);\n }\n \n if (isDefined(plugin.onRequest) && !isFunction(plugin.onRequest)) {\n throw new InvalidPluginError(`Plugin \"${plugin.name}\": onRequest must be a function`);\n }\n \n if (isDefined(plugin.onResponse) && !isFunction(plugin.onResponse)) {\n throw new InvalidPluginError(`Plugin \"${plugin.name}\": onResponse must be a function`);\n }\n \n if (isDefined(plugin.onError) && !isFunction(plugin.onError)) {\n throw new InvalidPluginError(`Plugin \"${plugin.name}\": onError must be a function`);\n }\n \n if (isDefined(plugin.validateConfig) && !isFunction(plugin.validateConfig)) {\n throw new InvalidPluginError(`Plugin \"${plugin.name}\": validateConfig must be a function`);\n }\n \n Object.freeze(plugin);\n map.set(plugin.name, plugin);\n }\n \n return map;\n }\n\n public static async collectRoutes(target: string) {\n const fakeApp = {\n use: () => {},\n get: () => {},\n post: () => {},\n put: () => {},\n patch: () => {},\n delete: () => {},\n all: () => {}\n } as unknown as Express;\n\n const instance = new FileBasedRouting({\n app: fakeApp,\n target,\n collectEndpoints: true\n });\n\n await instance.createRoutes();\n\n return instance.endpoints;\n }\n}\n\nexport default FileBasedRouting;"],"mappings":"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","names":["parent","_a","_b"]}