bun-ws-router
Version:
Lightweight client/server WebSocket router for Bun with type-safe Zod/Valibot validation.
71 lines • 3.21 kB
TypeScript
import type { WebSocketHandler } from "bun";
import type { CloseHandler, MessageHandler, MessageSchemaType, OpenHandler, UpgradeOptions, WebSocketData } from "./types";
/**
* Adapter interface for pluggable validation libraries.
* Implementations bridge Zod/Valibot specifics with generic router logic.
*/
export interface ValidatorAdapter {
getMessageType(schema: MessageSchemaType): string;
safeParse(schema: MessageSchemaType, data: unknown): {
success: boolean;
data?: any;
error?: any;
};
infer<T extends MessageSchemaType>(schema: T): any;
}
/**
* WebSocket router for Bun that provides type-safe message routing with validation.
* Routes incoming messages to handlers based on message type.
*
* @template T - Application-specific data to store with each WebSocket connection.
* Always includes a clientId property generated automatically.
*/
export declare class WebSocketRouter<T extends Record<string, unknown> = Record<string, never>> {
private readonly connectionHandler;
private readonly messageRouter;
private readonly validator;
constructor(validator: ValidatorAdapter);
/**
* Merges open, close, and message handlers from another WebSocketRouter instance.
*
* USE CASE: Compose routers from different modules/features.
* WARNING: Message type conflicts are resolved by last-write-wins.
*
* NOTE: Accepts `| any` to support Zod/Valibot router instances. The type override
* in derived classes creates an LSP variance issue, making them technically incompatible
* with the base type. This is an intentional trade-off for better developer experience.
*
* @param router - Router instance to merge routes from (including Zod/Valibot routers)
* @returns This router instance for method chaining
* @see specs/adrs.md#ADR-001 - Explains the type override variance issue
*/
addRoutes(router: WebSocketRouter<T> | any): this;
/**
* Upgrades an HTTP request to a WebSocket connection.
*
* FLOW: Generate clientId → Attempt upgrade → Return appropriate HTTP response
* NOTE: clientId (UUID v7) is both stored in data and sent as header.
*/
upgrade(req: Request, options: UpgradeOptions<WebSocketData<T>>): Response;
onOpen(handler: OpenHandler<WebSocketData<T>>): this;
onClose(handler: CloseHandler<WebSocketData<T>>): this;
onMessage<Schema extends MessageSchemaType>(schema: Schema, handler: MessageHandler<Schema, WebSocketData<T>>): this;
/**
* Returns a WebSocket handler that can be used with `Bun.serve`.
*
* USAGE: Pass to Bun.serve({ websocket: router.websocket })
* NOTE: Methods are bound to preserve 'this' context.
*/
get websocket(): WebSocketHandler<WebSocketData<T>>;
private handleOpen;
private handleClose;
private handleMessage;
/**
* Creates a send function for a specific WebSocket connection.
*
* PURPOSE: Provides handlers with a validated way to send messages.
* Each connection gets its own send function with timestamp auto-injection.
*/
private createSendFunction;
}
//# sourceMappingURL=router.d.ts.map