UNPKG

file-routing-expressjs

Version:

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

295 lines (219 loc) 10 kB
# file-routing-expressjs A dependency-free, flexible, system-based file routing for Express. ## Installation ```shell npm install file-routing-expressjs ``` ## Usage This package integration in your project is very simple. You will need to wrap your `Express` instance with an `mapRoutes(config)` that will bind the routes directly to the app. ```js import express from "express"; import path from "path"; import { mapRoutes } from "file-routing-expressjs"; const ROUTES_PATH = path.resolve(__dirname, "..", "app", "routes"); const app = express(); // Option 1: Basic usage mapRoutes({app: app, target: ROUTES_PATH}) // Option 2: If you need to log the endpoints binded by mapRoutes use this async function main() {     const { endpoints } = await mapRoutes({app: app, target: ROUTES_PATH});     console.table(endpoints); } main(); app.listen(3000, ()=> console.log("I'm listening mother father")); ``` ### Options - **`target`**: The root directory for your route files. Defaults to `/src/routes`. - **`app`**: The instance of the **Express** application used for handling routes. ## Routes Directory Structure Files located in your project's `options.target` directory will automatically correspond to a matching URL path. **Note**: Files that start with an underscore (`_`) or do not have a `.ts` or `.js` extension will not be bound to the app. ``` 📦routes 📂api 📜index.ts 📜_middleware.ts # global middlewares for '/api' 📂[users] # dynamic params 📂[user] 📜index.ts 📜books.ts 📜index.ts 📜_middleware.ts 📜_error.ts 📜_config.ts # /:users config file (path pattern etc.) 📜index.ts # '/' endpoint - default route 📜posts.ts # '/posts' endpoint 📜_error.ts # global error handler ``` The folder structure is quite simple and straightforward, as you can see. 💀💀💀 * `/api/<?pattern_in_index>` * `/:users<?patter_in_config>/<?pattern_in_index>` * `/:users<?patter_in_config>/books<?pattern_in_books>` * `/:users<?patter_in_config>/:user/<?pattern_in_index>` * `/<?pattern_in_index>` * `/posts<?pattern_in_posts>` ## Examples ### HTTP Method Handling If you export functions such as `get`, `post`, `put`, `patch`, `all` or `delete` from a route file, they will automatically be mapped to their respective `HTTP/Express` methods . ```js export const _get = (req, res, next) => {...} export const _post = (req, res) => {...} export const _delete = (req, res) => {...} export const _put = (req, res, next) => {...} export const _patch = (req, res, next) => {...} export const _all = (req, res, next) => {...} ``` ### Route Pattern #### For a directory In the example above, there's a file named `/[users]/_config.ts`. In this file, you should export an object that is used to configure the route pattern for that specific endpoint. This configuration object can include settings like a custom URL pattern or route validation. ```js // Option 1: default export export default {     pattern: /[a-fA-F0-9]{24}/g // this could be a Regex or a string }; // Option 2: named export export const config = {     pattern:'[a-fA-F0-9]{24}' }; ``` * `/:users([a-fA-F0-9]{24})/<?pattern_in_index>` If `users` path is not a dynamic route your endpoint will be: * `/([a-fA-F0-9]{24})/<?pattern_in_index>` #### For JS/TS files You can define a global pattern that applies to all HTTP methods in Express routes, or alternatively, specify a distinct pattern for each method within the route file. This allows for flexible URL handling, depending on whether you need a consistent format for all methods or different structures for specific HTTP methods. ```js // Option 1: a pattern for each method export const config = {     pattern: {         get: /[A-Z]{3}-[0-9]{4}-[a-z]{2}/,         post: /([0-9]{5})/,         put: /[A-Z]{2}[0-9]{2}/         delete: /(^\d{5}(-\d{4})?$)/,         patch: /(^([01]\d|2[0-3]):([0-5]\d)$)/,         all: /^\d{13,19}$/     } } // Option 2: a global pattern export const config = {     pattern: /[A-Z]{3}-[0-9]{4}-[a-z]{2}/ } ``` #### Option 1 | method | endpoint | | ---------- | --------------------------------------------------------- | | **GET** | `/:users([a-fA-F0-9]{24})/([A-Z]{3}-[0-9]{4}-[a-z]{2})` | | **POST** | `/:users([a-fA-F0-9]{24})/([0-9]{5})` | | **PUT** | `/:users([a-fA-F0-9]{24})/([A-Z]{2}[0-9]{2})` | | **DELETE** | `/:users([a-fA-F0-9]{24})/(^\d{5}(-\d{4})?$)` | | **PATCH** | `/:users([a-fA-F0-9]{24})/(^([01]\d\|2[0-3]):([0-5]\d)$)` | | **ALL** | `/:users([a-fA-F0-9]{24})/(^\d{13,19}$)` | **Note**: If you specify an **all** pattern in the configuration object, it will be used as the default pattern for any HTTP methods that are not explicitly defined. #### Option 2 | method | endpoint | | ---------------------------------------------------------- | ------------------------------------------------------- | | **GET**, **POST**, **PUT**, **DELETE**, **PATCH**, **ALL** | `/:users([a-fA-F0-9]{24})/([A-Z]{3}-[0-9]{4}-[a-z]{2})` | ### Middleware You can apply route-specific middleware in Express by exporting an array of request handlers directly from your route file. #### For a directory In the example above, there's a file named `/[users]/_middleware.ts`. In this file, you should export a middleware or the list of middlewares you want to apply on the endpoint (`/users` in this case). The middleware will wrap all the sub routes of `/:users` ```js import authMiddleware from "../middlewares/authMiddleware"; import rateLimitingMiddleware from "../middlewares/rateLimitingMiddleware"; import testMiddleware from "../middlewares/testMiddleware"; // Option 1: A list of middleware functions export const middlewares = [     authMiddleware, rateLimitingMiddleware     testMiddleware ]; // Option 2: A single middlware function export const middlewares = testMiddleware; // default export or named export export default middlewares; ``` #### For JS/TS files You can define a global middleware/list of middlewares that wraps to all HTTP methods in Express routes, or alternatively, specify a distinct middleware/list of middlewares for each method within the route file. ```js // Option 1: One middleware for all the exisiting requests handlers export const middlewares = authMiddleware; // Option 2: A list of middlewares for all the exisiting requests handlers export const middlewares = [rateLimitingMiddleware, authMiddleware, testMiddleware]; // Option 3: A map of methods with middlware/list of middlewares export const middlewares = {     get: [testMiddleware, rateLimitingMiddleware],     all: authMiddleware }; ``` **Note**: Any route handlers that are not explicitly defined will be wrapped by the `all` middleware, if such middleware exists. ### Error Handling You can apply route-specific middleware in Express by exporting an array of request handlers directly from your route file. #### For a directory In the example above, there is a file named `/[users]/_error_.ts`. Within this file, you should export an error handler function, which can be either a default or named export. This function will handle errors specific to `[users]` directory route and the routes under it. ```js import globalErrorHandler from "../middlewares/globalErrorHandler"; export const errorHandler = globalErrorHandler; // default export or named export export default errorHandler; ``` #### For JS/TS files You can define an error handler that wraps all HTTP methods in Express routes, or alternatively, specify a distinct error handler for each method within the route file. ```js import testErrorHandler from "../middlewares/testErrorHandler"; import clientErrorHandler from "../middlewares/clientErrorHandler"; // Option 1: A handler fro all the existing methods export const error = clientErrorHandler; // Option 2: A map of methods with error handlers export const error = {     put: testErrorHandler,     all: clientErrorHandler }; ``` **Note**: Any route handlers that are not explicitly defined will be wrapped by the `all` error handler, if such error handler exists. ### Examples - TS #### For a directory ##### `_config.ts` ```ts import { DirRouteConfig } from "file-routing-expressjs"; const config: DirRouteConfig = {     pattern: "[A-Z]{2}-\\d{4}" }; export default config; ``` ##### `_middleware.ts` ```ts import { RouterDirMiddleware } from "file-routing-expressjs"; import authMiddleware from "../middlewares/authMiddleware"; import testMiddleware from "../middlewares/testMiddleware"; export const middlewares: RouterDirMiddleware = [     authMiddleware,     testMiddleware ]; ``` ##### `_error.ts` ```ts import { ErrorHandler } from "file-routing-expressjs"; import errorsMiddleware from "../middlewares/errorsMiddleware"; export const errorHandler: ErrorHandler = errorsMiddleware; ``` #### For JS/TS files ```ts import { RequestHandler } from "express"; import { RouterFileMiddleware, RouterFileError, RouteConfig } from "file-routing-expressjs"; import testMiddleware from "../../middlewares/testMiddleware"; import authMiddleware from "../../middlewares/authMiddleware"; import clientErrorHandler from "../../middlewares/clientErrorMiddlware"; export const config: RouteConfig = {     pattern: {         get: /[A-Z]{3}-[0-9]{4}-[a-z]{2}/,         all: /[a-fA-F0-9]{24}/     } }; export const middlewares: RouterFileMiddleware = {     get: testMiddleware,     all: authMiddleware }; export const error: RouterFileError = clientErrorHandler; export const _get: RequestHandler = (req, res, next)=> {...} export const _post: RequestHandler = (req, res, next)=> {...} export const _put: RequestHandler = (req, res, next)=> {...} ```