@signicode/verser2-guest-bun
v0.9.3
Published
Bun Guest and Broker APIs for Verser2 outbound Host routing.
Downloads
1,999
Maintainers
Readme
@signicode/verser2-guest-bun
Serve a Bun Fetch-style handler through verser2 without opening a Bun listener.
This package adapts local handlers to Bun/fetch semantics and reuses the
@signicode/verser2-guest-node transport for Host connection, route
advertisement, Broker requests, and lease lifecycle; it also exports a
Bun-facing Broker wrapper.
Audience: Bun services acting as verser2 Guests, and Bun applications that
call Guests as Brokers. Requires a Host (@signicode/verser2-host).
Public API
VERSER2_GUEST_BUN_PACKAGE_NAMEcreateVerserBunGuest(options)— create a Bun GuestcreateVerserBroker(options)— create a Bun-facing Broker wrapperguest.revokeRoutes(domains)— revoke advertised route domains; delegates to Node GuestrevokeRoutes()with the same{ status: 'ack'|'partial'|'error' }responsebroker.onRouteChange(listener)— observe route lifecycle events (added,removed,changed,degraded) with payload{ type, targetId, domain, reason?, generation? }- Types: Guest/Broker options, request/response, lifecycle, route lifecycle events, route/handler types
Basic usage
Unlike a normal Bun server, a Bun Guest does not call Bun.serve() or
listen() for this routing path.
import { createVerserBunGuest } from '@signicode/verser2-guest-bun';
const guest = createVerserBunGuest({
hostUrl: 'https://localhost:8443',
guestId: 'bun-client-a',
tls: { caFile: '/etc/verser/ca.crt' },
});
guest.attach({
fetch(request) {
if (request.method === 'GET' && request.url.endsWith('/health')) {
return Response.json({ ok: true });
}
return new Response('not found', { status: 404 });
},
}, 'bun-client-a.local.test');
await guest.connect();Broker usage
The Bun package exports createVerserBroker wired to the same Node transport:
import { createVerserBroker } from '@signicode/verser2-guest-bun';
import http from 'node:http';
const broker = createVerserBroker({
hostUrl: 'https://localhost:8443',
brokerId: 'broker-a',
tls: { caFile: '/etc/verser/ca.crt' },
});
const agent = broker.createAgent();
const dispatcher = broker.createDispatcher();
const routedFetch = broker.createFetch();
await broker.connect();
await broker.waitForRoute('bun-client-a.local.test');
http.get('http://bun-client-a.local.test/health', { agent }, (res) => res.resume());
await routedFetch('http://bun-client-a.local.test/health');
await fetch('http://bun-client-a.local.test/health', { dispatcher });Route lifecycle observation
Brokers can observe route changes reactively:
const unsubscribe = broker.onRouteChange((event) => {
console.log(event.type, event.domain, event.reason);
});
// Unsubscribe later:
unsubscribe();The route snapshot (getRoutes()) is updated before listeners fire. See
Lifecycle and errors for event types,
reasons, and degraded-route behavior.
Guest route revocation
A connected Bun Guest can revoke advertised routes:
const result = await guest.revokeRoutes(['bun-client-a.local.test']);
// result.status === 'ack' | 'partial' | 'error'The revocation is sent over the dedicated /verser/guest/revoke request path.
The Bun wrapper delegates to the Node Guest implementation.
Local route dispatch
The handler object can include a routes table for local path matching. This is
local dispatch only and does not affect Host route advertisements.
guest.attach({
routes: {
'/health': new Response('ok', { status: 200 }),
'/users/:id': (request) => new Response(request.params.id),
'/files/*': () => new Response('wildcard', { status: 200 }),
'/items': {
GET: new Response('read', { status: 200 }),
POST: () => new Response('created', { status: 201 }),
},
},
fetch: (request) => new Response('fallback', { status: 404 }),
}, 'bun-client-a.local.test');Matching precedence: exact path → :param routes → * wildcard → fetch
fallback.
WebSockets
Bun Guests expose Bun's usual upgrade shape over VWS/1, without opening a Bun listener:
guest.attach({
fetch(request, server) {
if (server.upgrade(request, { protocol: 'chat.v1' })) return undefined;
return new Response('not found', { status: 404 });
},
websocket: {
message(ws, message) { ws.send(message); },
close(_ws, code, reason) { console.log(code, reason); },
},
}, 'bun-client-a.local.test');The Bun-facing Broker inherits webSocket() and adds nativeWebSocket() from
the Node transport. Both use explicit VWS/1 frames and can follow an
authenticated multi-Host federation path. The route advertisement contains no
WebSocket capability bit; an advertised endpoint may still reject an open.
Caveats
- The Bun Guest uses the same transport as the Node Guest; route advertisement, lifecycle events, close behavior, and lease management are consistent.
- Generic HTTP/1 upgrade forwarding is not implemented.
server.upgrade()is only the Bun Guest VWS/1 adapter described above. - CONNECT/RFC8441, L4 forwarding, and Agent/Dispatcher upgrades remain unsupported.
- Direct Broker request bodies use the Node Broker surface: omit the body, pass
Bufferchunks, or stream with a NodeReadable. Fetch-style request bodies are available throughcreateFetch()/createDispatcher(). - Bun Guest handler responses are Web
Responseobjects; Broker responses follow the Node Broker response stream surface. - When no domain is supplied to
attach(), the Guest ID is used as the route domain.
