[]previous and next page

Other runtimes

Any other runtime needs a few lines that call the handler.

For agentsUpdated

Any other runtime needs a few lines that call the handler. The handler is fetch(request, platform) => Promise<Response> and the framework imports no node:* module. createFetch(handler) from @shadow-js/dusk/server builds the { fetch(request, env, ctx) } module that Workers, Vercel and Netlify expect; the platforms above are its uses.

src/worker.tsts
import type { DuskHandler } from "@shadow-js/dusk/server";

export function createWorker(handler: DuskHandler): {
  fetch(request: Request, platform?: unknown): Promise<Response>;
} {
  return { fetch: (request, platform) => handler.fetch(request, platform) };
}

The second argument is the platform object. The handler reads two things from it: a string clientAddress (the peer address, for event.clientAddress), and, when envSource: false is set, its string properties as the environment that defineEnv validates on the first request (for bindings that exist only per request). Static assets and the client bundle must be served by the platform; the handler does not serve files.

getRequestEvent() needs AsyncLocalStorage to follow the request across await. Dusk finds it through process.getBuiltinModule("node:async_hooks"), so it works where that exists (Node 22 here; the source names Bun, Deno and Workers with nodejs_compat as hosts that expose it, untested). Where it does not, hasAsyncContext is false, getRequestEvent() throws DuskError SERVER_ALS_UNAVAILABLE, and tryGetRequestEvent() returns undefined; pass the event that middleware, API routes and server functions receive (and context.event in loaders) instead. The option asyncContext: false turns the context off on purpose.

src/routes/api/context.tsts
import { json, tryGetRequestEvent, type RequestEvent } from "@shadow-js/dusk/server";

export const GET = (event: RequestEvent) =>
  json({ sameEvent: tryGetRequestEvent() === event });