Replies: 2 comments 7 replies
-
|
If pillarjs/router#122 is agreed upon, then the following function will solve this case. * Recursively prints the registered routes of an Express router.
*
* @param {Array} routerStack - The stack of middleware and routes from an Express router.
* @param {string} [parentPath=''] - The parent path to prepend to the route paths.
*/
function printRegisteredRoutes(routerStack, parentPath = '') {
routerStack.forEach((middleware) => {
if (middleware.route) {
console.debug(
middleware.route.stack[0].method.toUpperCase(),
`${parentPath}${middleware.route.path}`
);
} else if (middleware.name === 'router') {
printRegisteredRoutes(
middleware.handle.stack,
`${parentPath}${middleware.path}`
);
}
});
} |
Beta Was this translation helpful? Give feedback.
7 replies
-
|
This is a hack around, I wouldn't promote running it in production but in a pipeline or locally it should solve the problem of targeting routers. It may require some shuffling of entry points but it works. // src/routes/user.ts
import type { Express, } from 'express';
export const userRouter = express.Router();
// Must be named function or a first class function
const someMiddleware: RequestHandler = (req, res, next) => {
next();
};
const someOtherMiddleware: RequestHandler = (req, res, next) => {
next();
};
userRouter.get('/', someMiddleware, function getUsers(req, res, next) { next() });
userRouter.post('/', someMiddleware, function getUsers(req, res, next) { next() });
userRouter.delete('/:id', function getUsers(req, res, next) { next() });
userRouter.get('/workspace/:id', someMiddleware, someOtherMiddleware, function getUserWorkspace(req, res, next) { next() });
userRouter.delete('/workspace/:id', function deleteUserWorkspace(req, res, next) { next() });
// Handler will be "<anonymous>"
userRouter.put('/workspace/:id', (req, res, next) => { next() });// src/routes/workspace.ts
import type { Express } from 'express';
export const workspaceRouter = express.Router();
// Must be named function or a first class function
const someMiddleware: RequestHandler = (req, res, next) => {
next();
};
workspaceRouter.get('/', someMiddleware, function getWorkspace(req, res, next) { next() });
workspaceRouter.post('/', someMiddleware, function createWorkspace(req, res, next) { next() });
workspaceRouter.delete('/:id', function deleteWorkspace(req, res, next) { next() });/// src/routes/index.ts
// Initialize the endpoints in a central location so it can be used by the server.ts or this generate.ts
import type { Express } from 'express';
import { userRouter } from './workspace.js';
import { workspaceRouter } from './workspace.js';
export function init(app: Express) {
app.use('/user', userRouter);
app.use('/workspace', workspaceRouter);
}// src/scripts/express-generate.ts
// Load env in case routes require then
import 'dotenv/config';
import 'dotenv-expand/config';
import express from 'express';
import type { Express, RequestHandler, IRouter } from 'express';
import { init } from '../routes/index.js';
const app: Express = express();
type ApplicationUse = typeof app.use;
type ILayer = IRouter['stack'][0];
// Bind the app.use so that the this context is available.
const originalUse: ApplicationUse = app.use.bind(app);
interface PathObject {
fullPath: string;
method: string;
middleware: string[];
handler: string;
}
function analyzeExpressPaths(router: IRouter, parentPath = '') {
for (const layer of router.stack) {
if (layer.name === 'handle' && layer.route) {
const fullPath = `${parentPath}${layer.route.path}`;
const path: PathObject = {
fullPath,
method: 'unknown',
middleware: [],
handler: 'unknown'
};
const numHandlers = layer.route.stack.length;
// Iterate over the RequestHandlers
for (let index = 0; index < numHandlers; index += 1) {
const middleware = layer.route.stack[index] as ILayer;
// The last argument will be the route handler
if (index >= numHandlers - 1) {
path.method = middleware.method.toUpperCase();
// This requires named variables/functions
path.handler = middleware.name;
} else {
// This requires named variables/functions
path.middleware.push(middleware.name);
}
}
console.log(path.method, path.fullPath, path.handler, path.middleware);
// Recursively call until all routers are covered.
} else if (layer.name === 'router' && layer.handle) {
analyzeExpressPaths(
layer.handle as IRouter,
parentPath
);
}
}
}
// Override the implementation of app.use
app.use = function (...args: Parameters<ApplicationUse>) {
// If this is a regular router then we're doing to try interpret the router object.
if (typeof args[0] === 'string') {
const basePath = args[0];
// Iterate over the remaining objects to find the router function
for (let i = 1; i < args.length; i += 1) {
const arg = args[i];
if (typeof arg === 'function' && arg.name === 'router' && basePath) {
// We now know the arg is a Router.
analyzeExpressPaths(arg, basePath);
}
}
}
originalUse(...args);
} as ApplicationUse;
// Initialize the app to load the routers
init(app);npx tsx ./src/scripts/express-generate.ts
GET /users/ getUsers [ 'someMiddleware' ]
POST /users/ getUsers [ 'someMiddleware' ]
DELETE /users/:id getUsers []
GET /users/workspace/:id getUserWorkspace [ 'someMiddleware', 'someOtherMiddleware' ]
DELETE /users/workspace/:id deleteUserWorkspace []
PUT /users/workspace/:id <anonymous> []
GET /workspace/ getWorkspace [ 'someMiddleware' ]
POST /workspace/ createWorkspace [ 'someMiddleware' ]
DELETE /workspace/:id deleteWorkspace []Then in your main app you can do something like this so that you're not modifying the app.use function in production. // src/app.ts
import { init } from '../routes/index.js';
const app: Express = express();
// Initialize the app to load the routers
init(app);
app.listen(() => {
}) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In continue of this discussion #5858
After upgrade to stable v5 i can't find
layer.regexpanymore. So, prevoius soluton doesn't work anymore.Does anyone have any ideas on how to build a complete tree of subrouts? Thank you!
Beta Was this translation helpful? Give feedback.
All reactions