135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
// 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<Record<string, unknown>> = (
|
|
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<unknown, IncomingRequestCfProperties>) {
|
|
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;
|