Skip to content

Support Node server and pluggable Start.serve (#23) - #111

Draft
nounder wants to merge 1 commit into
mainfrom
cursor/fix-23-esbuild-node-c215
Draft

Support Node server and pluggable Start.serve (#23)#111
nounder wants to merge 1 commit into
mainfrom
cursor/fix-23-esbuild-node-c215

Conversation

@nounder

@nounder nounder commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Fixes #23

Summary

Adds a Node.js HTTP server implementing StartServer, and makes Start.serve platform-pluggable so esbuild/node deployments are first-class alongside Bun.

Changes

  • node/NodeServer with Web Request/Response bridging and WebSocket upgrade framing
  • node/NodeRuntime
  • Start.serve({ server, runMain }) optional platform override (Bun remains default)

Test plan

  • bun test test/node/NodeServer.test.ts test/StartServe.test.ts (WS cases skip under Bun due to known Bun node:http upgrade bug; verified against Node)
Open in Web Open in Cursor 

- src/node/NodeServer.ts: implements the StartServer interface (upgrade,
  runFork, address, url, setRoutes) on top of node:http, mirroring
  BunServer's design. HTTP requests are bridged to/from the Web
  Request/Response API; routing reuses the existing platform-agnostic
  RouteHttp.toWebHandlerRuntime and RouteMap/PathPattern matching, so
  BundleRoute, StaticRoute, and every existing Route.* helper work
  unchanged.
- src/node/internal/WebSocketFrame.ts: minimal RFC 6455 server-side framing
  (encode/decode, handshake accept-key) — Node's raw 'upgrade' socket only
  gives bytes, not decoded messages, so Route.ws needs this to build a
  Socket the same way BunServer does with Bun's native WebSocket.
  NodeServer's upgrade() correlates an 'upgrade' event's raw socket back to
  the synthetic Request that flows through the same route-matching path as
  ordinary requests, via a WeakMap — this lets Route.ws call
  server.upgrade(request, scope) exactly like it does under Bun.
- src/node/NodeRuntime.ts: Node counterpart to bun/BunRuntime.ts (same
  process signal handling, just named for the platform it targets).
- src/Start.ts: Start.serve now accepts optional {server, runMain} to
  target another platform, defaulting to Bun for full backward
  compatibility. AppRequirements now bounds on the platform-agnostic
  StartServer.StartServer instead of BunServer.BunServer.
- Tests: test/node/NodeServer.test.ts covers HTTP routing (text/json/404/
  params/content-negotiation/POST bodies/HEAD) and Route.ws (echo,
  text+binary frames, concurrent connections, close codes, 426 responses).
  The websocket cases are skipped under `bun test` because Bun's node:http
  upgrade support has known socket.write flushing bugs (oven-sh/bun#32195)
  independent of this change; verified working against real Node.js
  manually. test/StartServe.test.ts verifies the new
  Start.serve({server, runMain}) plugability end-to-end against NodeServer.

Co-authored-by: Ralph Gutkowski <nounder@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support esbuild and node

2 participants