feat(core): Allow using middlewares with decorators on a per-route basis (no-changelog) (#5656)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-03-09 15:08:48 +01:00 committed by GitHub
parent 356e916194
commit d872866add
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 8 deletions

View file

@ -1,15 +1,25 @@
import type { RequestHandler } from 'express';
import { CONTROLLER_ROUTES } from './constants';
import type { Method, RouteMetadata } from './types';
interface RouteOptions {
middlewares?: RequestHandler[];
}
/* eslint-disable @typescript-eslint/naming-convention */
const RouteFactory =
(method: Method) =>
(path: `/${string}`): MethodDecorator =>
(path: `/${string}`, options: RouteOptions = {}): MethodDecorator =>
(target, handlerName) => {
const controllerClass = target.constructor;
const routes = (Reflect.getMetadata(CONTROLLER_ROUTES, controllerClass) ??
[]) as RouteMetadata[];
routes.push({ method, path, handlerName: String(handlerName) });
routes.push({
method,
path,
middlewares: options.middlewares ?? [],
handlerName: String(handlerName),
});
Reflect.defineMetadata(CONTROLLER_ROUTES, routes, controllerClass);
};

View file

@ -20,17 +20,18 @@ export const registerController = (app: Application, config: Config, controller:
const restBasePath = config.getEnv('endpoints.rest');
const prefix = `/${[restBasePath, controllerBasePath].join('/')}`.replace(/\/+/g, '/');
const middlewares = (
const controllerMiddlewares = (
(Reflect.getMetadata(CONTROLLER_MIDDLEWARES, controllerClass) ?? []) as MiddlewareMetadata[]
).map(
({ handlerName }) =>
(controller as Controller)[handlerName].bind(controller) as RequestHandler,
);
routes.forEach(({ method, path, handlerName }) => {
routes.forEach(({ method, path, middlewares: routeMiddlewares, handlerName }) => {
router[method](
path,
...middlewares,
...controllerMiddlewares,
...routeMiddlewares,
send(async (req: Request, res: Response) =>
(controller as Controller)[handlerName](req, res),
),

View file

@ -1,4 +1,4 @@
import type { Request, Response } from 'express';
import type { Request, Response, RequestHandler } from 'express';
export type Method = 'get' | 'post' | 'put' | 'patch' | 'delete';
@ -10,7 +10,10 @@ export interface RouteMetadata {
method: Method;
path: string;
handlerName: string;
middlewares: RequestHandler[];
}
type RequestHandler = (req?: Request, res?: Response) => Promise<unknown>;
export type Controller = Record<RouteMetadata['handlerName'], RequestHandler>;
export type Controller = Record<
RouteMetadata['handlerName'],
(req?: Request, res?: Response) => Promise<unknown>
>;