bun-ws-router
Version:
Lightweight client/server WebSocket router for Bun with type-safe Zod/Valibot validation.
106 lines • 4.54 kB
TypeScript
import type { AnyInboundMessage, ClientOptions, ClientState, WebSocketClient } from "../client/types.js";
import type { InferMessage, InferMeta, InferPayload, MessageSchemaType as ValibotMessageSchema } from "./types.js";
export * from "../client/types.js";
export type { InferMessage, InferMeta, InferPayload, MessageSchemaType as ValibotMessageSchema, } from "./types.js";
/**
* Options for send() method with typed meta field inference.
*/
interface SendOptions<S extends ValibotMessageSchema> {
meta?: InferMeta<S>;
correlationId?: string;
}
/**
* Options for request() method with typed meta field inference.
*/
interface RequestOptions<S extends ValibotMessageSchema> extends SendOptions<S> {
timeoutMs?: number;
signal?: AbortSignal;
}
/**
* Typed WebSocket client interface with Valibot schema inference.
*
* Overrides generic client methods to provide full type safety:
* - on(): Handler receives InferMessage<S> (typed msg with payload/meta)
* - send(): Payload conditional typing via overloads
* - request(): Returns Promise<InferMessage<R>>
*
* @see specs/adrs.md#ADR-002 - Type override implementation pattern
*/
export interface ValibotWebSocketClient extends Omit<WebSocketClient, "on" | "send" | "request"> {
readonly state: ClientState;
readonly isConnected: boolean;
readonly protocol: string;
connect(): Promise<void>;
close(opts?: {
code?: number;
reason?: string;
}): Promise<void>;
onState(cb: (state: ClientState) => void): () => void;
onceOpen(): Promise<void>;
/**
* Register typed message handler.
* Handler receives fully typed message inferred from schema.
*/
on<S extends ValibotMessageSchema>(schema: S, handler: (msg: InferMessage<S>) => void): () => void;
/**
* Send message with payload (schema defines payload field).
* Payload type inferred from schema, required at compile time.
*/
send<S extends ValibotMessageSchema>(schema: S, payload: InferPayload<S>, opts?: SendOptions<S>): InferPayload<S> extends never ? never : boolean;
/**
* Send message without payload (schema has no payload field).
* Payload parameter omitted at compile time.
*/
send<S extends ValibotMessageSchema>(schema: S, opts?: SendOptions<S>): InferPayload<S> extends never ? boolean : never;
/**
* Request/response with typed reply (with payload).
* Payload type inferred from schema, required at compile time.
*/
request<S extends ValibotMessageSchema, R extends ValibotMessageSchema>(schema: S, payload: InferPayload<S>, reply: R, opts?: RequestOptions<S>): InferPayload<S> extends never ? never : Promise<InferMessage<R>>;
/**
* Request/response with typed reply (no payload).
* Payload parameter omitted at compile time.
*/
request<S extends ValibotMessageSchema, R extends ValibotMessageSchema>(schema: S, reply: R, opts?: RequestOptions<S>): InferPayload<S> extends never ? Promise<InferMessage<R>> : never;
/**
* Hook for unhandled message types.
* Receives structurally valid messages with no registered schema.
*/
onUnhandled(cb: (msg: AnyInboundMessage) => void): () => void;
/**
* Hook for non-fatal internal errors.
* Fires for: parse failures, validation failures, queue overflow.
*/
onError(cb: (error: Error, context: {
type: "parse" | "validation" | "overflow" | "unknown";
details?: unknown;
}) => void): () => void;
}
/**
* Create typed WebSocket client with Valibot schema inference.
*
* Pure type cast - zero runtime overhead compared to generic client.
* All type safety is compile-time only via TypeScript inference.
*
* @example
* ```typescript
* import * as v from "valibot";
* import { createMessageSchema } from "bun-ws-router/valibot";
* import { createClient } from "bun-ws-router/valibot/client";
*
* const { messageSchema } = createMessageSchema(v);
* const HelloOk = messageSchema("HELLO_OK", { text: v.string() });
*
* const client = createClient({ url: "wss://api.example.com" });
*
* client.on(HelloOk, (msg) => {
* // ✅ msg fully typed: { type: "HELLO_OK", meta: {...}, payload: { text: string } }
* console.log(msg.payload.text.toUpperCase());
* });
* ```
*
* @see specs/client.md - Full client API documentation
* @see specs/adrs.md#ADR-002 - Type override implementation details
*/
export declare function createClient(opts: ClientOptions): ValibotWebSocketClient;
//# sourceMappingURL=client.d.ts.map