createBunServer
The fetch and websocket handlers for serving a Meeko application with Bun.serve, using Bun's native WebSocket for Socket and its payload, backpressure and idle limits.
import { createBunServer } from "@meekojs/meeko/bun";createBunServer(app, options) returns { fetch, websocket } to spread into Bun.serve: fetch handles HTTP and upgrades Socket channels with server.upgrade, and websocket connects each peer to the hub using Bun's native WebSocket. It also records each connection's IP (server.requestIP()), read by context.clientAddress and rateLimit.
This is what meeko build --adapter bun output uses (.meeko/output/bun/index.js). Unlike Node, it does not close the server or install process failure policy: the host calls server.stop() and handleProcessErrors.
Usage#
import { createServerApp, handleProcessErrors } from "@meekojs/meeko/server";
import { createBunAssetReader, createBunServer } from "@meekojs/meeko/bun";
const app = await createServerApp({
manifest, load, runtime, production: true,
assets: createBunAssetReader({ root: new URL("./client/", import.meta.url), assets: manifest.assets ?? {} }),
});
const server = Bun.serve({ hostname: "0.0.0.0", port: 3000, ...createBunServer(app, { publicOrigin: "https://example.com" }) });
handleProcessErrors(app, { close: async () => { await server.stop(); await app.close(); } });Type#
function createBunServer(app: ServerApp, options?: BunServerOptions): BunServeHandlersinterface BunServerOptions {
readonly publicOrigin?: string
readonly platform?: ServerPlatform
readonly onError?: (error: unknown, requestId: string) => void
readonly maxPayloadLength?: number
readonly backpressureLimit?: number
readonly idleTimeout?: number
readonly sendPings?: boolean
}interface BunServeHandlers {
fetch(request: Request, server: BunServerLike): Promise<Response | undefined>
readonly websocket: BunWebSocketHandler
}Parameters#
createBunServer(app, options?):
| Option | Type | Default | Description |
|---|---|---|---|
publicOrigin |
string |
the application's, or Bun's listening URL | Public origin for URLs and HTTP and Socket Origin checks. Never uses Host. |
platform |
ServerPlatform |
Bun with Bun.env |
Each request's platform. |
onError |
(error, requestId) => void |
the application's | Transport failure observer. |
maxPayloadLength |
number |
the application's socket.maxMessageBytes, or 65536 |
Largest incoming frame; Bun closes larger ones. |
backpressureLimit |
number |
1048576 (1 MiB) |
Queued outgoing bytes per peer. A send exceeding this closes that peer with 1011, without blocking the rest of the room. |
idleTimeout |
number |
60 |
Seconds without traffic before closing a peer. |
sendPings |
boolean |
true |
Sends pings to idle peers so live connections do not expire. |
Return value#
| Member | Description |
|---|---|
fetch(request, server) |
Handles HTTP with app.fetch and Socket upgrades. Returns undefined after an upgrade, as Bun expects. |
websocket |
open, message and close, with maxPayloadLength, backpressureLimit, closeOnBackpressureLimit: false, idleTimeout, sendPings and perMessageDeflate: false already resolved. |
Examples#
Build and run Bun output#
npx meeko build --adapter bun
npx meeko preview --adapter bun # lanza bun sobre la salida
MEEKO_HOST=0.0.0.0 MEEKO_PORT=3000 bun .meeko/output/bun/index.jsindex.js includes @meekojs/meeko and server dependencies: copy the entire folder, without node_modules. Building and prerendering still run in Node.
A Bun container#
FROM oven/bun:1.4
WORKDIR /app
COPY .meeko/output/bun ./
ENV MEEKO_HOST=0.0.0.0 MEEKO_PORT=3000
EXPOSE 3000
CMD ["bun", "index.js"]server.host and server.port in meeko.config.ts only apply to Node: in Bun use MEEKO_HOST and MEEKO_PORT (or PORT).
Alongside other Bun.serve routes#
const meeko = createBunServer(app);
Bun.serve({
port: 3000,
websocket: meeko.websocket,
fetch(request, server) {
if (new URL(request.url).pathname === "/healthz") return new Response("ok");
return meeko.fetch(request, server);
},
});The websocket handler ignores sockets not opened by Meeko.
Common mistakes#
Use it outside Bun#
// node server.ts
createBunAssetReader({ root, assets }).get("/assets/entry.js", request);Error: The Meeko Bun adapter requires the Bun runtime. meeko preview --adapter bun launches bun; if it is not on PATH, it fails with an explicit message.
bun .meeko/output/bun/index.jsA limit that is not a positive integer#
Bun.serve({ port: 3000, ...createBunServer(app, { maxPayloadLength: 0 }) });RangeError: Invalid maxPayloadLength (or Invalid backpressureLimit, Invalid idleTimeout).
Bun.serve({ port: 3000, ...createBunServer(app, { maxPayloadLength: 16 * 1024 }) });Without handleProcessErrors in a custom host#
Bun.serve({ port: 3000, ...createBunServer(app) });
setTimeout(() => { throw new Error("tarea programada"); }, 1000);The process exits with the error without going through onError or closing connections: createBunServer does not install the processErrors policy.
const server = Bun.serve({ port: 3000, ...createBunServer(app) });
handleProcessErrors(app, { close: async () => { await server.stop(); await app.close(); } });An invalid MEEKO_TRUST_PROXY#
MEEKO_TRUST_PROXY=on bun .meeko/output/bun/index.jsStartup stops with TypeError: MEEKO_TRUST_PROXY must be true, false or the number of trusted proxies (1-99), or cloudflare, not "on": createBunServer checks the variable on creation.
MEEKO_TRUST_PROXY=1 bun .meeko/output/bun/index.jsNotes#
- Socket in Bun. Native
Bun.serveWebSocket:maxPayloadLengthcuts off frames before the hub (which also responds with1009above its own limit), binary messages close with1003and compression is disabled. A session or authorization rejection upgrades and closes with4401or4403. - Signals. Generated output stops
Bun.serveand closes the application onSIGINTandSIGTERM, and appliesprocessErrors; in a custom host, do this yourself. - Process failures. Bun preserves the request's
requestIdin exceptions, not in rejections. - IP.
server.requestIP()provides the connection IP; behind a proxy, useMEEKO_TRUST_PROXY. - CSP and headers (since 1.7).
server.contentSecurityPolicyandserver.headersapply just as in Node. - Conformance.
pnpm run conformance:bunbuilds the test application with this adapter and runs it with Bun without sources ornode_modules.