Automatically load and register Express routes from folder structure
npm install exroutindex.js/ts maps to folder root
[id].ts becomes :id
/api or any prefix
bash
npm install exrout
`
For hot reload support (optional):
`bash
npm install chokidar
`
---
š Quick Start
$3
`javascript
import express from "express";
import autoRoutes from "exrout";
const app = express();
await autoRoutes(app, "./routes", {
prefix: "/api",
log: true
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
`
$3
`javascript
const express = require("express");
const autoRoutes = require("exrout");
const app = express();
autoRoutes(app, "./routes").then(() => {
app.listen(3000);
});
`
---
š Folder Structure ā Routes
Your file structure automatically becomes your API routes:
`
routes/
āāā index.ts ā /
āāā users.ts ā /users
āāā posts.ts ā /posts
āāā auth/
ā āāā index.ts ā /auth
ā āāā login.ts ā /auth/login
ā āāā register.ts ā /auth/register
ā āāā [token].ts ā /auth/:token
āāā users/
āāā index.ts ā /users
āāā [id].ts ā /users/:id
`
---
š§© Writing Routes
Each route file exports an Express Router:
`typescript
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => {
res.json({ message: "Hello from users!" });
});
router.post("/", (req, res) => {
res.json({ message: "User created!" });
});
export default router;
`
---
āļø Configuration Options
`typescript
await autoRoutes(app, "./routes", {
prefix: "/api", // Prefix all routes
middleware: [authMiddleware, loggerMiddleware], // Global middleware
log: true, // Log loaded routes
watch: true, // Hot reload in development
exclude: [".test.ts", "_", "helpers/*"] // Exclusion patterns
});
`
$3
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| prefix | string | "" | Prefix for all routes (e.g., /api) |
| middleware | RequestHandler[] | [] | Global middleware applied to all routes |
| log | boolean | false | Log loaded routes to console |
| watch | boolean | false | Enable hot reload (requires chokidar) |
| exclude | string[] | [] | Glob patterns to exclude files |
$3
These patterns are excluded by default:
- .test.ts / .test.js
- .spec.ts / .spec.js
- _* (files starting with underscore)
- *.d.ts (TypeScript declaration files)
---
š§ Dynamic Route Parameters
Use bracket notation for dynamic segments:
`
routes/
āāā users/
āāā [id].ts ā /users/:id
`
`typescript
// routes/users/[id].ts
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => {
res.json({ userId: req.params.id });
});
export default router;
`
Multiple params work too:
`
routes/
āāā [category]/
āāā [productId].ts ā /:category/:productId
`
---
ā” Async Router Factory
For routes that need async initialization:
`typescript
import { Router } from "express";
import { connectDatabase } from "./db";
export default async function createRouter() {
await connectDatabase();
const router = Router();
router.get("/", async (req, res) => {
const data = await fetchData();
res.json(data);
});
return router;
}
`
---
š„ Hot Reload (Development)
Enable automatic route reloading when files change:
`typescript
await autoRoutes(app, "./routes", {
watch: process.env.NODE_ENV === "development"
});
`
> ā ļø Requires chokidar to be installed.
---
š TypeScript Support
Full TypeScript support with exported types:
`typescript
import autoRoutes, {
AutoRoutesOptions,
AutoRoutesResult,
RouteInfo,
} from "exrout";
const options: AutoRoutesOptions = {
prefix: "/api",
log: true,
};
const result: AutoRoutesResult = await autoRoutes(app, "./routes", options);
result.routes.forEach((route: RouteInfo) => {
console.log(Route: ${route.path} -> ${route.file});
});
`
---
š Return Value
autoRoutes returns a promise with information about loaded routes:
`typescript
const result = await autoRoutes(app, "./routes");
console.log(result.routes);
// [
// { path: "/", file: "/abs/path/routes/index.ts" },
// { path: "/users", file: "/abs/path/routes/users.ts" },
// { path: "/users/:id", file: "/abs/path/routes/users/[id].ts" }
// ]
// If watch mode is enabled, you can stop watching:
result.close?.();
`
---
š« Excluding Files
Skip certain files from being loaded as routes:
`typescript
await autoRoutes(app, "./routes", {
exclude: [
"*.test.ts", // Skip test files
"_*", // Skip files starting with _
"helpers/*", // Skip helper directories
".backup." // Skip backup files
]
});
`
---
š Examples
$3
`typescript
import express from "express";
import autoRoutes from "exrout";
import { authMiddleware } from "./middleware/auth";
const app = express();
app.use(express.json());
// Public routes
await autoRoutes(app, "./routes/public");
// Protected routes with auth middleware
await autoRoutes(app, "./routes/protected", {
prefix: "/api",
middleware: [authMiddleware]
});
app.listen(3000);
`
$3
`typescript
import express from "express";
import autoRoutes from "exrout";
const app = express();
// Version 1 API
await autoRoutes(app, "./routes/v1", { prefix: "/api/v1" });
// Version 2 API
await autoRoutes(app, "./routes/v2", { prefix: "/api/v2" });
app.listen(3000);
``