// This loads all middlewares exposed on the middleware object and then starts // the invocation chain. The big idea is that we can add these to the middleware // export dynamically through wrangler, or we can potentially let users directly // add them as a sort of "plugin" system. import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "__ENTRY_POINT__"; import { __facade_invoke__, __facade_register__, Dispatcher } from "./common"; import type { WorkerEntrypointConstructor } from "__ENTRY_POINT__"; // Preserve all the exports from the worker export * from "__ENTRY_POINT__"; class __Facade_ScheduledController__ implements ScheduledController { readonly #noRetry: ScheduledController["noRetry"]; constructor( readonly scheduledTime: number, readonly cron: string, noRetry: ScheduledController["noRetry"] ) { this.#noRetry = noRetry; } noRetry() { if (!(this instanceof __Facade_ScheduledController__)) { throw new TypeError("Illegal invocation"); } // Need to call native method immediately in case uncaught error thrown this.#noRetry(); } } function wrapExportedHandler(worker: ExportedHandler): ExportedHandler { // If we don't have any middleware defined, just return the handler as is if ( __INTERNAL_WRANGLER_MIDDLEWARE__ === undefined || __INTERNAL_WRANGLER_MIDDLEWARE__.length === 0 ) { return worker; } // Otherwise, register all middleware once for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) { __facade_register__(middleware); } const fetchDispatcher: ExportedHandlerFetchHandler = function ( request, env, ctx ) { if (worker.fetch === undefined) { throw new Error("Handler does not export a fetch() function."); } return worker.fetch(request, env, ctx); }; return { ...worker, fetch(request, env, ctx) { const dispatcher: Dispatcher = function (type, init) { if (type === "scheduled" && worker.scheduled !== undefined) { const controller = new __Facade_ScheduledController__( Date.now(), init.cron ?? "", () => {} ); return worker.scheduled(controller, env, ctx); } }; return __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher); }, }; } function wrapWorkerEntrypoint( klass: WorkerEntrypointConstructor ): WorkerEntrypointConstructor { // If we don't have any middleware defined, just return the handler as is if ( __INTERNAL_WRANGLER_MIDDLEWARE__ === undefined || __INTERNAL_WRANGLER_MIDDLEWARE__.length === 0 ) { return klass; } // Otherwise, register all middleware once for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) { __facade_register__(middleware); } // `extend`ing `klass` here so other RPC methods remain callable return class extends klass { #fetchDispatcher: ExportedHandlerFetchHandler> = ( request, env, ctx ) => { this.env = env; this.ctx = ctx; if (super.fetch === undefined) { throw new Error("Entrypoint class does not define a fetch() function."); } return super.fetch(request); }; #dispatcher: Dispatcher = (type, init) => { if (type === "scheduled" && super.scheduled !== undefined) { const controller = new __Facade_ScheduledController__( Date.now(), init.cron ?? "", () => {} ); return super.scheduled(controller); } }; fetch(request: Request) { return __facade_invoke__( request, this.env, this.ctx, this.#dispatcher, this.#fetchDispatcher ); } }; } let WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined; if (typeof ENTRY === "object") { WRAPPED_ENTRY = wrapExportedHandler(ENTRY); } else if (typeof ENTRY === "function") { WRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY); } export default WRAPPED_ENTRY;