diff --git a/src/presets/cloudflare/runtime/_module-handler.ts b/src/presets/cloudflare/runtime/_module-handler.ts new file mode 100644 index 0000000000..92a9512a1c --- /dev/null +++ b/src/presets/cloudflare/runtime/_module-handler.ts @@ -0,0 +1,123 @@ +import "#nitro-internal-pollyfills"; +import type * as CF from "@cloudflare/workers-types"; +import type { ExportedHandler } from "@cloudflare/workers-types"; +import { useNitroApp } from "nitropack/runtime"; +import { requestHasBody, runCronTasks } from "nitropack/runtime/internal"; + +type MaybePromise = T | Promise; + +export function createHandler(hooks: { + fetch: ( + ...params: Parameters["fetch"]>> + ) => MaybePromise; +}) { + const nitroApp = useNitroApp(); + + return >{ + async fetch(request, env, context) { + // Preset-specific logic + if (hooks.fetch) { + const res = await hooks.fetch(request, env, context); + if (res) { + return res; + } + } + + const url = new URL(request.url); + let body; + if (requestHasBody(request as unknown as Request)) { + body = Buffer.from(await request.arrayBuffer()); + } + + // Expose latest env to the global context + (globalThis as any).__env__ = env; + + return nitroApp.localFetch(url.pathname + url.search, { + context: { + cf: (request as any).cf, + waitUntil: (promise: Promise) => context.waitUntil(promise), + cloudflare: { + request, + env, + context, + }, + }, + host: url.hostname, + protocol: url.protocol, + method: request.method, + headers: request.headers as unknown as Headers, + body, + }) as unknown as Promise; + }, + + scheduled(controller, env, context) { + (globalThis as any).__env__ = env; + context.waitUntil( + nitroApp.hooks.callHook("cloudflare:scheduled", { + controller, + env, + context, + }) + ); + if (import.meta._tasks) { + context.waitUntil( + runCronTasks(controller.cron, { + context: { + cloudflare: { + env, + context, + }, + }, + payload: {}, + }) + ); + } + }, + + email(message, env, context) { + (globalThis as any).__env__ = env; + context.waitUntil( + nitroApp.hooks.callHook("cloudflare:email", { + message, + event: message, // backward compat + env, + context, + }) + ); + }, + + queue(batch, env, context) { + (globalThis as any).__env__ = env; + context.waitUntil( + nitroApp.hooks.callHook("cloudflare:queue", { + batch, + event: batch, + env, + context, + }) + ); + }, + + tail(traces, env, context) { + (globalThis as any).__env__ = env; + context.waitUntil( + nitroApp.hooks.callHook("cloudflare:tail", { + traces, + env, + context, + }) + ); + }, + + trace(traces, env, context) { + (globalThis as any).__env__ = env; + context.waitUntil( + nitroApp.hooks.callHook("cloudflare:trace", { + traces, + env, + context, + }) + ); + }, + }; +} diff --git a/src/presets/cloudflare/runtime/cloudflare-module.ts b/src/presets/cloudflare/runtime/cloudflare-module.ts index 7786e1a067..990abda0a2 100644 --- a/src/presets/cloudflare/runtime/cloudflare-module.ts +++ b/src/presets/cloudflare/runtime/cloudflare-module.ts @@ -1,15 +1,13 @@ import "#nitro-internal-pollyfills"; import { useNitroApp, useRuntimeConfig } from "nitropack/runtime"; -import { requestHasBody, runCronTasks } from "nitropack/runtime/internal"; import { getPublicAssetMeta } from "#nitro-internal-virtual/public-assets"; - import { getAssetFromKV, mapRequestToAsset, } from "@cloudflare/kv-asset-handler"; -import type { ExportedHandler } from "@cloudflare/workers-types"; import wsAdapter from "crossws/adapters/cloudflare"; import { withoutBase } from "ufo"; +import { createHandler } from "./_module-handler"; // @ts-ignore Bundled by Wrangler // See https://github.com/cloudflare/kv-asset-handler#asset_manifest-required-for-es-modules @@ -25,7 +23,7 @@ interface Env { __STATIC_CONTENT?: any; } -export default >{ +export default createHandler({ async fetch(request, env, context) { // Websocket upgrade // https://crossws.unjs.io/adapters/cloudflare @@ -55,104 +53,8 @@ export default >{ } catch { // Ignore } - - const url = new URL(request.url); - let body; - if (requestHasBody(request as unknown as Request)) { - body = Buffer.from(await request.arrayBuffer()); - } - - // Expose latest env to the global context - (globalThis as any).__env__ = env; - - return nitroApp.localFetch(url.pathname + url.search, { - context: { - cf: (request as any).cf, - waitUntil: (promise: Promise) => context.waitUntil(promise), - cloudflare: { - request, - env, - context, - }, - }, - host: url.hostname, - protocol: url.protocol, - method: request.method, - headers: request.headers as unknown as Headers, - body, - }); - }, - - scheduled(controller, env, context) { - (globalThis as any).__env__ = env; - context.waitUntil( - nitroApp.hooks.callHook("cloudflare:scheduled", { - controller, - env, - context, - }) - ); - if (import.meta._tasks) { - context.waitUntil( - runCronTasks(controller.cron, { - context: { - cloudflare: { - env, - context, - }, - }, - payload: {}, - }) - ); - } - }, - - email(message, env, context) { - (globalThis as any).__env__ = env; - context.waitUntil( - nitroApp.hooks.callHook("cloudflare:email", { - message, - event: message, // backward compat - env, - context, - }) - ); - }, - - queue(batch, env, context) { - (globalThis as any).__env__ = env; - context.waitUntil( - nitroApp.hooks.callHook("cloudflare:queue", { - batch, - event: batch, - env, - context, - }) - ); }, - - tail(traces, env, context) { - (globalThis as any).__env__ = env; - context.waitUntil( - nitroApp.hooks.callHook("cloudflare:tail", { - traces, - env, - context, - }) - ); - }, - - trace(traces, env, context) { - (globalThis as any).__env__ = env; - context.waitUntil( - nitroApp.hooks.callHook("cloudflare:trace", { - traces, - env, - context, - }) - ); - }, -}; +}); function assetsCacheControl(_request: Request) { const url = new URL(_request.url);