type Middleware = ( context: TContext, next: () => Promise ) => Promise; export type MiddlewareChain = { use: (middleware: Middleware) => void; execute: (context: TContext) => Promise; }; export function createMiddlewareChain( fallback?: (context: TContext) => Promise ): MiddlewareChain { const middlewares: Middleware[] = []; return { use(middleware: Middleware) { middlewares.push(middleware); }, async execute(context: TContext) { let index = 0; async function dispatch(ctx: TContext): Promise { if (index >= middlewares.length) { return fallback ? fallback(ctx) : ctx as unknown as TReturn; } const current = middlewares[index++]; return current(ctx, () => dispatch(ctx)); } return dispatch(context); }, }; }