/** * The edge adapter: a nifra app presented as a Cloudflare-Workers-shaped `ExportedHandler`. * * ## Why this is not in the server kernel * * `toFetchHandler` never touches the `Server` class. It takes a STRUCTURAL app - anything with `fetch`, and * optionally `resolveWebSocketUpgrade` - which is what lets it wrap an app it has no access to the * internals of, and what makes it a separate concern from the kernel rather than a method on it. It sat * in `server.ts` for no reason other than that both were written the same week. * * The types here are all structural too (`ExecutionContext`, `ScheduledController`, * `DurableObjectNamespaceLike`), so `@nifrajs/core` declares the Workers surface it needs instead of * depending on `@cloudflare/workers-types`. The real Workers types satisfy them. * * The `MaybePromise` import is type-only and erased, so there is no runtime cycle back into the kernel. */ import type { Platform } from "./context.js"; import type { MaybePromise } from "./server.js"; import type { WebSocketUpgradeOutcome } from "./websocket.js"; /** A Cloudflare Workers-style execution context (the `fetch` 3rd arg). Structural - only * `waitUntil` is used; declared here so `@nifrajs/core` needs no Workers type dependency. */ export interface ExecutionContext { waitUntil(promise: Promise): void; } /** A Cloudflare Workers-style scheduled (cron) controller. Structural - no Workers type dependency. */ export interface ScheduledController { /** Epoch ms the run was scheduled for. */ readonly scheduledTime: number; /** The matching cron expression from `wrangler.toml` `[triggers]`. */ readonly cron: string; /** Tell the platform not to retry this run on failure. */ noRetry(): void; } /** A nifra cron handler: the platform controller + the same typed `env`/`waitUntil` nifra threads into * request handlers. Schedule background work with `waitUntil` so it outlives the trigger. */ export type ScheduledHandler = (controller: ScheduledController, context: { readonly env: Env; waitUntil(promise: Promise): void; }) => MaybePromise; /** Structural view of a Cloudflare Durable Object namespace binding - keeps `@cloudflare/workers-types` * out of `@nifrajs/core`. The real `DurableObjectNamespace` satisfies it. */ export interface DurableObjectNamespaceLike { idFromName(name: string): unknown; get(id: unknown): { fetch(request: Request): Promise; }; } /** * Adapt a nifra app to an edge "ExportedHandler" - use it as a Cloudflare Workers (or any * `fetch(request, env, ctx)` runtime) default export. It threads `env` + `ctx.waitUntil` into the * nifra Context, so handlers read `c.env` and schedule background work via `c.waitUntil`: * * export default toFetchHandler(app) * * Pass `{ scheduled }` to also export a Workers cron handler (for a `[triggers]` schedule) - it * receives the platform controller plus the same typed `env`/`waitUntil`: * * export default toFetchHandler(app, { * scheduled: (controller, { env, waitUntil }) => * waitUntil(env.KV.put("last-run", String(controller.scheduledTime))), * }) * * No Workers-only deps - `app.fetch` stays a portable Web-standard handler; this is the thin * shim from the platform's 3-arg `fetch`/`scheduled` to it. */ export declare function toFetchHandler(app: { fetch(request: Request, platform?: Platform): MaybePromise; resolveWebSocketUpgrade?(request: Request, platform?: Platform): MaybePromise; }, options?: { scheduled?: ScheduledHandler; /** * Route WebSocket upgrades to a Durable Object that holds the connections and runs the app's * pub/sub - enabling cross-connection broadcast (`app.publish`) on Cloudflare Workers, where a * stateless isolate can't. Pass the DO namespace binding from `env`; pair with `@nifrajs/workers`' * `createWebSocketHub(app)` (the DO class) + a `wrangler.toml` binding. Without this, WS upgrades use * a per-connection `WebSocketPair` (no broadcast). */ webSocketHub?: (env: Env) => DurableObjectNamespaceLike; }): { fetch(request: Request, env: Env, ctx: ExecutionContext): MaybePromise; scheduled?(controller: ScheduledController, env: Env, ctx: ExecutionContext): MaybePromise; }; //# sourceMappingURL=edge.d.ts.map