import type { Drash } from "../../mod.ts";export type MiddlewareFunction = | (( request: Drash.Http.Request, response: Drash.Http.Response, ) => Promise<void>) | ((request: Drash.Http.Request, response: Drash.Http.Response) => void);
export type MiddlewareType = { before_request?: MiddlewareFunction[]; after_request?: MiddlewareFunction[];};
export function Middleware(middlewares: MiddlewareType) { return function (...args: unknown[]) { switch (args.length) { case 1: return ClassMiddleware(middlewares).apply(this, args); case 2: break; case 3: if (typeof args[2] == "number") { break; } return MethodMiddleware(middlewares).apply(this, args); default: throw new Error("Not a valid decorator"); } };}
function MethodMiddleware( middlewares: MiddlewareType,): ( target: Drash.Http.Resource, propertyKey: string, descriptor: PropertyDescriptor,) => any { return function ( target: Drash.Http.Resource, propertyKey: string, descriptor: PropertyDescriptor, ) { const originalFunction = descriptor.value; descriptor.value = async function (...args: unknown[]) { const { request, response } = Object.getOwnPropertyDescriptors(this); if (middlewares.before_request != null) { for (const middleware of middlewares.before_request) { await middleware(request.value, response.value); } }
const result = originalFunction.apply(this, args);
if (middlewares.after_request != null) { for (const middleware of middlewares.after_request) { await middleware(request.value, result); } } return result; };
return descriptor; };}
function ClassMiddleware(middlewares: MiddlewareType) { return function <T extends { new (...args: unknown[]): {} }>(constr: T) { const classFunctions = Object.getOwnPropertyDescriptors(constr.prototype);
for (const key in classFunctions) { if (key == "constructor") { continue; }
const originalFunction = classFunctions[key].value; classFunctions[key].value = async function (...args: unknown[]) { const { request, response } = Object.getOwnPropertyDescriptors(this); if (middlewares.before_request != null) { for (const middleware of middlewares.before_request) { await middleware(request.value, response.value); } }
const result = originalFunction.apply(this, args);
if (middlewares.after_request != null) { for (const middleware of middlewares.after_request) { await middleware(request.value, result); } } return result; };
Object.defineProperty(constr.prototype, key, classFunctions[key]); }
return constr; };}