presets(deno): add deno-handler preset for library-mode embedding#4285
presets(deno): add deno-handler preset for library-mode embedding#4285petarbasic wants to merge 1 commit into
Conversation
The existing deno-server preset calls Deno.serve() as a module-level
side effect — importing the built index.mjs immediately starts a
server, making it unusable as a library.
This adds a sibling deno-handler preset that exports { fetch } instead
of side-effecting a listen, mirroring the cloudflare-worker →
cloudflare-module split. Enables multi-tenant Deno hosting where a
parent process routes requests to multiple Nitro builds in-process
(no localhost TCP between them).
Conformance: 43/43 tests pass, identical to deno-server v2 baseline.
|
@petarbasic is attempting to deploy a commit to the Nitro Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Motivation
Multi-tenant Deno hosting (one process serving multiple Nitro builds) needs
a way to embed the Nitro handler in a host process instead of binding a port
per build. The existing
deno-serverpreset callsDeno.serve()as amodule-level side effect — importing the built
index.mjsimmediately startsa server, making it unusable as a library.
The Cloudflare preset family already has the equivalent split:
cloudflare-moduleexports{ fetch }instead of side-effecting a listen.This PR adds the same pattern for the Deno family — a
deno-handlersiblingto
deno-server.Use case
A multi-tenant dispatcher routing many Nitro builds in a single Deno
process by Host header, in-process (no localhost TCP):
Same primitive Cloudflare Workers solves via
isolate.fetch()— noper-build port binding, no per-request localhost loopback.
Implementation
New preset
deno-handler(sibling ofdeno-server/deno-deploy):deno-server's entry shape minus theDeno.serve()call.fetch(named) anddefault { fetch }— mirrorscloudflare-module's convention.startScheduleRunner()(library callers own the schedulinglifecycle).
rollupConfig,exportConditions, websocket adapter,addEventListenererror trapping asdeno-server.commands.preview/hooks.compiled(embedding host ownsdeno.json).Verification
test/presets/deno-handler.test.tsboots a minimalDeno.servewrapperaround the exported
fetchand runs the sharedtestNitro()conformancesuite against it.
43/43 tests pass — identical pass/skip ratios to the
deno-serverv2baseline. Skip-list updates in
test/tests.tsmirrordeno-server's(same Deno-runtime limitations: module-conflict resolution, sourcemap,
SQL DB driver,
BroadcastChannelunstable).Also verified end-to-end with two real Nitro builds + a routing dispatcher
(multi-site Host-header routing, no port binding at module import) —
matches the production use case the preset is designed for.
Notes
info(
Deno.ServeHandlerInfo) as the second arg tofetch(request, info);throws clearly if missing. Non-WS calls only need the
Request.the host driver owns scheduling.
as a concrete starting point with passing conformance tests.