export type Awaitable = T | Promise; // TODO: allow dispatching more events? export type Dispatcher = ( type: "scheduled", init: { cron?: string } ) => Awaitable; export type IncomingRequest = Request< unknown, IncomingRequestCfProperties >; export interface MiddlewareContext { dispatch: Dispatcher; next(request: IncomingRequest, env: any): Awaitable; } export type Middleware = ( request: IncomingRequest, env: any, ctx: ExecutionContext, middlewareCtx: MiddlewareContext ) => Awaitable; const __facade_middleware__: Middleware[] = []; // The register functions allow for the insertion of one or many middleware, // We register internal middleware first in the stack, but have no way of controlling // the order that addMiddleware is run in service workers so need an internal function. export function __facade_register__(...args: (Middleware | Middleware[])[]) { __facade_middleware__.push(...args.flat()); } export function __facade_registerInternal__( ...args: (Middleware | Middleware[])[] ) { __facade_middleware__.unshift(...args.flat()); } function __facade_invokeChain__( request: IncomingRequest, env: any, ctx: ExecutionContext, dispatch: Dispatcher, middlewareChain: Middleware[] ): Awaitable { const [head, ...tail] = middlewareChain; const middlewareCtx: MiddlewareContext = { dispatch, next(newRequest, newEnv) { return __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail); }, }; return head(request, env, ctx, middlewareCtx); } export function __facade_invoke__( request: IncomingRequest, env: any, ctx: ExecutionContext, dispatch: Dispatcher, finalMiddleware: Middleware ): Awaitable { return __facade_invokeChain__(request, env, ctx, dispatch, [ ...__facade_middleware__, finalMiddleware, ]); }