--- url: 'https://ws-asyncapi.github.io/documentation/api.md' --- # ws-asyncapi API ## Modules * [client](client/index.md) * [core](core/index.md) * [cursors](cursors/index.md) * [emitter](emitter/index.md) * [query-core](query-core/index.md) * [react](react/index.md) * [solid](solid/index.md) * [testing](testing/index.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/introduction.md' --- # Why ws-asyncapi **ws-asyncapi** is a contract-first WebSocket framework for TypeScript. You declare a **channel** once on the server, and the browser client is fully typed from that same declaration — every event, command, RPC, stream, and presence shape flows end to end with no `any` and no manual codegen step. The thesis in one line: **Socket.IO's runtime + tRPC-grade end-to-end types + AsyncAPI docs.** ## The gap it fills If you reach for raw WebSockets, you write your own message framing, reconnection, acknowledgements, rooms, and you hand-maintain the types on both ends. If you reach for [Socket.IO](https://socket.io), you get a great runtime — rooms, acks, reconnection, horizontal scaling — but the contract between client and server is untyped strings and payloads. If you reach for [tRPC](https://trpc.io), you get beautiful end-to-end types, but it's request/response over HTTP, not a live bidirectional socket with events, streams, and presence. ws-asyncapi takes the runtime you'd want from Socket.IO and the type-safety you'd want from tRPC, and derives **both** — plus an [AsyncAPI 3.0](https://www.asyncapi.com) document — from a single source of truth. ## What you get * **End-to-end types from one contract.** `createClient()` infers the entire client surface. No build step, no generated files in your repo. * **RPC with acknowledgements.** `await client.request(...)` resolves with a typed output or rejects with a typed, discriminated error. Timeouts and idempotency keys are built in. * **Server streams.** Declare an async generator on the server; consume it with `for await` on the client. Backpressure and cancellation handled for you. * **Typed presence & history.** A per-room roster of who's connected and their typed state, plus per-room event history/rewind for backlogs. * **Live cursors.** A volatile presence path plus the opt-in [`@ws-asyncapi/cursors`](/guides/presence-cursors) package for smoothed multiplayer cursors. * **Resilience.** Auto-reconnect with backoff and jitter, heartbeats, offline buffering, and connection-state recovery (replay of missed events). * **Scale-out.** A pluggable backplane — in-memory for a single node, Redis for a cluster — powers rooms, presence, and recovery across instances. * **Framework bindings.** Thin [React and Solid](/guides/react-solid) bindings over a framework-agnostic `query-core` map RPCs onto TanStack Query and bridge presence/streams into hooks and signals. ## How it fits together ``` ┌──────────────────────────────────────────────┐ │ Channel (the contract: events, RPC, streams,│ │ presence, history, auth) │ └───────────────┬──────────────────┬───────────┘ │ │ infers │ │ emits createClient │ AsyncAPI 3.0 doc → CLI codegen │ │ ┌───────────────────▼──┐ ┌─────▼───────────────────┐ │ Typed browser client │ ⇄ WS ⇄ │ Adapter (Node / Elysia)│ │ events · request · │ │ + Backplane │ │ stream · presence │ │ (local / Redis) │ └───────────────────────┘ └─────────────────────────┘ ``` * A **`Channel`** is the contract. It's a chainable builder: `.serverMessage()`, `.clientMessage()`, `.rpc()`, `.stream()`, `.presence()`, `.history()`, `.onAuth()`. * An **adapter** hosts channels on a server runtime ([`@ws-asyncapi/adapter-node`](/get-started) or `@ws-asyncapi/adapter-elysia`). * A **backplane** fans messages across nodes and stores rooms/presence/history (in-memory by default, Redis for clusters). * The **client** (`@ws-asyncapi/client`) is a single framed dispatcher with a pending table, reconnection, and recovery — typed entirely from the contract. ## When to use it Reach for ws-asyncapi when you want a **live, bidirectional, typed** channel: chat and collaboration, multiplayer presence and cursors, live dashboards and tickers, notifications, or any feature where the server pushes typed data and the client makes typed calls back. If all you need is request/response, plain tRPC or REST is simpler. If you need shared, mergeable editable documents (CRDTs), pair ws-asyncapi as the transport with a CRDT library — see the [presence & cursors guide](/guides/presence-cursors) for where presence ends and CRDTs begin. ## Next steps * [**Get started**](/get-started) — stand up a server and a typed client in a few minutes. * [**Channels & the contract**](/guides/channels-contract) — the full builder surface and the codegen path. * [**RPC & acknowledgements**](/guides/rpc) — typed calls, errors, timeouts, idempotency. * [**Presence & live cursors**](/guides/presence-cursors) — rosters, volatile updates, smoothed cursors. * [**React & Solid bindings**](/guides/react-solid) — hooks and signals over TanStack Query. --- --- url: 'https://ws-asyncapi.github.io/documentation/get-started.md' --- # Get started This guide takes you from nothing to a typed, bidirectional WebSocket in a few minutes. You'll define a **channel** (the contract), serve it on Node, and connect a client whose types come straight from that channel — no codegen. ## Prerequisites * Node.js 18+ or [Bun](https://bun.sh) * A TypeScript project ## 1. Install You need the core, the Node adapter, the client, and a validator. We'll use [zod](https://zod.dev) here. ::: pm-add ws-asyncapi @ws-asyncapi/adapter-node @ws-asyncapi/client zod ::: ::: tip Prefer valibot or arktype? Any [Standard Schema](https://standardschema.dev) validator works — see [Channels & the contract](/guides/channels-contract#validators). Stick with zod for this tutorial. ::: ## 2. Define the contract A `Channel` is a chainable builder. The first argument is the connection path (each channel is its own WebSocket route); the second is its name. ```ts // server.ts import { Channel } from "ws-asyncapi"; import { z } from "zod"; export const chat = new Channel("/chat/:room", "chat") // server → client event (fire-and-forget) .serverMessage("message", z.object({ from: z.string(), text: z.string() })) // client → server RPC: handler returns the typed reply .rpc( "send", z.object({ text: z.string() }), z.object({ id: z.string() }), async ({ message, ws }) => { const id = crypto.randomUUID(); // broadcast to everyone subscribed to this room ws.publish("room", "message", { from: "you", text: message.text }); return { id }; }, ) // subscribe each new connection to the room topic .onOpen(({ ws }) => ws.subscribe("room")); ``` ::: tip Export the channel value Export `chat` so the client can import its **type** with `import type { chat } from "./server"`. Only the type crosses the boundary — no server code ends up in your client bundle. ::: ## 3. Serve it The Node adapter hosts one or more channels and returns a handle you can close. ```ts // server.ts (continued) import { createNodeWsServer } from "@ws-asyncapi/adapter-node"; createNodeWsServer([chat], { port: 3000 }); console.log("ws-asyncapi listening on :3000"); ``` Run it with [Bun](https://bun.sh) (which runs TypeScript directly): ```bash bun server.ts ``` You should see `ws-asyncapi listening on :3000`. ## 4. Connect a typed client `createClient` infers the whole surface from the contract. ```ts // client.ts import { createClient } from "@ws-asyncapi/client"; import type { chat } from "./server"; const client = createClient( "ws://localhost:3000", "/chat/general", // must match the channel's path pattern ); // typed event subscription client.onEvent("message", (m) => { // m: { from: string; text: string } console.log(`${m.from}: ${m.text}`); }); // typed RPC — resolves with { id: string } const { id } = await client.request("send", { text: "hello!" }); console.log("sent", id); ``` That's it. The client reconnects automatically, heartbeats to detect dead connections, buffers outgoing calls while offline, and recovers missed events on reconnect — all on by default. ## What just happened * The **channel** is the single source of truth. The server validates every inbound payload against it; the client's types are inferred from it. * `serverMessage` declares a **server → client event**; `rpc` declares a **client → server call with a typed reply**. (`clientMessage` declares a fire-and-forget **command** — no reply.) * `ws.publish(topic, event, data)` fans an event out to everyone subscribed to a topic via the **backplane** (in-memory here; swap in Redis to scale out). ## Next steps * [**Channels & the contract**](/guides/channels-contract) — every builder method, path params, validators, and the AsyncAPI/codegen path. * [**RPC & acknowledgements**](/guides/rpc) — typed errors, `safeRequest`, timeouts, idempotency, and server → client RPC. * [**Presence & live cursors**](/guides/presence-cursors) — rosters and smoothed cursors. * [**React & Solid bindings**](/guides/react-solid) — use it from a UI framework. --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/channels-contract.md' --- # Channels & the contract A **`Channel`** is the contract between server and client. It's a chainable builder; each method adds a typed capability and returns a new, widened channel type. The same value drives server-side validation, the client's inferred types, and an emitted AsyncAPI 3.0 document. Each channel is its **own WebSocket route** (path-per-channel — no multiplexing). ```ts import { Channel } from "ws-asyncapi"; import { z } from "zod"; export const chat = new Channel("/chat/:room", "chat"); // ^ path pattern ^ name ``` ## Path parameters Path params (`:room`) are captured and available to handlers. The client must connect to a concrete path that matches the pattern. ```ts const channel = new Channel("/doc/:id", "doc"); // client connects to "/doc/42" ``` ## Declaring messages | Method | Direction | Reply? | On the client | | --- | --- | --- | --- | | `.serverMessage(name, schema)` | server → client | — | `client.onEvent(name, cb)` | | `.clientMessage(name, handler, schema)` | client → server | no | `client.call(name, data)` | | `.rpc(name, in, out, handler, errors?)` | client → server | yes | `await client.request(name, in)` | | `.serverRpc(name, in, out)` | server → client | yes | `client.onRequest(name, handler)` | | `.stream(name, in, out, handler)` | server → client (many) | — | `for await (… of client.stream(name, in))` | ```ts export const chat = new Channel("/chat/:room", "chat") .serverMessage("message", z.object({ from: z.string(), text: z.string() })) .clientMessage( "typing", ({ ws, message }) => ws.publish("room", "typing", message), z.object({ on: z.boolean() }), ) .rpc( "send", z.object({ text: z.string() }), z.object({ id: z.string() }), async ({ message }) => ({ id: crypto.randomUUID() }), ); ``` Names must be unique across `serverMessage` / `clientMessage` / `rpc` / `serverRpc` / `stream` within a channel — the builder rejects collisions when the AsyncAPI document is generated. ## Validators Any [Standard Schema](https://standardschema.dev) validator works — zod, valibot, arktype. The schema's **input** shape validates inbound payloads; its **output** (parsed) shape is what handlers and the client see, so transforms and defaults flow through. ## Connection lifecycle & context ```ts new Channel("/chat/:room", "chat") .onOpen(({ ws, request }) => ws.subscribe("room")) .onClose(({ ws }) => {/* cleanup */}) // accumulate typed context (auth, db handles, per-connection state) .derive(({ request }) => ({ userId: request.query.token ?? "anon" })) .resolve(async ({ userId }) => ({ user: await loadUser(userId) })); ``` `.derive()` / `.resolve()` add fields to the context object every handler receives (Elysia-style). Use them for auth, dependency injection, and per-connection state. See [RPC & acknowledgements](/guides/rpc) for how errors in this pipeline surface to callers. ## Plugins (`.use`) `channel.use(plugin)` applies a function `(channel) => extended channel`. Since every builder method threads the channel's generics, the plugin's return type *is* the widened channel — so a plugin can package reusable setup (context, hooks, even contract additions) as a unit. **Inline** (fully typed for any contribution): ```ts const chat = new Channel("/chat/:room", "chat") .use((c) => c.derive(({ request }) => ({ token: request.query.token }))) .use((c) => c.serverMessage("message", z.object({ text: z.string() }))); ``` **Reusable hook plugins** (rate-limit, logging, metrics, guards) compose by reference with full typing — they use `.beforeMessage`/`.onError`/`.onOpen`/ `.onClose`, which return the same channel type: ```ts const rateLimit = (opts: { max: number }) => (c: C) => c.beforeMessage(({ ws }) => { if (over(ws.id, opts)) throw new RpcError("OVERLOADED", "slow down"); }); channel.use(rateLimit({ max: 100 })); ``` **Reusable context/contract plugins** — to package reusable *context or contract* (a `derive`d user, an `rpc`, events) and keep full typing, author the plugin as a **channel** built on a base, and `.use()` it. Its contributions are merged into the host with complete inference: ```ts // a reusable plugin, authored as a channel const auth = new Channel("/", "auth") .derive(() => ({ user: getUser() })) .rpc("login", z.object({ pw: z.string() }), z.object({ ok: z.boolean() }), async () => ({ ok: true })) .serverMessage("kicked", z.object({ reason: z.string() })); const chat = new Channel("/chat/:room", "chat") .serverMessage("message", z.object({ text: z.string() })) .use(auth); // ← `user`, the `login` rpc, and the `kicked` event are all merged + typed ``` Merging combines events/commands/rpc/server-rpc/streams and derived context (plugin contributions run after the host's); single lifecycle hooks compose; `presence`/`auth`/`query`/`headers` are adopted only if the host hasn't set them. ::: tip Which form? **Inline** (`c => c....`) and **channel** (`new Channel(...).…`) plugins are both fully typed for any contribution. The **reusable function** form (`(c: C) => c.…`) is fully typed only for hook-only plugins (rate-limit, logging) — for reusable *context/contract*, use the channel form above. ::: **Named, idempotent plugins** — wrap a plugin with `definePlugin` to give it a stable name; `.use()` then applies it **at most once** per channel, so a shared sub-plugin used by several plugins runs a single time: ```ts import { definePlugin } from "ws-asyncapi"; const withCors = definePlugin({ name: "app/cors", setup: (c) => c.onOpen(({ ws }) => {/* … */}), }); channel.use(withCors).use(withCors); // setup runs once ``` **Server-level plugins** — for cross-channel infrastructure (metrics, tracing, audit logging) that observes rather than shapes the contract, pass a `ServerPlugin` to the adapter. It taps the lifecycle of every channel (`onConnection`/`onDisconnect`/`onMessage`/`onError`), fire-and-forget and isolated: ```ts import type { ServerPlugin } from "ws-asyncapi"; const metrics: ServerPlugin = { onConnection: ({ channel, socketId }) => {/* … */}, onMessage: ({ channel, kind, name }) => {/* … */}, onError: ({ channel, error }) => {/* … */}, }; createNodeWsServer([chat, board], { port: 3000, plugins: [metrics] }); ``` ## Presence, history & auth These are covered in depth in their own guides, but they're declared on the same builder: ```ts new Channel("/doc/:id", "doc") // typed per-room presence roster .presence(z.object({ name: z.string(), cursor: z.object({ x: z.number(), y: z.number() }).nullable() })) // retain the last 50 "message" events per room for rewind/backlog .history("message", { keep: 50 }) // mid-connection credential refresh (token rotation without a reconnect) .onAuth(z.object({ token: z.string() }), ({ credentials }) => ({ userId: verify(credentials.token) })); ``` See [Presence & live cursors](/guides/presence-cursors) for the roster and cursor APIs. ## Two ways to get a typed client ### Inference (recommended) `createClient()` infers the entire client surface directly from the channel value's type. No build step, nothing generated into your repo. ```ts import { createClient } from "@ws-asyncapi/client"; import type { chat } from "./server"; const client = createClient("ws://localhost:3000", "/chat/general"); ``` ### AsyncAPI + CLI codegen Every channel also produces a standard **AsyncAPI 3.0** document, and the CLI generates an equivalent typed client from it. Use this when client and server live in separate repos, or when you want a published, language-agnostic contract. ```ts import { getAsyncApiDocument } from "ws-asyncapi"; const doc = getAsyncApiDocument([chat]); // serve `doc` at e.g. GET /asyncapi.json ``` ```bash # generate a typed client from a running server's document bunx @ws-asyncapi/cli http://localhost:3000/asyncapi.json ``` The generated client is typed for the **full** surface — events, commands, RPC, server-RPC, streams, auth credentials, presence state, and history — matching the inference path. ## Next * [**RPC & acknowledgements**](/guides/rpc) * [**Presence & live cursors**](/guides/presence-cursors) * [**React & Solid bindings**](/guides/react-solid) --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/rpc.md' --- # RPC & acknowledgements An **RPC** is a client → server call that returns a typed reply — the acknowledgement Socket.IO makes you wire up by hand, but fully typed. Declare it with `.rpc(name, inputSchema, outputSchema, handler, errors?)`. ```ts // server.ts import { Channel, RpcError } from "ws-asyncapi"; import { z } from "zod"; export const api = new Channel("/api", "api").rpc( "transfer", z.object({ to: z.string(), amount: z.number().positive() }), z.object({ balance: z.number() }), async ({ message }) => { if (message.amount > balanceOf("me")) throw new RpcError("INSUFFICIENT_FUNDS", "not enough", { short: message.amount - balanceOf("me"), }); return { balance: debit("me", message.amount) }; }, // declared, recoverable error codes → typed `data` per code { INSUFFICIENT_FUNDS: z.object({ short: z.number() }) }, ); ``` ## Calling it ```ts const client = createClient("ws://localhost:3000", "/api"); const { balance } = await client.request("transfer", { to: "bob", amount: 10 }); // ^ number — inferred from the output schema ``` `request` resolves with the typed output or **throws** on failure. The input is validated on the server before the handler runs (a failure throws a `VALIDATION` error). ## Handling errors without try/catch — `safeRequest` `safeRequest` returns a discriminated result you narrow on `error`, so typed error `data` is reachable without exceptions: ```ts const res = await client.safeRequest("transfer", { to: "bob", amount: 999 }); if (res.error) { if (res.error.code === "INSUFFICIENT_FUNDS") { // res.error.data: { short: number } ← narrowed by the code toast(`You're short ${res.error.data.short}`); } } else { // res.data: { balance: number } console.log(res.data.balance); } ``` Every result also carries the built-in runtime codes — `VALIDATION`, `NOT_FOUND`, `INTERNAL`, `TIMEOUT`, `OVERLOADED` — with `data: unknown`. ## Timeouts Calls reject with a `TIMEOUT` error (synthesized client-side) if no reply arrives in time. The default is 30s; override per call: ```ts await client.request("transfer", input, { timeout: 5_000 }); ``` ## Idempotency Pass a stable `idempotencyKey` so a retried call (e.g. after a reconnect) runs the handler **once** and replays the cached result to duplicates — side effects don't happen twice. ```ts await client.request("transfer", input, { idempotencyKey: `transfer:${operationId}`, }); ``` Generate one key per logical action and reuse it across retries. ## Errors from the context pipeline Errors thrown in `.derive()` / `.resolve()` (for example, failed auth) surface to the caller as RPC errors too. Throw an `RpcError` with a declared code to give callers typed `data`; throw anything else and the caller sees `INTERNAL`. ## Server → client RPC Sometimes the **server** needs to ask the **client** a question and await a typed reply — declare it with `.serverRpc(name, input, output)`: ```ts // contract new Channel("/agent", "agent").serverRpc( "whoAreYou", z.object({}), z.object({ name: z.string() }), ); ``` ```ts // client answers client.onRequest("whoAreYou", async () => ({ name: "Alice" })); ``` The server calls it through its socket handle and awaits the typed `{ name }`. ## Next * [**Channels & the contract**](/guides/channels-contract) — the full builder surface. * [**Presence & live cursors**](/guides/presence-cursors) — live multiplayer state. * [**React & Solid bindings**](/guides/react-solid) — RPCs as TanStack Query queries/mutations. --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/auth.md' --- # Authentication Auth in ws-asyncapi rides on the same typed context pipeline as everything else. There are two moments: **connect time** (who is this?) and **mid-connection** (refresh a token without dropping the socket). ## Connect-time auth Read the upgrade request's `query`/`headers` in `.derive` (sync) or `.resolve` (async) and merge the identity into context. Throwing rejects the connection. ```ts import { Channel, RpcError } from "ws-asyncapi"; import { z } from "zod"; export const app = new Channel("/app", "app") .resolve(async ({ request }) => { const user = await verifyJwt(request.query.token); if (!user) throw new RpcError("UNAUTHENTICATED", "bad token"); return { user }; // now available to every handler }) .rpc("me", z.object({}), z.object({ id: z.string() }), async ({ user }) => ({ id: user.id, })); ``` The client passes credentials via the `query` option: ```ts createClient("ws://localhost:3000", "/app", { query: { token } }); ``` ::: tip Browser headers Browsers can't set WebSocket request headers, so prefer `query` in the browser. Validate the shape with `.query(schema)` / `.headers(schema)` — any [Standard Schema](https://standardschema.dev) validator works. ::: ## Per-message guards `.beforeMessage` runs before every inbound command/RPC — the place for authorization, rate-limiting, and logging. Throw an `RpcError` to reject; on an RPC it becomes a typed error reply, on a fire-and-forget command it surfaces via `.onError`. ```ts new Channel("/app", "app") .resolve(async ({ request }) => ({ user: await getUser(request.query.token) })) .beforeMessage(({ data }) => { if (!data.user) throw new RpcError("UNAUTHORIZED", "sign in first"); }); ``` ## Mid-connection token refresh A WebSocket outlives its bearer token. `.onAuth` lets a client swap credentials on a **live** connection — no reconnect — re-running validation and updating context. ```ts // server new Channel("/app", "app").onAuth( z.object({ token: z.string() }), ({ credentials }) => { const claims = verifyJwt(credentials.token); if (!claims) throw new RpcError("UNAUTHENTICATED", "expired"); return { userId: claims.sub }; // merged into the LIVE connection context }, ); ``` ```ts // client — refresh before the old token expires await client.authenticate({ token: freshToken }); // resolves on accept; throws a typed RpcError on reject ``` Returned fields merge into the live connection context, so all later command/RPC/stream handlers see the new identity. The last accepted credentials are re-sent automatically after a reconnect, so the refreshed identity survives drops. ## Authorization & rooms Rooms are fully server-controlled — a client can't subscribe itself. Per-room authorization is therefore expressible directly in your handlers: only `ws.subscribe(topic)` a socket to topics it may access (in `.onOpen`, or after a successful `.authenticate`). The default rejection code is `UNAUTHENTICATED`; throw your own `RpcError(code, msg, data)` for typed, declared errors. ## Next * [**Channels & the contract**](/guides/channels-contract) — `derive`/`resolve`, context * [**RPC & acknowledgements**](/guides/rpc) — typed errors * [**Presence & live cursors**](/guides/presence-cursors) --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/presence-cursors.md' --- # Presence & live cursors **Presence** is a per-room roster of who's connected and their typed state — "Alice and Bob are here, Alice is typing." **Live cursors** are a specialization of presence for the high-frequency case of broadcasting pointer positions. ## Declaring presence Add `.presence(stateSchema)` to a channel. Each connection belongs to one **presence room**, derived server-side from the connection's concrete address (`/doc/:id` → `#presence:/doc/42`), so the client never names the room. ```ts // server.ts import { Channel } from "ws-asyncapi"; import { z } from "zod"; export const board = new Channel("/board/:id", "board").presence( z.object({ name: z.string(), cursor: z.object({ x: z.number(), y: z.number() }).nullable(), }), ); ``` ## The client roster `client.presence` is typed by your schema: ```ts const client = createClient("ws://localhost:3000", "/board/1"); // announce yourself — resolves once the server returns the current roster await client.presence.set({ name: "Alice", cursor: null }); // observe the roster live (fires on every join/leave/update) const off = client.presence.subscribe((members) => { // members: Map render([...members.values()]); }); // read the cached roster synchronously client.presence.get(); // leave presence (stay connected); others get a leave diff await client.presence.clear(); ``` The last announced state is re-sent automatically after a reconnect, so a member's presence survives a brief drop. ## Volatile updates — the cursor hot path `presence.set` is acknowledged and reconciled — right for join/leave and occasional state changes. For something that fires dozens of times a second (a cursor), use **`presence.update`**: ```ts client.presence.update({ cursor: { x: e.clientX, y: e.clientY } }); ``` `update` is fire-and-forget, last-write-wins, **dropped while offline** (a stale cursor is useless), and merges into the last-known state so other fields are preserved. Coalesce it to a sane wire rate with `presenceThrottle`: ```ts const client = createClient("ws://localhost:3000", "/board/1", { presenceThrottle: 50, // ~20 Hz on the wire; the receiver smooths between samples }); ``` ## Live cursors with `@ws-asyncapi/cursors` The general presence primitives above are deliberately opinion-free. The opt-in [`@ws-asyncapi/cursors`](https://github.com/ws-asyncapi) package turns the incoming roster into a smoothed `Map` of everyone else's cursor, ready to render. ::: pm-add @ws-asyncapi/cursors ::: ```ts import { cursorsStore } from "@ws-asyncapi/cursors"; // others' cursors, smoothed to ~60fps even though the wire rate is ~20Hz const cursors = cursorsStore(client); // Subscribable> cursors.subscribe(() => paint(cursors.getSnapshot())); // yourself excluded ``` Send your own pointer with the volatile primitive: ```ts window.addEventListener("pointermove", (e) => client.presence.update({ cursor: { x: e.clientX, y: e.clientY } }), ); ``` ### How it updates `presence.update` coalesces to the latest per throttle window → one volatile diff to the server (validate → last-write store → fan out, no ack) → the receiver's `cursorsStore` feeds each peer's point into a smoother whose `requestAnimationFrame` loop emits interpolated positions → a fresh `Map` snapshot → your render. Cursors are ephemeral: never persisted, never replayed on reconnect. ### Smoothing The default is a zero-dependency rAF lerp (degrades to passthrough without `requestAnimationFrame`, e.g. SSR). Swap it: ```ts cursorsStore(client, { smoothing: false }); // raw last-write import { PerfectCursor } from "perfect-cursors"; // your install — optional cursorsStore(client, { smoothing: (cb) => new PerfectCursor(cb) }); ``` `perfect-cursors` already matches the smoother interface (`{ addPoint([x, y]); dispose() }`), so it drops in without being a dependency. In React/Solid, bind the store with the generic `useStore` / `fromStore` hook — see [React & Solid bindings](/guides/react-solid). ## History & rewind Related but distinct: `.history(eventName, { keep })` retains recent events of a room so a (re)connecting client can fetch a backlog (e.g. the chat scrollback). ```ts // server: retain the last 50 "message" events per room new Channel("/chat/:room", "chat") .serverMessage("message", z.object({ from: z.string(), text: z.string() })) .history("message", { keep: 50 }); ``` ```ts // client: fetch the backlog when opening a room const recent = await client.history("room:42", { limit: 50 }); for (const entry of recent) { if (entry.event === "message") { // entry.data: { from: string; text: string } — discriminated on entry.event } } ``` ## Presence vs CRDTs Presence is an ephemeral, last-write-wins map — perfect for cursors, selections, and "who's online." It is **not** a merge engine for shared editable documents. For collaboratively edited content (rich text, structured docs), use a CRDT library like [Yjs](https://yjs.dev) for the document and ws-asyncapi as the transport; keep cursors and selections in presence. Yjs "awareness" is itself just an ephemeral last-write map — which is exactly what presence already gives you. ## Next * [**React & Solid bindings**](/guides/react-solid) — presence and cursors as hooks/signals. * [**Channels & the contract**](/guides/channels-contract) — where `.presence` and `.history` fit. --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/react-solid.md' --- # React & Solid bindings The framework bindings are thin layers over a shared, framework-agnostic `@ws-asyncapi/query-core`. RPCs map onto [TanStack Query](https://tanstack.com/query) (`useQuery` / `useMutation`); presence, streams, events, and connection state are exposed as reactive stores that each binding bridges into its native primitive (React hooks via `useSyncExternalStore`, Solid signals). ## React ::: pm-add @ws-asyncapi/react @tanstack/react-query ::: Create one client per app and wrap your tree in a `QueryClientProvider`: ```tsx // ws.ts import { createReactClient } from "@ws-asyncapi/react"; import type { chat } from "./server"; export const ws = createReactClient( "ws://localhost:3000", "/chat/general", ); ``` ```tsx // App.tsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const qc = new QueryClient(); export default function App() { return ( ); } ``` ```tsx // Room.tsx import { ws } from "./ws"; function Room() { // RPC as a query — typed input & output, cached by TanStack Query const history = ws.useHistory("room:general", { liveEvent: "message", limit: 50 }); // RPC as a mutation const send = ws.useMutate("send"); // presence roster const { members, set, update } = ws.usePresence(); // a server → client event, latest value const lastTyping = ws.useLastEvent("typing"); return ( ); } ``` The React surface: | Hook | Purpose | | --- | --- | | `useRequest(name, input, opts?)` | RPC as a TanStack query | | `useMutate(name, opts?)` | RPC as a TanStack mutation | | `useStream(name, input, opts?)` | consume a stream (latest value by default; `{ reduce: "append" }` to accumulate) | | `usePresence()` | `{ members, self, set, update, clear }` | | `useHistory(room, opts?)` | room backlog (with optional `liveEvent` to append live) | | `useLastEvent(name)` | latest payload of a server event | | `useEvent(name, handler)` | imperative event subscription | | `useConnection()` | `{ connected, recovered }` | | `useStore(store)` | bind **any** `Subscribable` (e.g. cursors) to a React value | ## Solid ::: pm-add @ws-asyncapi/solid @tanstack/solid-query ::: Same shape, Solid primitives. Methods are `create*` and return accessors: ```tsx import { createSolidClient } from "@ws-asyncapi/solid"; import type { chat } from "./server"; export const ws = createSolidClient("ws://localhost:3000", "/chat/general"); function Room() { const history = ws.createRequest("history", { limit: 50 }); // history.data is reactive const presence = ws.createPresence(); // presence.members() return
{presence.members().size} online
; } ``` The Solid surface mirrors React: `createRequest`, `createMutate`, `createStream`, `createPresence`, `createHistory`, `createLastEvent`, `createEvent`, `createConnection`, and `fromStore` (bind any `Subscribable` into an `Accessor`). ## Streams `useStream` / `createStream` default to the **latest value** (O(1), no accumulation) — ideal for a price ticker or live gauge: ```tsx const price = ws.useStream("prices", { symbol: "ACME" }); // price.data: latest item | undefined ``` Opt into accumulation when you need the list: ```tsx const feed = ws.useStream("events", {}, { reduce: "append", max: 200 }); // feed.data: Item[] ``` ## Binding cursors (and any custom store) [`@ws-asyncapi/cursors`](/guides/presence-cursors) exposes a `Subscribable` store. Bind it with the generic `useStore` / `fromStore` — no cursor-specific hook needed, keeping the bindings opinion-free: ```tsx import { useStore } from "@ws-asyncapi/react"; import { cursorsStore } from "@ws-asyncapi/cursors"; import { useMemo } from "react"; function Cursors() { const cursors = useStore(useMemo(() => cursorsStore(ws.client), [])); return ( <> {[...cursors].map(([id, { x, y }]) => ( ))} ); } ``` `ws.client` is the underlying, precisely-typed client — the escape hatch for anything the hooks don't wrap (`opened`, raw `request`, `presence.update`, …). ## Other frameworks Both bindings are thin wrappers over **`@ws-asyncapi/query-core`** — plain functions and small `{ subscribe, getSnapshot }` stores, since [`@tanstack/query-core`](https://tanstack.com/query) powers React, Solid, Vue, Svelte, and Angular alike. To wire ws-asyncapi into a framework without a binding yet, map query-core's pieces onto that framework's primitives: * **Option factories** → its `useQuery`/`useMutation`: `requestQueryOptions`, `mutationOptions`, `historyQueryOptions`. * **Stores** → its external-store hook (`useSyncExternalStore`, Solid's `from`, …): `presenceStore`, `streamStore`, `lastEventStore`, `connectionStore`. * **Live cache glue**: `subscribeHistoryLive` appends incoming events into a history query's cache entry. `@ws-asyncapi/react` is the reference implementation. You rarely install query-core directly — reach for it only when writing a new binding. ## Next * [**Presence & live cursors**](/guides/presence-cursors) — the store these hooks bind. * [**RPC & acknowledgements**](/guides/rpc) — what `useRequest` / `useMutate` call. --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/adapters.md' --- # Adapters An **adapter** runs your channels over a real WebSocket server. The protocol lives in `ws-asyncapi`'s shared, transport-agnostic dispatcher, so every adapter behaves **identically** — RPC, rooms, presence, history, middleware, codecs, and connection-state-recovery all work the same way. Pick the adapter that matches your runtime. | Adapter | Package | Built on | | --- | --- | --- | | Node | `@ws-asyncapi/adapter-node` | [`ws`](https://github.com/websockets/ws) | | Elysia | `@ws-asyncapi/adapter-elysia` | [Elysia](https://elysiajs.com) (Bun) | ## Node adapter ```ts import { z } from "zod"; import { Channel } from "ws-asyncapi"; import { createNodeWsServer } from "@ws-asyncapi/adapter-node"; const chat = new Channel("/chat/:room", "chat") .$typeChannels<`room:${string}`>() .serverMessage("message", z.object({ from: z.string(), text: z.string() })) .onOpen(({ ws }) => ws.subscribe("room:1")); const { wss, drain, close } = createNodeWsServer([chat], { port: 3000 }); ``` ### Attach to an existing HTTP server Run alongside Express/Fastify/`node:http` instead of opening a port: ```ts import { createServer } from "node:http"; const server = createServer(app); // your Express/Fastify app createNodeWsServer([chat], { server }); server.listen(3000); ``` ### Graceful shutdown For zero-downtime deploys, wire `drain()` to `SIGTERM`: it stops accepting connections, sends every client a close `1001` so they reconnect elsewhere, waits up to `graceMs`, then terminates stragglers and closes the backplane. With [connection-state-recovery](/guides/scaling#connection-state-recovery) the reconnect replays anything missed. ```ts process.on("SIGTERM", () => drain(10_000)); ``` ## Elysia adapter ```ts import { Elysia } from "elysia"; import { wsAsyncAPIAdapter } from "@ws-asyncapi/adapter-elysia"; new Elysia() .use(wsAsyncAPIAdapter([chat], { /* codec, backplane, maxPayload, plugins */ })) .listen(3000); ``` ## Options Both adapters take the same options: | Option | Default | Purpose | | --- | --- | --- | | `port` *(node)* | — | Open a server on this port (ignored if `server` is given) | | `server` *(node)* | — | Attach to an existing `node:http` server | | `codec` | JSON | Wire [codec](/guides/scaling#codecs) — must match the client | | `backplane` | `LocalBackplane` | [Scaling backplane](/guides/scaling) (rooms, presence, history) | | `maxPayload` | 1 MiB | Max inbound message bytes; larger frames are rejected with close `1009` before they're buffered (decode-bomb guard) | | `plugins` | — | [Server-level plugins](/guides/channels-contract#plugins-use) (metrics/tracing) | ## Broadcasting from anywhere A channel value can publish to a room from outside any handler — a cron, a webhook, a job queue: ```ts chat.publish("room:1", "message", { from: "clock", text: new Date().toISOString() }); ``` Across multiple server instances, this requires a shared backplane — see [Scaling](/guides/scaling). To emit from a process that **isn't** running a server, use the [external emitter](/guides/scaling#external-emitter). ## Serving the AsyncAPI document & UI Every channel emits a standard AsyncAPI 3.0 document. Serve it (and an interactive UI) from any HTTP route: ```ts import { getAsyncApiDocument, getAsyncApiUI } from "ws-asyncapi"; const doc = getAsyncApiDocument([chat]); // JSON contract → GET /asyncapi.json const html = getAsyncApiUI([chat]); // rendered docs page → GET /docs ``` See [AsyncAPI & codegen](/guides/codegen) for generating a client from this document. ## Next * [**Scaling & the backplane**](/guides/scaling) * [**Testing**](/guides/testing) * [**AsyncAPI & codegen**](/guides/codegen) --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/scaling.md' --- # Scaling & the backplane A single ws-asyncapi server keeps rooms, presence, and history in memory. To run **many** server instances behind a load balancer — so a `publish` on node A reaches a client on node B — they share a **backplane**. The backplane is the one seam that fans messages across nodes and stores rooms, presence, and history. Swap it; everything else stays the same. | Backplane | Package | Scope | | --- | --- | --- | | `LocalBackplane` | `ws-asyncapi` (default) | Single process / in-memory | | `RedisBackplane` | `@ws-asyncapi/backplane-redis` | Cluster-wide (ioredis pub/sub + Redis data structures) | ## Local (default) Nothing to configure — a single instance uses `LocalBackplane`, which powers rooms, presence, history, and recovery on one node. ## Redis backplane Run **identical** server instances behind a load balancer and give each the same Redis. Rooms, presence, history, broadcasts, and admin ops become cluster-wide. ```ts import { createNodeWsServer } from "@ws-asyncapi/adapter-node"; import { RedisBackplane } from "@ws-asyncapi/backplane-redis"; const backplane = new RedisBackplane({ url: "redis://localhost:6379", // or pass `redisOptions` (ioredis) directly recovery: true, // enable connection-state-recovery historyTTL: 3_600_000, // sliding TTL (ms) for per-room history keys }); createNodeWsServer([chat], { port: 3000, backplane }); ``` Under the hood: a single Redis channel fans every frame to all nodes (each delivers locally, skipping the origin); presence is a self-cleaning Redis HASH per room; history is a capped LIST per room with a sliding TTL so idle rooms expire instead of leaking keys. ### Options | Option | Default | Purpose | | --- | --- | --- | | `url` | — | Redis connection URL | | `redisOptions` | — | ioredis options (use instead of `url`) | | `prefix` | `"wsaa"` | Key/channel prefix | | `recovery` | off | Enable recovery (see below) — `{ bufferSize?, sessionTTL? }` | | `historyTTL` | 1h | Sliding TTL (ms) for room `.history` buffers | ## Connection-state-recovery A dropped client can reconnect and **replay the room events it missed** instead of silently losing them. Enable `recovery` on the backplane: ```ts new RedisBackplane({ url: "redis://localhost:6379", recovery: { bufferSize: 10_000, // events retained in the replay log sessionTTL: 120_000, // how long a disconnected session stays recoverable (ms) }, }); ``` Recovery mints a globally-monotonic offset per published event (one `INCR`) and keeps a bounded replay log plus per-session room snapshots. On reconnect, the client re-joins its rooms and receives everything after its last seen offset. The client exposes `client.recovered` and an `onRecover(cb)` hook. Only **room broadcasts** recover — not direct sends. (`LocalBackplane` has recovery on by default, single-node.) ## Codecs The wire format is pluggable. The default is JSON; swap in **MessagePack** for smaller binary frames. The **whole cluster and all clients must share one codec** — it's confirmed in the connection handshake. ```ts import { msgpackCodec } from "@ws-asyncapi/codec-msgpack"; // server createNodeWsServer([chat], { port: 3000, codec: msgpackCodec }); // client createClient(url, path, { codec: msgpackCodec }); ``` ## External emitter To emit events from a process that **isn't** running a server — a background job, a billing service, a cron — use `@ws-asyncapi/emitter` with a backplane shared with your servers (the [`@socket.io/redis-emitter`](https://socket.io/docs/v4/redis-adapter/#emitter) equivalent). The emitter publishes through the backplane; each server delivers to its connected clients. ```ts import { createEmitter } from "@ws-asyncapi/emitter"; import { RedisBackplane } from "@ws-asyncapi/backplane-redis"; import type { chat } from "./contract"; const emitter = createEmitter( new RedisBackplane({ url: "redis://localhost:6379" }), // same Redis as the servers ); // to a room — every client in room:1 across the cluster receives it await emitter.publish("room:1", "message", { from: "billing", text: "paid" }); // to a single socket by id await emitter.toSocket(socketId, "message", { from: "system", text: "hi" }); await emitter.close(); ``` Event names and payloads are inferred from the channel's `serverMessage` declarations, so a wrong name or shape is a compile error. The emitter is **one-way** (emit to rooms/sockets only) — acknowledgements, presence, and inbound messages need a running server. Its `codec` must match the servers'. ## Next * [**Adapters**](/guides/adapters) * [**Presence & live cursors**](/guides/presence-cursors) * [**Testing**](/guides/testing) — simulate multiple cluster nodes in-memory --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/codegen.md' --- # AsyncAPI & codegen Every channel produces a standard **AsyncAPI 3.0** document, and `@ws-asyncapi/cli` generates a typed client from it. Use this path when client and server live in **separate repos**, when the consumer isn't TypeScript, or when you want a published, language-agnostic contract. Otherwise prefer the codegen-free [`createClient`](/guides/channels-contract#inference-recommended). ## Emit the document ```ts import { getAsyncApiDocument, getAsyncApiUI } from "ws-asyncapi"; import { chat } from "./server"; const doc = getAsyncApiDocument([chat]); // serve at e.g. GET /asyncapi.json const html = getAsyncApiUI([chat]); // interactive docs page → GET /docs ``` The document covers the full surface — events, commands, RPC (with typed errors), server-RPC, streams, auth credentials, and presence state — plus a per-channel **contract hash** for drift detection. ## Generate a client Point the CLI at a running server's document: ```bash bunx @ws-asyncapi/cli http://localhost:3000/asyncapi.json # writes generated.ts — a `declare module "@ws-asyncapi/client"` augmentation ``` Import the generated file once (its types augment the client), then use the address-based factory: ```ts import "./generated"; // registers the channel types import { websocketAsyncAPI } from "@ws-asyncapi/client"; const client = websocketAsyncAPI("ws://localhost:3000", "/chat/general"); // same typed surface as createClient: onEvent, request, safeRequest, stream, // authenticate, presence, history ``` ## Which path? | | `createClient` | CLI codegen + `websocketAsyncAPI` | | --- | --- | --- | | Setup | none (import the type) | run the CLI, import `generated.ts` | | Best for | monorepo / shared types | separate repos, polyglot, published contract | | Output in repo | nothing generated | `generated.ts` | Both produce the same precisely-typed client at runtime and type level. ## Next * [**Channels & the contract**](/guides/channels-contract) * [**Adapters**](/guides/adapters) — serving the document & UI * [**AI agents & LLMs**](/guides/ai-agents) — the AsyncAPI doc as machine-readable contract --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/testing.md' --- # Testing `@ws-asyncapi/testing` gives you an **in-memory test harness**: connect a fully-typed client to a channel with **no sockets, no ports, no `listen()`**. It runs the *real* dispatcher and the *real* `WebSocketNode` implementation over an in-memory pipe, so your tests exercise the actual protocol — RPC, typed errors, events, rooms, broadcast, server→client RPC, streams, and connection-state-recovery all behave exactly as in production. ```bash npm install -D @ws-asyncapi/testing # peers: ws-asyncapi, @ws-asyncapi/client, @ws-asyncapi/adapter-node ``` ## Basic test ```ts import { expect, test } from "bun:test"; // or vitest / jest import { createTestHarness } from "@ws-asyncapi/testing"; import { chat } from "./server"; // your Channel test("history RPC", async () => { const h = createTestHarness(chat); const client = h.connect(); // typed client, inferred from `chat` await client.opened; const { items } = await client.request("history", { limit: 10 }); expect(items).toHaveLength(10); await h.close(); }); ``` Everything is typed straight from the channel — `request`, `onEvent`, `call`, `safeRequest`, `stream`, `onRequest` all infer their argument and result types, and wrong names or payloads are compile errors. ## Multiple clients (fan-out, presence) ```ts const h = createTestHarness(chat); const a = h.connect(); const b = h.connect(); await Promise.all([a.opened, b.opened]); const received: unknown[] = []; b.onEvent("message", (m) => received.push(m)); a.call("say", { text: "hi" }); // broadcasts to the room → b receives it ``` ## Streams ```ts for await (const tick of client.stream("prices", { symbol: "ACME" })) { // ... } ``` ## Simulating other cluster nodes The harness drives a real backplane (a fresh `LocalBackplane` with recovery on, by default). Pass a **shared** backplane to test cross-node behavior — or publish through `h.backplane` / point an [external emitter](/guides/scaling#external-emitter) at it. ```ts const h = createTestHarness(chat, { backplane, codec }); // h.backplane — publish to it to simulate events from another node ``` ## Options `createTestHarness(channel, options?)`: | Option | Default | Purpose | | --- | --- | --- | | `codec` | JSON | Wire codec (client and server share it automatically) | | `backplane` | fresh `LocalBackplane` (recovery on) | Share one to simulate a cluster | | `plugins` | — | [Server-level plugins](/guides/channels-contract#plugins-use) (metrics/tracing) | `h.connect(options?)` accepts `{ path?, query?, headers? }` — `path` defaults to the channel address with params filled `1`. ## Next * [**RPC & acknowledgements**](/guides/rpc) * [**Scaling & the backplane**](/guides/scaling) * [**Channels & the contract**](/guides/channels-contract) --- --- url: 'https://ws-asyncapi.github.io/documentation/guides/ai-agents.md' --- # AI agents & LLMs ws-asyncapi is designed to be **legible to language models**. The whole framework is contract-first: one `Channel` declaration is the source of truth for events, commands, RPC, streams, presence, history, and auth — and that same value drives the client's types and a machine-readable AsyncAPI 3.0 document. A model that reads your channel knows your entire wire protocol, and the TypeScript compiler gives it immediate, precise feedback when it writes against that contract. This page covers the three things this project ships for AI-assisted workflows: 1. An installable **agent Skill** that teaches a coding agent the framework. 2. **`llms.txt`** — these docs, packaged for model context. 3. **Copy / download as Markdown** on every page. ## Why ws-asyncapi is AI-friendly * **The contract is the spec.** A `Channel` is a single, compact declaration. Hand it (or its emitted AsyncAPI document) to a model and it has the complete protocol — no scattered string event names to guess at. * **End-to-end types are a feedback loop.** `createClient()` infers the entire client surface with no codegen. When an agent calls `client.request` with the wrong shape, `tsc` rejects it — the model self-corrects instead of shipping a runtime bug. * **AsyncAPI is machine-readable.** `getAsyncApiDocument([channel])` emits standard AsyncAPI 3.0 JSON, which agents and other tools can consume directly. See [Channels & the contract](/guides/channels-contract#asyncapi-cli-codegen). ## The agent Skill The docs repo ships an [Agent Skill](https://agentskills.io) named **`ws-asyncapi`** that teaches a coding agent (Claude Code, and any tool that supports the open Skills format) how to *build apps with* the framework — not how to use the docs site. It activates automatically when the agent sees `ws-asyncapi`/`@ws-asyncapi/*` imports or APIs like `new Channel(`, `createClient(`, `createNodeWsServer(`, and routes the agent to focused references before it writes code: | Reference | Covers | | --- | --- | | `channels` | The full builder — events, commands, rpc, serverRpc, streams, path params, validators, `derive`/`resolve` context, lifecycle, broadcast | | `client` | `createClient`, `request`/`safeRequest`, typed errors, streams, reconnection/heartbeat/recovery, idempotency | | `adapters-scaling` | Node & Elysia adapters, the backplane interface, Redis scaling, msgpack codec, the external emitter | | `presence-cursors` | Typed presence, volatile updates, per-room history, live cursors | | `auth` | `.onAuth` + `client.authenticate` token refresh, auth in `derive`/`resolve` | | `react-solid` | `@ws-asyncapi/react` hooks and `@ws-asyncapi/solid` primitives over TanStack Query (`@ws-asyncapi/query-core`) | | `codegen` | The AsyncAPI 3.0 document and the CLI-generated client (`@ws-asyncapi/cli`) | | `testing` | In-memory test harness (`@ws-asyncapi/testing`) | ### Install it With the [Skills CLI](https://skills.sh) (installs into `~/.claude/skills`): ```bash npx skills add ws-asyncapi/documentation@ws-asyncapi -g ``` Or install manually — copy the skill folder into your skills directory (`~/.claude/skills/` for personal use, or `.claude/skills/` committed to your repo): ```bash git clone https://github.com/ws-asyncapi/documentation cp -r documentation/skills/ws-asyncapi ~/.claude/skills/ws-asyncapi ``` The skill lives at [`skills/ws-asyncapi/`](https://github.com/ws-asyncapi/documentation/tree/main/skills/ws-asyncapi) in the docs repo. Once installed, restart your agent and it will pick the skill up on the next ws-asyncapi task. ## llms.txt These docs are published in the [llms.txt](https://llmstxt.org) format, so you can drop the whole reference into any model's context window: * **** — a structured index of every page with links and summaries (small; good for navigation). * **** — the full docs concatenated into one Markdown file (large; good for "answer only from these docs" prompts). Paste a URL into a chat, attach the file as context, or fetch it in a tool: ```bash curl https://ws-asyncapi.github.io/documentation/llms-full.txt -o ws-asyncapi-docs.md ``` ## Copy & download as Markdown Every page on this site has **Copy** and **Download as Markdown** buttons at the top. Use them to grab a single page as clean Markdown — ideal for pasting the exact guide you need (e.g. [RPC & acknowledgements](/guides/rpc)) into a model rather than the whole corpus. ## Wiring up your tools * **Claude Code** — install the Skill (above); it activates automatically. You can also point it at a page's Markdown or the `llms.txt` URL for one-off questions. * **Cursor** — add the docs as a custom doc source (`@Docs` → add `https://ws-asyncapi.github.io/documentation/`), then reference `@ws-asyncapi` in prompts. For deep context, attach `llms-full.txt`. * **GitHub Copilot / others** — attach `llms-full.txt` (or a per-page Markdown copy) as context, or keep the Skill folder in your repo under `.claude/skills/` so it travels with the project. ## A good agent workflow Let the contract drive the agent: 1. **Write the `Channel` first** (or have the agent draft it). It's small, it's the spec, and it's the one thing reviewers should scrutinize. 2. **Let types do the enforcement.** Ask the agent to build the server handlers and the `createClient()` client against that channel and run `tsc` — mismatches surface immediately, no runtime guessing. 3. **Hand over the AsyncAPI document** (`getAsyncApiDocument([channel])`) when the client lives in a separate repo or stack — it's the language-agnostic contract, and the [CLI](/guides/channels-contract#asyncapi-cli-codegen) regenerates a typed client from it. ## Next * [**Channels & the contract**](/guides/channels-contract) * [**RPC & acknowledgements**](/guides/rpc) * [**Get started**](/get-started) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/classes/WebSocketImplementation.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / WebSocketImplementation # Abstract Class: WebSocketImplementation\ Defined in: .api-entries/core/index.d.ts:15 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` ## Constructors ### Constructor > **new WebSocketImplementation**<`WebsocketData`, `Topics`>(): `WebSocketImplementation`<`WebsocketData`, `Topics`> #### Returns `WebSocketImplementation`<`WebsocketData`, `Topics`> ## Properties ### id > `abstract` `readonly` **id**: `string` Defined in: .api-entries/core/index.d.ts:30 Connection-unique socket id (used for room membership / presence). ## Methods ### send() > `abstract` **send**<`T`>(`type`, ...`data`): `void` Defined in: .api-entries/core/index.d.ts:16 #### Type Parameters ##### T `T` *extends* `string` | `number` | `symbol` #### Parameters ##### type `T` ##### data ...`WebsocketData`\[`"server"`]\[`T`] *extends* `never` ? \[] : \[`WebsocketData`\[`"server"`]\[`T`]] #### Returns `void` *** ### sendFrame() > `abstract` **sendFrame**(`frame`): `void` Defined in: .api-entries/core/index.d.ts:18 Low-level: encode and send any wire frame (used by the dispatcher). #### Parameters ##### frame `any` #### Returns `void` *** ### sendRaw() > `abstract` **sendRaw**(`data`): `void` Defined in: .api-entries/core/index.d.ts:20 Low-level: send already-encoded bytes (used to replay buffered frames). #### Parameters ##### data `string` | `Uint8Array`<`ArrayBufferLike`> #### Returns `void` *** ### request() > `abstract` **request**<`Name`>(`name`, `input`, `options?`): `Promise`<`NonNullable`<`WebsocketData`\[`"serverRpc"`]>\[`Name`]\[`"output"`]> Defined in: .api-entries/core/index.d.ts:26 Server→client RPC: ask this client and await its typed reply. Mirrors the client's `request()` in the other direction. Rejects with an `RpcError` on the client throwing, a timeout, or disconnect. #### Type Parameters ##### Name `Name` *extends* `string` | `number` | `symbol` #### Parameters ##### name `Name` ##### input `NonNullable`<`WebsocketData`\[`"serverRpc"`]>\[`Name`]\[`"input"`] ##### options? ###### timeout? `number` #### Returns `Promise`<`NonNullable`<`WebsocketData`\[`"serverRpc"`]>\[`Name`]\[`"output"`]> *** ### subscribe() > `abstract` **subscribe**(`topic`): `void` Defined in: .api-entries/core/index.d.ts:31 #### Parameters ##### topic `Topics` #### Returns `void` *** ### unsubscribe() > `abstract` **unsubscribe**(`topic`): `void` Defined in: .api-entries/core/index.d.ts:32 #### Parameters ##### topic `Topics` #### Returns `void` *** ### isSubscribed() > `abstract` **isSubscribed**(`topic`): `boolean` Defined in: .api-entries/core/index.d.ts:33 #### Parameters ##### topic `Topics` #### Returns `boolean` *** ### publish() > `abstract` **publish**<`T`>(`topic`, `type`, ...`data`): `void` Defined in: .api-entries/core/index.d.ts:34 #### Type Parameters ##### T `T` *extends* `string` | `number` | `symbol` #### Parameters ##### topic `Topics` ##### type `T` ##### data ...`WebsocketData`\[`"server"`]\[`T`] *extends* `never` ? \[] : \[`WebsocketData`\[`"server"`]\[`T`]] #### Returns `void` *** ### broadcast() > `abstract` **broadcast**<`T`>(`topic`, `type`, ...`data`): `void` Defined in: .api-entries/core/index.d.ts:39 Like [publish](#publish), but excludes this socket from delivery — the Socket.IO `socket.broadcast.to(topic).emit(...)` equivalent. #### Type Parameters ##### T `T` *extends* `string` | `number` | `symbol` #### Parameters ##### topic `Topics` ##### type `T` ##### data ...`WebsocketData`\[`"server"`]\[`T`] *extends* `never` ? \[] : \[`WebsocketData`\[`"server"`]\[`T`]] #### Returns `void` *** ### roomMembers() > `abstract` **roomMembers**(`topic`): `Promise`<`string`\[]> Defined in: .api-entries/core/index.d.ts:41 Cluster-wide socket ids currently in `topic` (presence / fetchSockets). #### Parameters ##### topic `Topics` #### Returns `Promise`<`string`\[]> *** ### close() > `abstract` **close**(`code?`, `reason?`): `void` Defined in: .api-entries/core/index.d.ts:42 #### Parameters ##### code? `number` ##### reason? `string` #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/classes/Channel.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / Channel # Class: Channel\ Defined in: .api-entries/core/index.d.ts:689 ## Type Parameters ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### WebsocketClientData `WebsocketClientData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md)\[`"client"`] = { } ### WebsocketServerData `WebsocketServerData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md)\[`"server"`] = { } ### Topics `Topics` *extends* `string` = `string` ### Path `Path` *extends* `` `/${string}` `` = `` `/${string}` `` ### Params `Params` *extends* `unknown` | `undefined` = [`ExtractRouteParams`](../type-aliases/ExtractRouteParams.md)<`Path`> ### Data `Data` *extends* `unknown` | `undefined` = { } ### RpcMap `RpcMap` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; `errors`: `Record`<`string`, `unknown`>; }> = { } ### ServerRpcMap `ServerRpcMap` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; }> = { } ### StreamMap `StreamMap` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; }> = { } ### AuthCredentials `AuthCredentials` = `undefined` ### PresenceState `PresenceState` = `undefined` ## Constructors ### Constructor > **new Channel**<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`>(`address`, `name`, `schema?`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:757 #### Parameters ##### address `Path` ##### name `string` ##### schema? `ChannelObject` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> ## Properties ### address > **address**: `Path` Defined in: .api-entries/core/index.d.ts:700 *** ### name > **name**: `string` Defined in: .api-entries/core/index.d.ts:701 *** ### schema > **schema**: `ChannelObject` Defined in: .api-entries/core/index.d.ts:702 *** ### ~ > **~**: `object` Defined in: .api-entries/core/index.d.ts:703 #### client > **client**: `Map`<`string`, [`MessageHandlerSchema`](../interfaces/MessageHandlerSchema.md)<[`WebsocketDataType`](../interfaces/WebsocketDataType.md), `Topics`, `any`, `Query`, `Headers`, `Params`, `Data`>> #### server > **server**: `Map`<`string`, [`AnySchema`](../type-aliases/AnySchema.md)> #### rpc > **rpc**: `Map`<`string`, [`RpcDefinition`](../interfaces/RpcDefinition.md)> #### serverRpc > **serverRpc**: `Map`<`string`, [`ServerRpcDefinition`](../interfaces/ServerRpcDefinition.md)> #### stream > **stream**: `Map`<`string`, [`StreamDefinition`](../interfaces/StreamDefinition.md)> #### history > **history**: `Map`<`string`, `number`> #### sockets > **sockets**: `Map`<`string`, [`Connection`](../interfaces/Connection.md)> #### plugins > **plugins**: `Set`<`string`> #### serverPlugins > **serverPlugins**: [`ServerPlugin`](../interfaces/ServerPlugin.md)\[] #### serverEvents > **serverEvents**: `Map`<`string`, (`data`) => `void`> #### sendCommand > **sendCommand**: (`cmd`) => `void` ##### Parameters ###### cmd [`NodeCommand`](../type-aliases/NodeCommand.md) ##### Returns `void` #### query > **query**: [`AnySchema`](../type-aliases/AnySchema.md) #### headers > **headers**: [`AnySchema`](../type-aliases/AnySchema.md) #### onOpen > **onOpen**: [`OnOpenHandler`](../type-aliases/OnOpenHandler.md)<[`WebsocketDataType`](../interfaces/WebsocketDataType.md), `Topics`, `Query`, `Headers`, `Params`, `Data`> #### onClose > **onClose**: [`OnCloseHandler`](../type-aliases/OnCloseHandler.md)<[`WebsocketDataType`](../interfaces/WebsocketDataType.md), `Topics`, `Query`, `Headers`, `Params`, `Data`> #### globalPublish > **globalPublish**: (`topic`, `type`, `message`) => `void` ##### Parameters ###### topic `any` ###### type `any` ###### message `any` ##### Returns `void` #### fetchSockets > **fetchSockets**: (`room?`) => `Promise`<[`RemoteSocketInfo`](../interfaces/RemoteSocketInfo.md)\[]> ##### Parameters ###### room? `string` ##### Returns `Promise`<[`RemoteSocketInfo`](../interfaces/RemoteSocketInfo.md)\[]> #### beforeUpgrade > **beforeUpgrade**: [`BeforeUpgradeHandler`](../type-aliases/BeforeUpgradeHandler.md)<`Query`, `Headers`, `Params`, `Data`> #### derives > **derives**: (`ctx`) => `any`\[] ##### Parameters ###### ctx ###### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> ###### data `any` ##### Returns `any` #### middlewares > **middlewares**: (`ctx`) => `any`\[] ##### Parameters ###### ctx ###### ws `any` ###### type `string` ###### message `any` ###### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> ###### data `any` ##### Returns `any` #### onError > **onError**: (`ctx`) => `void` ##### Parameters ###### ctx ###### ws `any` ###### error `unknown` ###### type `string` ###### data `any` ##### Returns `void` #### publishFrame > **publishFrame**: (`topic`, `frame`, `except?`) => `void` ##### Parameters ###### topic `string` ###### frame `AnyFrame` ###### except? `string`\[] ##### Returns `void` #### presence > **presence**: `object` ##### presence.state > **state**: [`AnySchema`](../type-aliases/AnySchema.md) ##### presence.room > **room**: (`ctx`) => `string` ###### Parameters ###### ctx ###### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> ###### data `any` ###### Returns `string` #### auth > **auth**: `object` ##### auth.credentials > **credentials**: [`AnySchema`](../type-aliases/AnySchema.md) ##### auth.handler > **handler**: (`ctx`) => `any` ###### Parameters ###### ctx ###### ws `any` ###### credentials `any` ###### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> ###### data `any` ###### Returns `any` ## Methods ### query() > **query**<`QueryObject`>(`query`): `Channel`<[`InferOut`](../type-aliases/InferOut.md)<`QueryObject`>, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:758 #### Type Parameters ##### QueryObject `QueryObject` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### query `QueryObject` #### Returns `Channel`<[`InferOut`](../type-aliases/InferOut.md)<`QueryObject`>, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### headers() > **headers**<`HeadersObject`>(`headers`): `Channel`<`Query`, [`InferOut`](../type-aliases/InferOut.md)<`HeadersObject`>, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:759 #### Type Parameters ##### HeadersObject `HeadersObject` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### headers `HeadersObject` #### Returns `Channel`<`Query`, [`InferOut`](../type-aliases/InferOut.md)<`HeadersObject`>, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### serverMessage() > **serverMessage**<`Name`, `Validation`>(`name`, `validation?`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData` & `{ [k in string]: Validation extends AnySchema ? InferOut : never }`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:760 #### Type Parameters ##### Name `Name` *extends* `string` ##### Validation `Validation` *extends* [`AnySchema`](../type-aliases/AnySchema.md) = `undefined` #### Parameters ##### name `Name` ##### validation? `Validation` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData` & `{ [k in string]: Validation extends AnySchema ? InferOut : never }`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### clientMessage() > **clientMessage**<`Name`, `Validation`, `Message`>(`name`, `handler`, `validation?`): `Channel`<`Query`, `Headers`, `WebsocketClientData` & `{ [k in string]: InferIn }`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:763 #### Type Parameters ##### Name `Name` *extends* `string` ##### Validation `Validation` *extends* [`AnySchema`](../type-aliases/AnySchema.md) ##### Message `Message` = [`InferOut`](../type-aliases/InferOut.md)<`Validation`> #### Parameters ##### name `Name` ##### handler [`MessageHandler`](../type-aliases/MessageHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, `Message`, `Query`, `Headers`, `Params`, `Data`> ##### validation? `Validation` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData` & `{ [k in string]: InferIn }`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### rpc() > **rpc**<`Name`, `Input`, `Output`, `Errors`>(`name`, `input`, `output`, `handler`, `errors?`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap` & { \[k in string]: { input: InferIn\; output: InferOut\; errors: { \[C in string | number | symbol]: InferOut\ } } }, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:781 Declares a request/response message (acknowledged RPC). Unlike [clientMessage](#clientmessage) (fire-and-forget), the handler returns a value that is validated against `output` and sent back to the caller as a typed reply. The client awaits it via `client.request(name, input)`. Pass an optional `errors` map (code → `data` schema) to declare expected failures in the contract. The handler throws `new RpcError(code, message, data)`; the generated client surfaces them as a typed, discriminated union via `client.safeRequest(name, input)`. #### Type Parameters ##### Name `Name` *extends* `string` ##### Input `Input` *extends* [`AnySchema`](../type-aliases/AnySchema.md) ##### Output `Output` *extends* [`AnySchema`](../type-aliases/AnySchema.md) ##### Errors `Errors` *extends* `Record`<`string`, [`AnySchema`](../type-aliases/AnySchema.md)> = { } #### Parameters ##### name `Name` ##### input `Input` ##### output `Output` ##### handler [`RpcHandler`](../type-aliases/RpcHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, [`InferOut`](../type-aliases/InferOut.md)<`Input`>, [`InferOut`](../type-aliases/InferOut.md)<`Output`>, `Query`, `Headers`, `Params`, `Data`> ##### errors? `Errors` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap` & { \[k in string]: { input: InferIn\; output: InferOut\; errors: { \[C in string | number | symbol]: InferOut\ } } }, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### serverRpc() > **serverRpc**<`Name`, `Input`, `Output`>(`name`, `input`, `output`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap` & `{ [k in string]: { input: InferIn; output: InferOut } }`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:801 Declares a **server→client** request/response (acknowledged RPC). The server calls it on a connection via `ws.request(name, input)` and awaits the client's typed reply; the client answers it with `client.onRequest(name, (input) => output)`. The reverse direction of [rpc](#rpc). #### Type Parameters ##### Name `Name` *extends* `string` ##### Input `Input` *extends* [`AnySchema`](../type-aliases/AnySchema.md) ##### Output `Output` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### name `Name` ##### input `Input` ##### output `Output` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap` & `{ [k in string]: { input: InferIn; output: InferOut } }`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### stream() > **stream**<`Name`, `Input`, `Output`>(`name`, `input`, `output`, `handler`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap` & `{ [k in string]: { input: InferIn; output: InferOut } }`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:823 Declares a **stream**: the client opens it with `client.stream(name, input)` and consumes a sequence of typed values with `for await`. The handler is an async generator — each `yield` is validated against `output` and pushed to the client as it arrives; returning ends the stream, throwing fails it with a typed error. If the consumer stops iterating (or disconnects), the handler is cancelled (its `signal` aborts and the generator is `return()`-ed, so a `try/finally` can clean up). ```ts .stream("ticks", z.object({}), z.object({ n: z.number() }), async function* ({ signal }) { for (let n = 0; !signal.aborted; n++) { yield { n }; await sleep(1000); } }) ``` #### Type Parameters ##### Name `Name` *extends* `string` ##### Input `Input` *extends* [`AnySchema`](../type-aliases/AnySchema.md) ##### Output `Output` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### name `Name` ##### input `Input` ##### output `Output` ##### handler [`StreamHandler`](../type-aliases/StreamHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, [`InferOut`](../type-aliases/InferOut.md)<`Input`>, [`InferOut`](../type-aliases/InferOut.md)<`Output`>, `Query`, `Headers`, `Params`, `Data`> #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap` & `{ [k in string]: { input: InferIn; output: InferOut } }`, `AuthCredentials`, `PresenceState`> *** ### onOpen() > **onOpen**(`handler`): `this` Defined in: .api-entries/core/index.d.ts:833 #### Parameters ##### handler [`OnOpenHandler`](../type-aliases/OnOpenHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, `Query`, `Headers`, `Params`, `Data`> #### Returns `this` *** ### onClose() > **onClose**(`handler`): `this` Defined in: .api-entries/core/index.d.ts:838 #### Parameters ##### handler [`OnCloseHandler`](../type-aliases/OnCloseHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, `Query`, `Headers`, `Params`, `Data`> #### Returns `this` *** ### publish() > **publish**<`Name`>(`topic`, `name`, ...`message`): `void` Defined in: .api-entries/core/index.d.ts:847 ! Be careful this `public` method does not see to what channel it belongs to. This function can be changed in the near future. #### Type Parameters ##### Name `Name` *extends* `string` #### Parameters ##### topic `Topics` ##### name `Name` ##### message ...`WebsocketServerData`\[`Name`] *extends* `never` ? \[] : \[`WebsocketServerData`\[`Name`]] #### Returns `void` *** ### toSocket() > **toSocket**<`Name`>(`socketId`, `name`, ...`message`): `void` Defined in: .api-entries/core/index.d.ts:853 Send an event to a single socket by id, anywhere in the cluster (the Socket.IO `io.to(socketId).emit(...)` equivalent). Routed through the socket's reserved per-socket room. #### Type Parameters ##### Name `Name` *extends* `string` #### Parameters ##### socketId `string` ##### name `Name` ##### message ...`WebsocketServerData`\[`Name`] *extends* `never` ? \[] : \[`WebsocketServerData`\[`Name`]] #### Returns `void` *** ### fetchSockets() > **fetchSockets**(`room?`): `Promise`<[`RemoteSocketInfo`](../interfaces/RemoteSocketInfo.md)\[]> Defined in: .api-entries/core/index.d.ts:858 List sockets cluster-wide (presence). With `room`, only sockets in that room; otherwise every connected socket. Returns ids + their rooms. #### Parameters ##### room? `Topics` #### Returns `Promise`<[`RemoteSocketInfo`](../interfaces/RemoteSocketInfo.md)\[]> *** ### disconnectSockets() > **disconnectSockets**(`room?`): `void` Defined in: .api-entries/core/index.d.ts:860 Disconnect sockets cluster-wide — all, or only those in `room`. #### Parameters ##### room? `Topics` #### Returns `void` *** ### socketsJoin() > **socketsJoin**(`rooms`, `room?`): `void` Defined in: .api-entries/core/index.d.ts:862 Make sockets (all, or those in `room`) join `rooms`, cluster-wide. #### Parameters ##### rooms `Topics` | `Topics`\[] ##### room? `Topics` #### Returns `void` *** ### socketsLeave() > **socketsLeave**(`rooms`, `room?`): `void` Defined in: .api-entries/core/index.d.ts:864 Make sockets (all, or those in `room`) leave `rooms`, cluster-wide. #### Parameters ##### rooms `Topics` | `Topics`\[] ##### room? `Topics` #### Returns `void` *** ### serverSideEmit() > **serverSideEmit**(`event`, `data?`): `void` Defined in: .api-entries/core/index.d.ts:870 Emit an event to the **other** server nodes in the cluster (not clients). Handlers are registered with [onServerEvent](#onserverevent). The emitting node does not receive its own event. #### Parameters ##### event `string` ##### data? `unknown` #### Returns `void` *** ### onServerEvent() > **onServerEvent**<`T`>(`event`, `handler`): `this` Defined in: .api-entries/core/index.d.ts:872 Handle a [serverSideEmit](#serversideemit) event from another node. #### Type Parameters ##### T `T` = `unknown` #### Parameters ##### event `string` ##### handler (`data`) => `void` #### Returns `this` *** ### $typeChannels() > **$typeChannels**<`T`>(): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `T`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:876 This function can be changed in the near future. #### Type Parameters ##### T `T` *extends* `string` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `T`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### beforeUpgrade() > **beforeUpgrade**<`DataThis`>(`handler`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `DataThis`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:877 #### Type Parameters ##### DataThis `DataThis` #### Parameters ##### handler [`BeforeUpgradeHandler`](../type-aliases/BeforeUpgradeHandler.md)<`Query`, `Headers`, `Params`, `DataThis`> #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `DataThis`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### use() #### Call Signature > **use**<`Result`>(`plugin`): `Result` Defined in: .api-entries/core/index.d.ts:900 Apply a **plugin** — a function that receives this channel and returns an extended one. Because every builder method threads the channel's generics, the plugin's return type *is* the widened channel, so typed context, hooks, and contract additions a plugin contributes flow straight through. Use it to package reusable behavior (auth, rate-limit, logging) as an installable, typed unit. ```ts // reusable plugin (generic over the channel it's applied to) const withUser = (c: C) => c.resolve(async ({ request }) => ({ user: await verify(request.query.token) })); // configurable plugin (curried) const rateLimit = (opts: { max: number }) => (c: C) => c.beforeMessage(({ ws }) => { if (over(ws.id, opts)) throw new RpcError("OVERLOADED", "slow down"); }); const chat = new Channel("/chat/:room", "chat") .use(withUser) // handlers now see `user`, typed .use(rateLimit({ max: 100 })); ``` ##### Type Parameters ###### Result `Result` ##### Parameters ###### plugin (`channel`) => `Result` ##### Returns `Result` #### Call Signature > **use**<`PluginClient`, `PluginServer`, `PluginData`, `PluginRpc`, `PluginServerRpc`, `PluginStream`>(`plugin`): `Channel`<`Query`, `Headers`, `WebsocketClientData` & `PluginClient`, `WebsocketServerData` & `PluginServer`, `Topics`, `Path`, `Params`, `Data` & `PluginData`, `RpcMap` & `PluginRpc`, `ServerRpcMap` & `PluginServerRpc`, `StreamMap` & `PluginStream`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:901 Apply a **plugin** — a function that receives this channel and returns an extended one. Because every builder method threads the channel's generics, the plugin's return type *is* the widened channel, so typed context, hooks, and contract additions a plugin contributes flow straight through. Use it to package reusable behavior (auth, rate-limit, logging) as an installable, typed unit. ```ts // reusable plugin (generic over the channel it's applied to) const withUser = (c: C) => c.resolve(async ({ request }) => ({ user: await verify(request.query.token) })); // configurable plugin (curried) const rateLimit = (opts: { max: number }) => (c: C) => c.beforeMessage(({ ws }) => { if (over(ws.id, opts)) throw new RpcError("OVERLOADED", "slow down"); }); const chat = new Channel("/chat/:room", "chat") .use(withUser) // handlers now see `user`, typed .use(rateLimit({ max: 100 })); ``` ##### Type Parameters ###### PluginClient `PluginClient` *extends* `Record`<`string`, `any`> ###### PluginServer `PluginServer` *extends* `Record`<`string`, `any`> ###### PluginData `PluginData` ###### PluginRpc `PluginRpc` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; `errors`: `Record`<`string`, `unknown`>; }> ###### PluginServerRpc `PluginServerRpc` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; }> ###### PluginStream `PluginStream` *extends* `Record`<`string`, { `input`: `unknown`; `output`: `unknown`; }> ##### Parameters ###### plugin `Channel`<`any`, `any`, `PluginClient`, `PluginServer`, `any`, `any`, `any`, `PluginData`, `PluginRpc`, `PluginServerRpc`, `PluginStream`, `any`, `any`> ##### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData` & `PluginClient`, `WebsocketServerData` & `PluginServer`, `Topics`, `Path`, `Params`, `Data` & `PluginData`, `RpcMap` & `PluginRpc`, `ServerRpcMap` & `PluginServerRpc`, `StreamMap` & `PluginStream`, `AuthCredentials`, `PresenceState`> *** ### derive() > **derive**<`Derived`>(`fn`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `Derived`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:917 Extend the connection context with typed fields (auth, db handles, the decoded user, ...). Runs once on open; the returned object is merged into `data` and visible to every handler. Chainable — each call widens `data`. #### Type Parameters ##### Derived `Derived` *extends* `Record`<`string`, `unknown`> #### Parameters ##### fn (`ctx`) => `Derived` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `Derived`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### resolve() > **resolve**<`Derived`>(`fn`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `Derived`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> Defined in: .api-entries/core/index.d.ts:922 Async variant of [derive](#derive) (e.g. fetch the user from a token). #### Type Parameters ##### Derived `Derived` *extends* `Record`<`string`, `unknown`> #### Parameters ##### fn (`ctx`) => `Promise`<`Derived`> #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data` & `Derived`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, `PresenceState`> *** ### onAuth() > **onAuth**<`Creds`>(`credentials`, `handler`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, [`InferIn`](../type-aliases/InferIn.md)<`Creds`>, `PresenceState`> Defined in: .api-entries/core/index.d.ts:948 Declares **mid-connection credential refresh**. A WebSocket can outlive its initial bearer token; `.onAuth` lets the client present fresh credentials on the *live* connection (via `client.authenticate(creds)`) without dropping and re-handshaking. `credentials` validates the incoming payload; the handler receives the parsed credentials plus the current context, and returns the fields to merge into that context (typically the re-decoded user) — visible to every subsequent handler. Throw `new RpcError(code, message, data)` to reject the refresh; the client's `authenticate` promise rejects with that typed error. The resilient client also re-sends the last credentials automatically after a reconnect, so the refreshed identity survives transient drops. ```ts .resolve(async ({ request }) => ({ user: await verify(request.headers.token) })) .onAuth(z.object({ token: z.string() }), async ({ credentials }) => ({ user: await verify(credentials.token), // replaces the stale user })) ``` #### Type Parameters ##### Creds `Creds` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### credentials `Creds` ##### handler [`AuthHandler`](../type-aliases/AuthHandler.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`, [`InferOut`](../type-aliases/InferOut.md)<`Creds`>, `Query`, `Headers`, `Params`, `Data`> #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, [`InferIn`](../type-aliases/InferIn.md)<`Creds`>, `PresenceState`> *** ### presence() > **presence**<`State`>(`state`, `options?`): `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, [`InferOut`](../type-aliases/InferOut.md)<`State`>> Defined in: .api-entries/core/index.d.ts:973 Enables **typed presence** — a per-room roster of who's connected and their live state (cursor, status, "typing…"). `state` is the per-member state schema, typed end-to-end. Each connection belongs to one **presence room**, derived server-side (so the client never names a room): by default the connection's concrete address (`/doc/:id` → `#presence:/doc/42`); override with `options.room` to key it however you like. The client drives it with `client.presence.set(state)` / `.subscribe(cb)` / `.clear()`; join/leave/update diffs ride the normal room fan-out, so it works across a cluster for free, and a (re)connecting client fetches the current roster via a snapshot (backed by `backplane.getPresence`). ```ts .presence(z.object({ name: z.string(), typing: z.boolean() })) // client: client.presence.set({ name: "Alice", typing: false }); client.presence.subscribe((members) => render(members)); // Map ``` #### Type Parameters ##### State `State` *extends* [`AnySchema`](../type-aliases/AnySchema.md) #### Parameters ##### state `State` ##### options? ###### room? (`ctx`) => `string` #### Returns `Channel`<`Query`, `Headers`, `WebsocketClientData`, `WebsocketServerData`, `Topics`, `Path`, `Params`, `Data`, `RpcMap`, `ServerRpcMap`, `StreamMap`, `AuthCredentials`, [`InferOut`](../type-aliases/InferOut.md)<`State`>> *** ### history() > **history**<`Name`>(`name`, `options?`): `this` Defined in: .api-entries/core/index.d.ts:996 Retains recent events of `name` per room (**history / rewind**), so a (re)connecting client can fetch a backlog with `client.history(room)` — the chat-backlog / last-N-ticks pattern. Different from connection-state-recovery (which replays only *your* gap during a brief blip): history is room-scoped and any subscribed client can read it. Call once per event you want retained; `keep` bounds the per-room buffer (default 100). Retention is in the backplane (in-memory for `LocalBackplane`); a client can only read history for rooms it is in. ```ts .serverMessage("message", z.object({ text: z.string() })) .history("message", { keep: 50 }) // client: const recent = await client.history("room:42", { limit: 50 }); ``` #### Type Parameters ##### Name `Name` *extends* `string` #### Parameters ##### name `Name` ##### options? ###### keep? `number` #### Returns `this` *** ### beforeMessage() > **beforeMessage**(`fn`): `this` Defined in: .api-entries/core/index.d.ts:1004 Per-message middleware (auth, rate-limit, logging). Runs before each command/rpc handler. Throw to reject: on an rpc the caller receives a typed Error frame; on a command it routes to [onError](#onerror). #### Parameters ##### fn (`ctx`) => `unknown` #### Returns `this` *** ### onError() > **onError**(`fn`): `this` Defined in: .api-entries/core/index.d.ts:1016 Handle errors thrown by command handlers or middleware. #### Parameters ##### fn (`ctx`) => `void` #### Returns `this` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/classes/IdempotencyCache.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / IdempotencyCache # Class: IdempotencyCache Defined in: .api-entries/core/index.d.ts:554 Bounded, TTL'd store mapping idempotency key → settled RPC outcome. The first call for a key runs `exec`; subsequent calls (in-flight or completed) get the same outcome without re-running it. ## Constructors ### Constructor > **new IdempotencyCache**(`options?`): `IdempotencyCache` Defined in: .api-entries/core/index.d.ts:556 #### Parameters ##### options? [`IdempotencyOptions`](../interfaces/IdempotencyOptions.md) #### Returns `IdempotencyCache` ## Methods ### run() > **run**(`key`, `exec`): `Promise`<[`CachedRpc`](../interfaces/CachedRpc.md)> Defined in: .api-entries/core/index.d.ts:562 Run `exec` exactly once for `key`; duplicates resolve to the same outcome. `exec` must not throw — it returns a [CachedRpc](../interfaces/CachedRpc.md) for both success and failure so failures are cached identically (a retry sees the same error). #### Parameters ##### key `string` ##### exec () => `Promise`<[`CachedRpc`](../interfaces/CachedRpc.md)> #### Returns `Promise`<[`CachedRpc`](../interfaces/CachedRpc.md)> *** ### clear() > **clear**(): `void` Defined in: .api-entries/core/index.d.ts:564 Drop everything (e.g. on shutdown). #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/classes/LocalBackplane.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / LocalBackplane # Class: LocalBackplane Defined in: .api-entries/core/index.d.ts:382 ## Implements * [`Backplane`](../interfaces/Backplane.md) ## Constructors ### Constructor > **new LocalBackplane**(`options?`): `LocalBackplane` Defined in: .api-entries/core/index.d.ts:385 #### Parameters ##### options? [`LocalBackplaneOptions`](../interfaces/LocalBackplaneOptions.md) #### Returns `LocalBackplane` ## Properties ### nodeId > `readonly` **nodeId**: `` `${string}-${string}-${string}-${string}-${string}` `` Defined in: .api-entries/core/index.d.ts:384 unique id of this server node #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`nodeId`](../interfaces/Backplane.md#nodeid) ## Methods ### onMessage() > **onMessage**(`handler`): `void` Defined in: .api-entries/core/index.d.ts:386 Register the local delivery callback (called once by the adapter). #### Parameters ##### handler (`message`) => `void` #### Returns `void` #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`onMessage`](../interfaces/Backplane.md#onmessage) *** ### publish() > **publish**(`topic`, `payload`, `offset?`, `except?`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:387 Fan a message out to all nodes; each delivers locally to subscribers. When `offset` is supplied (recovery-capable backplanes) the message is also appended to the replay log under that offset. #### Parameters ##### topic `string` ##### payload `string` | `Uint8Array`<`ArrayBufferLike`> ##### offset? `string` | `number` ##### except? `string`\[] #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`publish`](../interfaces/Backplane.md#publish) *** ### assignOffset() > **assignOffset**(): `number` Defined in: .api-entries/core/index.d.ts:388 Vend the next monotonic, cluster-wide offset for an outgoing event. #### Returns `number` #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`assignOffset`](../interfaces/Backplane.md#assignoffset) *** ### replaySince() > **replaySince**(`offset`, `topics`): `Promise`<[`BackplaneMessage`](../interfaces/BackplaneMessage.md)\[]> Defined in: .api-entries/core/index.d.ts:389 Replay buffered events for the given `topics` whose offset is strictly greater than `offset`, in global publish order. #### Parameters ##### offset `string` | `number` ##### topics `string`\[] #### Returns `Promise`<[`BackplaneMessage`](../interfaces/BackplaneMessage.md)\[]> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`replaySince`](../interfaces/Backplane.md#replaysince) *** ### saveSession() > **saveSession**(`sessionId`, `state`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:390 Persist a disconnecting connection's recoverable state for `ttlMs`. #### Parameters ##### sessionId `string` ##### state [`SessionState`](../interfaces/SessionState.md) #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`saveSession`](../interfaces/Backplane.md#savesession) *** ### loadSession() > **loadSession**(`sessionId`): `Promise`<[`SessionState`](../interfaces/SessionState.md)> Defined in: .api-entries/core/index.d.ts:391 Load a reconnecting connection's state, or null if expired/unknown. #### Parameters ##### sessionId `string` #### Returns `Promise`<[`SessionState`](../interfaces/SessionState.md)> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`loadSession`](../interfaces/Backplane.md#loadsession) *** ### dropSession() > **dropSession**(`sessionId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:392 Drop a session once it has been recovered (or on hard close). #### Parameters ##### sessionId `string` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`dropSession`](../interfaces/Backplane.md#dropsession) *** ### addToRoom() > **addToRoom**(`topic`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:393 Record that a local socket joined a room (topic). #### Parameters ##### topic `string` ##### socketId `string` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`addToRoom`](../interfaces/Backplane.md#addtoroom) *** ### removeFromRoom() > **removeFromRoom**(`topic`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:394 Record that a local socket left a room (topic). #### Parameters ##### topic `string` ##### socketId `string` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`removeFromRoom`](../interfaces/Backplane.md#removefromroom) *** ### removeSocket() > **removeSocket**(`socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:395 Remove a socket from all rooms (on disconnect). #### Parameters ##### socketId `string` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`removeSocket`](../interfaces/Backplane.md#removesocket) *** ### setPresence() > **setPresence**(`room`, `socketId`, `state`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:396 Store (or replace) a member's presence state in a room. #### Parameters ##### room `string` ##### socketId `string` ##### state `unknown` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`setPresence`](../interfaces/Backplane.md#setpresence) *** ### clearPresence() > **clearPresence**(`room`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:397 Remove a member from a room's presence roster. #### Parameters ##### room `string` ##### socketId `string` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`clearPresence`](../interfaces/Backplane.md#clearpresence) *** ### getPresence() > **getPresence**(`room`): `Promise`<`Record`<`string`, `unknown`>> Defined in: .api-entries/core/index.d.ts:398 Current roster of a presence room: socket id → state. #### Parameters ##### room `string` #### Returns `Promise`<`Record`<`string`, `unknown`>> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`getPresence`](../interfaces/Backplane.md#getpresence) *** ### configureHistory() > **configureHistory**(`events`): `void` Defined in: .api-entries/core/index.d.ts:399 Register which event names to retain and how many (event name → keep). #### Parameters ##### events `Record`<`string`, `number`> #### Returns `void` #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`configureHistory`](../interfaces/Backplane.md#configurehistory) *** ### appendHistory() > **appendHistory**(`topic`, `event`, `data`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:400 Append an event to a room's history (no-op if the event isn't retained). #### Parameters ##### topic `string` ##### event `string` ##### data `unknown` #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`appendHistory`](../interfaces/Backplane.md#appendhistory) *** ### getHistory() > **getHistory**(`topic`, `limit?`): `Promise`<`object`\[]> Defined in: .api-entries/core/index.d.ts:401 Fetch a room's retained events (most-recent `limit`, or all), in order. #### Parameters ##### topic `string` ##### limit? `number` #### Returns `Promise`<`object`\[]> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`getHistory`](../interfaces/Backplane.md#gethistory) *** ### roomMembers() > **roomMembers**(`topic`): `Promise`<`string`\[]> Defined in: .api-entries/core/index.d.ts:405 Cluster-wide socket ids in a room (presence / fetchSockets). #### Parameters ##### topic `string` #### Returns `Promise`<`string`\[]> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`roomMembers`](../interfaces/Backplane.md#roommembers) *** ### rooms() > **rooms**(`socketId`): `Promise`<`string`\[]> Defined in: .api-entries/core/index.d.ts:406 Rooms a socket currently belongs to. #### Parameters ##### socketId `string` #### Returns `Promise`<`string`\[]> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`rooms`](../interfaces/Backplane.md#rooms) *** ### close() > **close**(): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:407 #### Returns `Promise`<`void`> #### Implementation of [`Backplane`](../interfaces/Backplane.md).[`close`](../interfaces/Backplane.md#close) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/classes/OutboundRpc.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / OutboundRpc # Class: OutboundRpc Defined in: .api-entries/core/index.d.ts:420 Outbound (server-initiated) RPC bookkeeping for a single connection. The wire protocol is symmetric: the server can send a Frame.Request to a client and await its Frame.Reply/Frame.Error, exactly like a client does in the other direction. This holds the per-connection correlation counter + pending table for those server→client requests. One instance lives per connection (so a reply in a later message resolves the original promise). ## Constructors ### Constructor > **new OutboundRpc**(): `OutboundRpc` #### Returns `OutboundRpc` ## Methods ### request() > **request**(`send`, `name`, `input`, `timeout`): `Promise`<`unknown`> Defined in: .api-entries/core/index.d.ts:423 Send a request to the peer and resolve when its reply arrives. #### Parameters ##### send (`frame`) => `void` ##### name `string` ##### input `unknown` ##### timeout `number` #### Returns `Promise`<`unknown`> *** ### resolve() > **resolve**(`corrId`, `value`): `void` Defined in: .api-entries/core/index.d.ts:425 Resolve the pending request for `corrId` (on an inbound Reply). #### Parameters ##### corrId `number` ##### value `unknown` #### Returns `void` *** ### reject() > **reject**(`corrId`, `error`): `void` Defined in: .api-entries/core/index.d.ts:427 Reject the pending request for `corrId` (on an inbound Error). #### Parameters ##### corrId `number` ##### error `RpcError` #### Returns `void` *** ### rejectAll() > **rejectAll**(`error`): `void` Defined in: .api-entries/core/index.d.ts:429 Reject everything in flight (on disconnect). #### Parameters ##### error `RpcError` #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/client/classes/RpcError.md' --- [ws-asyncapi API](../../index.md) / [client](../index.md) / RpcError # Class: RpcError Defined in: node\_modules/ws-asyncapi/dist/wire.d.ts:226 Error surfaced on the client when an RPC fails — either rejected by the server with an Frame.Error frame or synthesized locally on timeout. ## Extends * `Error` ## Constructors ### Constructor > **new RpcError**(`code`, `message`, `data?`): `RpcError` Defined in: node\_modules/ws-asyncapi/dist/wire.d.ts:229 #### Parameters ##### code `ErrorCode` ##### message `string` ##### data? `unknown` #### Returns `RpcError` #### Overrides `Error.constructor` ## Properties ### stackTraceLimit > `static` **stackTraceLimit**: `number` Defined in: node\_modules/@types/node/globals.d.ts:68 The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). The default value is `10` but may be set to any valid JavaScript number. Changes will affect any stack trace captured *after* the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. #### Inherited from `Error.stackTraceLimit` *** ### cause? > `optional` **cause?**: `unknown` Defined in: node\_modules/typescript/lib/lib.es2022.error.d.ts:26 The cause of the error. #### Inherited from `Error.cause` *** ### name > **name**: `string` Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1076 #### Inherited from `Error.name` *** ### message > **message**: `string` Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1077 #### Inherited from `Error.message` *** ### stack? > `optional` **stack?**: `string` Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1078 #### Inherited from `Error.stack` *** ### code > `readonly` **code**: `ErrorCode` Defined in: node\_modules/ws-asyncapi/dist/wire.d.ts:227 *** ### data? > `readonly` `optional` **data?**: `unknown` Defined in: node\_modules/ws-asyncapi/dist/wire.d.ts:228 ## Methods ### captureStackTrace() #### Call Signature > `static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void` Defined in: node\_modules/@types/node/globals.d.ts:52 Creates a `.stack` property on `targetObject`, which when accessed returns a string representing the location in the code at which `Error.captureStackTrace()` was called. ```js const myObject = {}; Error.captureStackTrace(myObject); myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with `${myObject.name}: ${myObject.message}`. The optional `constructorOpt` argument accepts a function. If given, all frames above `constructorOpt`, including `constructorOpt`, will be omitted from the generated stack trace. The `constructorOpt` argument is useful for hiding implementation details of error generation from the user. For instance: ```js function a() { b(); } function b() { c(); } function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit; // Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error; } a(); ``` ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from `Error.captureStackTrace` #### Call Signature > `static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void` Defined in: node\_modules/bun-types/globals.d.ts:1042 Create .stack property on a target object ##### Parameters ###### targetObject `object` ###### constructorOpt? `Function` ##### Returns `void` ##### Inherited from `Error.captureStackTrace` *** ### prepareStackTrace() > `static` **prepareStackTrace**(`err`, `stackTraces`): `any` Defined in: node\_modules/@types/node/globals.d.ts:56 #### Parameters ##### err `Error` ##### stackTraces `CallSite`\[] #### Returns `any` #### See https://v8.dev/docs/stack-trace-api#customizing-stack-traces #### Inherited from `Error.prepareStackTrace` *** ### isError() #### Call Signature > `static` **isError**(`error`): `error is Error` Defined in: node\_modules/typescript/lib/lib.esnext.error.d.ts:23 Indicates whether the argument provided is a built-in Error instance or not. ##### Parameters ###### error `unknown` ##### Returns `error is Error` ##### Inherited from `Error.isError` #### Call Signature > `static` **isError**(`value`): `value is Error` Defined in: node\_modules/bun-types/globals.d.ts:1037 Check if a value is an instance of Error ##### Parameters ###### value `unknown` The value to check ##### Returns `value is Error` True if the value is an instance of Error, false otherwise ##### Inherited from `Error.isError` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/classes/StreamRegistry.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / StreamRegistry # Class: StreamRegistry Defined in: .api-entries/core/index.d.ts:442 Server-side bookkeeping for active streams on one connection. Each `client.stream(name, input)` opens a stream identified by a client-minted id. The server runs the channel's async-generator handler and pushes each yielded value as a import("./wire.ts").Frame.StreamData frame. This tracks the in-flight streams so a client cancel (StreamStop) or a disconnect can abort them — the handler's `signal` fires and its generator is `return()`-ed, so a `try/finally` cleans up. One instance per connection. ## Constructors ### Constructor > **new StreamRegistry**(): `StreamRegistry` #### Returns `StreamRegistry` ## Methods ### add() > **add**(`streamId`): `AbortSignal` Defined in: .api-entries/core/index.d.ts:445 Register a new stream and return the signal handed to its handler. #### Parameters ##### streamId `number` #### Returns `AbortSignal` *** ### stop() > **stop**(`streamId`): `void` Defined in: .api-entries/core/index.d.ts:447 Cancel one stream (client StreamStop). #### Parameters ##### streamId `number` #### Returns `void` *** ### done() > **done**(`streamId`): `void` Defined in: .api-entries/core/index.d.ts:449 Mark a stream finished (handler completed/failed) — no abort. #### Parameters ##### streamId `number` #### Returns `void` *** ### abortAll() > **abortAll**(): `void` Defined in: .api-entries/core/index.d.ts:451 Cancel every active stream (on disconnect). #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/client.md' --- [ws-asyncapi API](../index.md) / client # client ## Classes * [RpcError](classes/RpcError.md) ## Interfaces * [WebsocketAsyncAPIMap](interfaces/WebsocketAsyncAPIMap.md) * [CloseEvent](interfaces/CloseEvent.md) * [OpenEvent](interfaces/OpenEvent.md) * [ReconnectOptions](interfaces/ReconnectOptions.md) * [HeartbeatOptions](interfaces/HeartbeatOptions.md) * [WebsocketAsyncAPIOptions](interfaces/WebsocketAsyncAPIOptions.md) * [WebSocketLike](interfaces/WebSocketLike.md) * [RequestOptions](interfaces/RequestOptions.md) * [WsClient](interfaces/WsClient.md) * [PresenceApi](interfaces/PresenceApi.md) ## Type Aliases * [FindMatchingAddressKey](type-aliases/FindMatchingAddressKey.md) * [HistoryEntry](type-aliases/HistoryEntry.md) * [BuiltinErrorCode](type-aliases/BuiltinErrorCode.md) * [TypedRpcError](type-aliases/TypedRpcError.md) * [SafeResult](type-aliases/SafeResult.md) ## Functions * [websocketAsyncAPI](functions/websocketAsyncAPI.md) * [createClient](functions/createClient.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core.md' --- [ws-asyncapi API](../index.md) / core # core ## Classes * [WebSocketImplementation](classes/WebSocketImplementation.md) * [LocalBackplane](classes/LocalBackplane.md) * [OutboundRpc](classes/OutboundRpc.md) * [StreamRegistry](classes/StreamRegistry.md) * [IdempotencyCache](classes/IdempotencyCache.md) * [Channel](classes/Channel.md) ## Interfaces * [WebsocketDataType](interfaces/WebsocketDataType.md) * [ServerPluginContext](interfaces/ServerPluginContext.md) * [ServerPlugin](interfaces/ServerPlugin.md) * [ValidationIssue](interfaces/ValidationIssue.md) * [WebsocketClientData](interfaces/WebsocketClientData.md) * [RequestData](interfaces/RequestData.md) * [MessageHandlerSchema](interfaces/MessageHandlerSchema.md) * [BackplaneMessage](interfaces/BackplaneMessage.md) * [SessionState](interfaces/SessionState.md) * [Backplane](interfaces/Backplane.md) * [LocalBackplaneOptions](interfaces/LocalBackplaneOptions.md) * [Connection](interfaces/Connection.md) * [CachedRpc](interfaces/CachedRpc.md) * [IdempotencyOptions](interfaces/IdempotencyOptions.md) * [RemoteSocketInfo](interfaces/RemoteSocketInfo.md) * [RpcDefinition](interfaces/RpcDefinition.md) * [ServerRpcDefinition](interfaces/ServerRpcDefinition.md) * [StreamDefinition](interfaces/StreamDefinition.md) ## Type Aliases * [NodeCommand](type-aliases/NodeCommand.md) * [AnySchema](type-aliases/AnySchema.md) * [JsonSchemaTarget](type-aliases/JsonSchemaTarget.md) * [SchemaIO](type-aliases/SchemaIO.md) * [InferOut](type-aliases/InferOut.md) * [InferIn](type-aliases/InferIn.md) * [ValidationResult](type-aliases/ValidationResult.md) * [VendorJsonSchemaConverter](type-aliases/VendorJsonSchemaConverter.md) * [MaybePromise](type-aliases/MaybePromise.md) * [OnOpenHandler](type-aliases/OnOpenHandler.md) * [OnCloseHandler](type-aliases/OnCloseHandler.md) * [MessageHandler](type-aliases/MessageHandler.md) * [RpcHandler](type-aliases/RpcHandler.md) * [StreamHandler](type-aliases/StreamHandler.md) * [AuthHandler](type-aliases/AuthHandler.md) * [ExtractRouteParams](type-aliases/ExtractRouteParams.md) * [BeforeUpgradeHandler](type-aliases/BeforeUpgradeHandler.md) * [GetWebSocketType](type-aliases/GetWebSocketType.md) * [NamedPlugin](type-aliases/NamedPlugin.md) * [AnyChannel](type-aliases/AnyChannel.md) * [AddressPattern](type-aliases/AddressPattern.md) * [InferClient](type-aliases/InferClient.md) ## Variables * [AuthFrame](variables/AuthFrame.md) * [COMMAND\_TOPIC](variables/COMMAND_TOPIC.md) * [PLUGIN\_NAME](variables/PLUGIN_NAME.md) ## Functions * [emitServerPlugin](functions/emitServerPlugin.md) * [applyCommand](functions/applyCommand.md) * [isStandardSchema](functions/isStandardSchema.md) * [validate](functions/validate.md) * [registerJsonSchemaConverter](functions/registerJsonSchemaConverter.md) * [toJsonSchema](functions/toJsonSchema.md) * [perSocketRoom](functions/perSocketRoom.md) * [openConnection](functions/openConnection.md) * [closeConnection](functions/closeConnection.md) * [dispatchFrame](functions/dispatchFrame.md) * [getAsyncApiUI](functions/getAsyncApiUI.md) * [getAsyncApiDocument](functions/getAsyncApiDocument.md) * [publishEvent](functions/publishEvent.md) * [contractHash](functions/contractHash.md) * [definePlugin](functions/definePlugin.md) * [pluginName](functions/pluginName.md) ## References ### CloseCode Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### CommandFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### ErrorFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### EventFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### Frame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### HelloFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### HistoryEntry Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### HistoryQueryFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PROTOCOL\_VERSION Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PingFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PongFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceClearFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceDiffFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceQueryFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceSetFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceSnapshot Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### PresenceUpdateFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### ReplyFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### RequestFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### StreamDataFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### StreamEndFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### StreamErrorFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### StreamStartFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### StreamStopFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### WelcomeFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### jsonCodec Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### AnyFrame Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### Codec Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### ErrorCode Renames and re-exports [AuthFrame](variables/AuthFrame.md) *** ### RpcError Renames and re-exports [AuthFrame](variables/AuthFrame.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/cursors.md' --- [ws-asyncapi API](../index.md) / cursors # cursors ## Interfaces * [CursorPoint](interfaces/CursorPoint.md) * [CursorSmoother](interfaces/CursorSmoother.md) * [CursorsClient](interfaces/CursorsClient.md) * [CursorsOptions](interfaces/CursorsOptions.md) ## Type Aliases * [SmootherFactory](type-aliases/SmootherFactory.md) ## Variables * [lerpSmoother](variables/lerpSmoother.md) ## Functions * [cursorsStore](functions/cursorsStore.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/emitter.md' --- [ws-asyncapi API](../index.md) / emitter # emitter ## Interfaces * [EmitterOptions](interfaces/EmitterOptions.md) ## Type Aliases * [Emitter](type-aliases/Emitter.md) ## Functions * [createEmitter](functions/createEmitter.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/applyCommand.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / applyCommand # Function: applyCommand() > **applyCommand**(`channel`, `cmd`, `isOrigin`): `void` Defined in: .api-entries/core/index.d.ts:130 Apply a command to a channel's local sockets. Called by each node from its backplane message handler. `isOrigin` is true on the node that issued the command (used to avoid echoing `serverSideEmit` back to the sender). ## Parameters ### channel [`AnyChannel`](../type-aliases/AnyChannel.md) ### cmd [`NodeCommand`](../type-aliases/NodeCommand.md) ### isOrigin `boolean` ## Returns `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/closeConnection.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / closeConnection # Function: closeConnection() > **closeConnection**(`channel`, `backplane`, `conn`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:490 Run `onClose`, persist the recovery session, and drop the socket from rooms. ## Parameters ### channel [`AnyChannel`](../type-aliases/AnyChannel.md) ### backplane [`Backplane`](../interfaces/Backplane.md) ### conn [`Connection`](../interfaces/Connection.md) ## Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/connectionStore.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / connectionStore # Function: connectionStore() > **connectionStore**(`client`): [`Subscribable`](../interfaces/Subscribable.md)<{ `connected`: `boolean`; `recovered`: `boolean`; }> Defined in: .api-entries/query-core/index.d.ts:117 Connection liveness as a subscribable store. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ## Returns [`Subscribable`](../interfaces/Subscribable.md)<{ `connected`: `boolean`; `recovered`: `boolean`; }> --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/contractHash.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / contractHash # Function: contractHash() > **contractHash**(`channel`): `string` Defined in: .api-entries/core/index.d.ts:573 Deterministic hash of a channel's wire contract (commands, events, RPCs, server→client RPCs, and the connection query/headers schemas). Stable across runs and processes for the same contract; changes whenever any message name or schema changes. Memoized per channel. ## Parameters ### channel `unknown` ## Returns `string` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/functions/createClient.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / createClient # Function: createClient() > **createClient**<`C`>(`url`, `path`, `options?`): [`WsClient`](../interfaces/WsClient.md)<`InferClient`<`C`>> Defined in: .api-entries/client/index.d.ts:330 Codegen-free typed client. Infers the full client surface (events, commands, RPCs, typed errors, query/headers) directly from a server `Channel` type — no CLI step, no generated file, no global `declare module`. Same runtime as [websocketAsyncAPI](websocketAsyncAPI.md). ```ts import type { chat } from "./server"; // the Channel value's type import { createClient } from "@ws-asyncapi/client"; const client = createClient("ws://localhost:3000", "/chat/1"); client.onEvent("message", (m) => m.text); // typed const { items } = await client.request("history", { limit: 50 }); // typed ``` ## Type Parameters ### C `C` *extends* `AnyChannel` ## Parameters ### url `string` ### path `InferClient`<`C`>\[`"address"`] ### options? [`WebsocketAsyncAPIOptions`](../interfaces/WebsocketAsyncAPIOptions.md)<`AsRecord`<`InferClient`<`C`>\[`"query"`]>, `AsRecord`<`InferClient`<`C`>\[`"headers"`]>> ## Returns [`WsClient`](../interfaces/WsClient.md)<`InferClient`<`C`>> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/emitter/functions/createEmitter.md --- [ws-asyncapi API](../../index.md) / [emitter](../index.md) / createEmitter # Function: createEmitter() > **createEmitter**<`C`>(`backplane`, `options?`): `object` Defined in: .api-entries/emitter/index.d.ts:28 Emit events to connected clients **from a process that isn't running a server** — the Socket.IO `@socket.io/redis-emitter` equivalent. Hand it a backplane shared with the running servers (e.g. a `RedisBackplane` pointed at the same Redis) and publish: the servers' `onMessage` fans your events out to their connected clients. Typed against a channel via `typeof channel`. ```ts import { RedisBackplane } from "@ws-asyncapi/backplane-redis"; import { createEmitter } from "@ws-asyncapi/emitter"; import type { chat } from "./contract"; const emitter = createEmitter( new RedisBackplane({ url: "redis://localhost:6379" }), ); emitter.publish("room:1", "message", { from: "billing", text: "paid" }); ``` One-way only: emit to rooms / sockets. Acks, presence, and inbound messages require a running server. ## Type Parameters ### C `C` *extends* `AnyChannel` ## Parameters ### backplane `Backplane` ### options? [`EmitterOptions`](../interfaces/EmitterOptions.md) ## Returns ### publish() > **publish**<`E`>(`room`, `event`, `data`): `Promise`<`void`> Emit an event to everyone in `room`, cluster-wide. #### Type Parameters ##### E `E` *extends* `string` #### Parameters ##### room `string` ##### event `E` ##### data `InferClient`<`C`>\[`"eventMap"`]\[`E`] #### Returns `Promise`<`void`> ### toSocket() > **toSocket**<`E`>(`socketId`, `event`, `data`): `Promise`<`void`> Emit an event to a single socket by id, cluster-wide. #### Type Parameters ##### E `E` *extends* `string` #### Parameters ##### socketId `string` ##### event `E` ##### data `InferClient`<`C`>\[`"eventMap"`]\[`E`] #### Returns `Promise`<`void`> ### close() > **close**(): `Promise`<`void`> Close the underlying backplane connection. #### Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/react/functions/createReactClient.md --- [ws-asyncapi API](../../index.md) / [react](../index.md) / createReactClient # Function: createReactClient() > **createReactClient**<`C`>(`url`, `path`, `options?`): [`ReactClient`](../interfaces/ReactClient.md)<`InferClient`<`C`>> Defined in: .api-entries/react/index.d.ts:72 ## Type Parameters ### C `C` *extends* `AnyChannel` ## Parameters ### url `string` ### path `InferClient`<`C`>\[`"address"`] ### options? `WebsocketAsyncAPIOptions`<`any`, `any`> ## Returns [`ReactClient`](../interfaces/ReactClient.md)<`InferClient`<`C`>> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/solid/functions/createSolidClient.md --- [ws-asyncapi API](../../index.md) / [solid](../index.md) / createSolidClient # Function: createSolidClient() > **createSolidClient**<`C`>(`url`, `path`, `options?`): [`SolidClient`](../interfaces/SolidClient.md)<`InferClient`<`C`>> Defined in: .api-entries/solid/index.d.ts:76 ## Type Parameters ### C `C` *extends* `AnyChannel` ## Parameters ### url `string` ### path `InferClient`<`C`>\[`"address"`] ### options? `WebsocketAsyncAPIOptions`<`any`, `any`> ## Returns [`SolidClient`](../interfaces/SolidClient.md)<`InferClient`<`C`>> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/testing/functions/createTestHarness.md --- [ws-asyncapi API](../../index.md) / [testing](../index.md) / createTestHarness # Function: createTestHarness() > **createTestHarness**<`C`>(`channel`, `options?`): [`TestHarness`](../interfaces/TestHarness.md)<`C`> Defined in: .api-entries/testing/index.d.ts:28 ## Type Parameters ### C `C` *extends* `AnyChannel` ## Parameters ### channel `C` ### options? [`TestHarnessOptions`](../interfaces/TestHarnessOptions.md) ## Returns [`TestHarness`](../interfaces/TestHarness.md)<`C`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/functions/cursorsStore.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / cursorsStore # Function: cursorsStore() > **cursorsStore**<`S`>(`client`, `options?`): `Subscribable`<`Map`<`string`, [`CursorPoint`](../interfaces/CursorPoint.md)>> Defined in: .api-entries/cursors/index.d.ts:69 Live cursors as a Subscribable: a `Map` of *other* members' (optionally smoothed) cursor positions, derived from presence diffs. Self is excluded; members that leave (or clear their cursor) are dropped. Bind it with the framework's generic store hook (`useStore` / `fromStore`). ## Type Parameters ### S `S` = { `cursor?`: [`CursorPoint`](../interfaces/CursorPoint.md); } ## Parameters ### client [`CursorsClient`](../interfaces/CursorsClient.md)<`S`> ### options? [`CursorsOptions`](../interfaces/CursorsOptions.md)<`S`> ## Returns `Subscribable`<`Map`<`string`, [`CursorPoint`](../interfaces/CursorPoint.md)>> --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/definePlugin.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / definePlugin # Function: definePlugin() > **definePlugin**<`Setup`>(`options`): [`NamedPlugin`](../type-aliases/NamedPlugin.md)<`Setup`> Defined in: .api-entries/core/index.d.ts:614 Tag a plugin with a stable `name` so [Channel.use](../classes/Channel.md#use) applies it at most once per channel. `setup` is the plugin body — `(channel) => extended channel`. The same typing rules as `.use` apply: inline-shaped and hook-only setups keep full typing; reusable setups that add context/contract run at runtime but their added types don't thread through a by-reference application. ## Type Parameters ### Setup `Setup` *extends* (`channel`) => `unknown` ## Parameters ### options #### name `string` #### setup `Setup` ## Returns [`NamedPlugin`](../type-aliases/NamedPlugin.md)<`Setup`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/dispatchFrame.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / dispatchFrame # Function: dispatchFrame() > **dispatchFrame**(`channel`, `backplane`, `conn`, `frame`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:495 Handle one decoded inbound frame. The adapter is responsible for decoding the transport bytes into an [AnyFrame](../variables/AuthFrame.md) before calling this. ## Parameters ### channel [`AnyChannel`](../type-aliases/AnyChannel.md) ### backplane [`Backplane`](../interfaces/Backplane.md) ### conn [`Connection`](../interfaces/Connection.md) ### frame `AnyFrame` ## Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/emitServerPlugin.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / emitServerPlugin # Function: emitServerPlugin() > **emitServerPlugin**(`plugins`, `run`): `void` Defined in: .api-entries/core/index.d.ts:91 Run a hook across all server plugins, fire-and-forget. Errors (sync or async) are swallowed so observability never breaks the connection. ## Parameters ### plugins [`ServerPlugin`](../interfaces/ServerPlugin.md)\[] ### run (`plugin`) => `unknown` ## Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/solid/functions/fromStore.md' --- [ws-asyncapi API](../../index.md) / [solid](../index.md) / fromStore # Function: fromStore() > **fromStore**<`T`>(`store`): `Accessor`<`T`> Defined in: .api-entries/solid/index.d.ts:32 Bridge any `query-core` Subscribable (e.g. `cursorsStore` from `@ws-asyncapi/cursors`, or your own) into a Solid accessor (signal). The generic escape hatch that keeps cursor/other opinions out of this package. ## Type Parameters ### T `T` ## Parameters ### store `Subscribable`<`T`> ## Returns `Accessor`<`T`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/getAsyncApiDocument.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / getAsyncApiDocument # Function: getAsyncApiDocument() > **getAsyncApiDocument**(`channelsRaw`, `schema?`): `AsyncAPIObject` Defined in: .api-entries/core/index.d.ts:503 ## Parameters ### channelsRaw [`AnyChannel`](../type-aliases/AnyChannel.md)\[] ### schema? `Partial`<`AsyncAPIObject`> ## Returns `AsyncAPIObject` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/getAsyncApiUI.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / getAsyncApiUI # Function: getAsyncApiUI() > **getAsyncApiUI**<`As`>(`asyncApi`, `as`): `AsyncApiUIResults`\[`As`] Defined in: .api-entries/core/index.d.ts:501 ## Type Parameters ### As `As` *extends* `"string"` | `"response"` ## Parameters ### asyncApi `AsyncAPIObject` ### as `As` ## Returns `AsyncApiUIResults`\[`As`] --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/historyQueryKey.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / historyQueryKey # Function: historyQueryKey() > **historyQueryKey**(`keyPrefix`, `room`, `limit?`): `unknown`\[] Defined in: .api-entries/query-core/index.d.ts:51 ## Parameters ### keyPrefix `string` ### room `string` ### limit? `number` ## Returns `unknown`\[] --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/historyQueryOptions.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / historyQueryOptions # Function: historyQueryOptions() > **historyQueryOptions**(`client`, `keyPrefix`, `room`, `limit?`): `object` Defined in: .api-entries/query-core/index.d.ts:62 Options for a room-history query. Spread into any framework's `useQuery`. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### keyPrefix `string` ### room `string` ### limit? `number` ## Returns `object` ### queryKey > **queryKey**: `unknown`\[] ### queryFn > **queryFn**: () => `Promise`<`object`\[]> #### Returns `Promise`<`object`\[]> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/isStandardSchema.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / isStandardSchema # Function: isStandardSchema() > **isStandardSchema**(`s`): `s is StandardSchemaV1` Defined in: .api-entries/core/index.d.ts:161 True if `s` implements Standard Schema (has a `~standard` prop). ## Parameters ### s `unknown` ## Returns `s is StandardSchemaV1` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/lastEventStore.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / lastEventStore # Function: lastEventStore() > **lastEventStore**(`client`, `event`): [`Subscribable`](../interfaces/Subscribable.md)<`unknown`> Defined in: .api-entries/query-core/index.d.ts:115 The most recent value of an event as a subscribable store. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### event `string` ## Returns [`Subscribable`](../interfaces/Subscribable.md)<`unknown`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/mutationOptions.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / mutationOptions # Function: mutationOptions() > **mutationOptions**(`client`, `command`): `object` Defined in: .api-entries/query-core/index.d.ts:58 Options for an RPC-as-mutation. Spread into any framework's `useMutation`. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### command `string` ## Returns `object` ### mutationFn > **mutationFn**: (`input`) => `Promise`<`unknown`> #### Parameters ##### input `unknown` #### Returns `Promise`<`unknown`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/openConnection.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / openConnection # Function: openConnection() > **openConnection**(`channel`, `conn`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:488 Run the channel's `.derive`/`.resolve` chain, then `onOpen`. ## Parameters ### channel [`AnyChannel`](../type-aliases/AnyChannel.md) ### conn [`Connection`](../interfaces/Connection.md) ## Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/perSocketRoom.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / perSocketRoom # Function: perSocketRoom() > **perSocketRoom**(`socketId`): `string` Defined in: .api-entries/core/index.d.ts:486 Reserved per-socket room so a socket can be addressed directly by id (`channel.toSocket(id, …)`), cluster-wide, through the normal publish path. ## Parameters ### socketId `string` ## Returns `string` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/pluginName.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / pluginName # Function: pluginName() > **pluginName**(`plugin`): `string` Defined in: .api-entries/core/index.d.ts:619 Read a plugin's name, if it was created with [definePlugin](definePlugin.md). ## Parameters ### plugin `unknown` ## Returns `string` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/presenceStore.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / presenceStore # Function: presenceStore() > **presenceStore**(`client`): [`Subscribable`](../interfaces/Subscribable.md)<[`PresenceSnapshotState`](../interfaces/PresenceSnapshotState.md)> & `object` Defined in: .api-entries/query-core/index.d.ts:105 Live presence roster as a subscribable store (+ `set`/`clear`). The snapshot reference is stable between changes, so it's safe for `useSyncExternalStore`. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ## Returns [`Subscribable`](../interfaces/Subscribable.md)<[`PresenceSnapshotState`](../interfaces/PresenceSnapshotState.md)> & `object` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/publishEvent.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / publishEvent # Function: publishEvent() > **publishEvent**(`backplane`, `codec`, `topic`, `type`, `data`, `except?`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:514 Build and publish a server→client Event through a [Backplane](../interfaces/Backplane.md). Shared by the adapters and the standalone emitter so the offset-stamping + encoding logic lives in one place. Assigns a recovery offset when the backplane supports it, encodes the Event frame once, then publishes — the backplane fans it out to every node and appends it to the replay log. ## Parameters ### backplane [`Backplane`](../interfaces/Backplane.md) ### codec `Codec` ### topic `string` ### type `string` ### data `unknown` ### except? `string`\[] ## Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/functions/registerJsonSchemaConverter.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / registerJsonSchemaConverter # Function: registerJsonSchemaConverter() > **registerJsonSchemaConverter**(`vendor`, `convert`): `void` Defined in: .api-entries/core/index.d.ts:198 Register a JSON Schema converter, keyed by `~standard.vendor`, for validators that can validate but can't emit JSON Schema themselves. Call once at startup: ```ts import { toJsonSchema } from "@valibot/to-json-schema"; import { registerJsonSchemaConverter } from "ws-asyncapi"; registerJsonSchemaConverter("valibot", (s) => toJsonSchema(s as never)); ``` ## Parameters ### vendor `string` ### convert [`VendorJsonSchemaConverter`](../type-aliases/VendorJsonSchemaConverter.md) ## Returns `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/requestQueryOptions.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / requestQueryOptions # Function: requestQueryOptions() > **requestQueryOptions**(`client`, `keyPrefix`, `command`, `input`): `object` Defined in: .api-entries/query-core/index.d.ts:53 Options for an RPC-as-query. Spread into any framework's `useQuery`. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### keyPrefix `string` ### command `string` ### input `unknown` ## Returns `object` ### queryKey > **queryKey**: `unknown`\[] ### queryFn > **queryFn**: () => `Promise`<`unknown`> #### Returns `Promise`<`unknown`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/rpcQueryKey.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / rpcQueryKey # Function: rpcQueryKey() > **rpcQueryKey**(`keyPrefix`, `command`, `input`): `unknown`\[] Defined in: .api-entries/query-core/index.d.ts:50 ## Parameters ### keyPrefix `string` ### command `string` ### input `unknown` ## Returns `unknown`\[] --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/streamFold.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / streamFold # Function: streamFold() > **streamFold**<`Item`, `Acc`>(`options?`): `object` Defined in: .api-entries/query-core/index.d.ts:88 Build the `{ initial, step }` fold. Default (no options) keeps only the **latest** item — O(1), nothing accumulated. ## Type Parameters ### Item `Item` ### Acc `Acc` ## Parameters ### options? [`StreamReduce`](../type-aliases/StreamReduce.md)<`Item`, `Acc`> ## Returns `object` ### initial > **initial**: `unknown` ### step > **step**: (`acc`, `item`) => `unknown` #### Parameters ##### acc `unknown` ##### item `Item` #### Returns `unknown` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/react/functions/streamFold.md' --- [ws-asyncapi API](../../index.md) / [react](../index.md) / streamFold # Function: streamFold() > **streamFold**<`Item`, `Acc`>(`options?`): `object` Defined in: node\_modules/@ws-asyncapi/query-core/dist/index.d.ts:88 Build the `{ initial, step }` fold. Default (no options) keeps only the **latest** item — O(1), nothing accumulated. ## Type Parameters ### Item `Item` ### Acc `Acc` ## Parameters ### options? [`StreamReduce`](../type-aliases/StreamReduce.md)<`Item`, `Acc`> ## Returns `object` ### initial > **initial**: `unknown` ### step > **step**: (`acc`, `item`) => `unknown` #### Parameters ##### acc `unknown` ##### item `Item` #### Returns `unknown` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/streamStore.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / streamStore # Function: streamStore() > **streamStore**(`client`, `name`, `input`, `options?`): [`Subscribable`](../interfaces/Subscribable.md)<[`StreamSnapshot`](../interfaces/StreamSnapshot.md)<`unknown`>> Defined in: .api-entries/query-core/index.d.ts:113 Consume a stream as a subscribable store. Default keeps the **latest** value (O(1)); pass `reduce` to accumulate. Iteration starts on first subscribe and is cancelled (StreamStop) when the last subscriber leaves. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### name `string` ### input `unknown` ### options? [`StreamReduce`](../type-aliases/StreamReduce.md)<`unknown`, `unknown`> ## Returns [`Subscribable`](../interfaces/Subscribable.md)<[`StreamSnapshot`](../interfaces/StreamSnapshot.md)<`unknown`>> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/functions/subscribeHistoryLive.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / subscribeHistoryLive # Function: subscribeHistoryLive() > **subscribeHistoryLive**(`client`, `queryClient`, `keyPrefix`, `room`, `options`): () => `void` Defined in: .api-entries/query-core/index.d.ts:74 Keep a history query live by appending incoming `liveEvent` events into the same cache entry (bounded by `limit`). Returns an unsubscribe. Framework- agnostic: pass the adapter's `QueryClient`. ## Parameters ### client [`QueryCoreClient`](../interfaces/QueryCoreClient.md) ### queryClient `QueryClient` ### keyPrefix `string` ### room `string` ### options #### liveEvent `string` #### limit? `number` ## Returns () => `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/toJsonSchema.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / toJsonSchema # Function: toJsonSchema() > **toJsonSchema**(`schema`, `io?`, `target?`): `object` Defined in: .api-entries/core/index.d.ts:209 Produce a JSON Schema for the AsyncAPI contract / CLI codegen. Resolution ladder: 1. **StandardJSONSchemaV1** — native `~standard.jsonSchema[io]()` (Zod ≥4.2, ArkType ≥2.1.28). 2. **Registered vendor converter** — for validators that validate but emit JSON Schema elsewhere (e.g. Valibot via `@valibot/to-json-schema`); see [registerJsonSchemaConverter](registerJsonSchemaConverter.md). 3. **`{}`** — runtime validation still works; the generated type is `unknown`. ## Parameters ### schema [`AnySchema`](../type-aliases/AnySchema.md) ### io? [`SchemaIO`](../type-aliases/SchemaIO.md) ### target? [`JsonSchemaTarget`](../type-aliases/JsonSchemaTarget.md) ## Returns `object` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/react/functions/useStore.md' --- [ws-asyncapi API](../../index.md) / [react](../index.md) / useStore # Function: useStore() > **useStore**<`T`>(`store`): `T` Defined in: .api-entries/react/index.d.ts:29 Bind any `query-core` Subscribable (e.g. `cursorsStore` from `@ws-asyncapi/cursors`, or your own) to a React value. The generic escape hatch that keeps cursor/other opinions out of this package. ## Type Parameters ### T `T` ## Parameters ### store `Subscribable`<`T`> ## Returns `T` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/functions/validate.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / validate # Function: validate() > **validate**(`schema`, `value`): `Promise`<[`ValidationResult`](../type-aliases/ValidationResult.md)> Defined in: .api-entries/core/index.d.ts:180 Validate `value` against `schema` (a Standard Schema validator, which may run sync or async). Returns the **parsed** value on success (so transforms / coercion / defaults are applied), or normalized issues on failure. A value that isn't a Standard Schema is treated as "no validation" and passes through. ## Parameters ### schema [`AnySchema`](../type-aliases/AnySchema.md) ### value `unknown` ## Returns `Promise`<[`ValidationResult`](../type-aliases/ValidationResult.md)> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/functions/websocketAsyncAPI.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / websocketAsyncAPI # Function: websocketAsyncAPI() > **websocketAsyncAPI**<`Path`, `Channel`, `T`>(`url`, `path`, `options?`): `object` Defined in: .api-entries/client/index.d.ts:254 ## Type Parameters ### Path `Path` *extends* `any` ### Channel `Channel` *extends* `any` ### T `T` = { `commandMap`: `any`; `eventMap`: `any`; `rpcMap`: `any`; `serverRpcMap`: `any`; `streamMap`: `any`; `authCredentials`: `any`; `presenceState`: `any`; } ## Parameters ### url `string` ### path `Path` ### options? [`WebsocketAsyncAPIOptions`](../interfaces/WebsocketAsyncAPIOptions.md)<`any`, `any`> ## Returns ### ~original > `readonly` **~original**: [`WebSocketLike`](../interfaces/WebSocketLike.md) ### connected > `readonly` **connected**: `boolean` ### sessionId > `readonly` **sessionId**: `string` Server-assigned session id (stable across reconnects). ### recovered > `readonly` **recovered**: `boolean` Whether the most recent (re)connect recovered missed events. ### opened > **opened**: `Promise`<`void`> ### onRecover() > **onRecover**(`callback`): () => `boolean` Fires after each (re)connect handshake with whether the session was recovered (`true` = missed events were replayed, `false` = clean (re)subscribe). Useful to refetch state only when recovery failed. #### Parameters ##### callback (`recovered`) => `void` #### Returns () => `boolean` ### onOpen() > **onOpen**(`callback`): () => `boolean` #### Parameters ##### callback (`data`) => `void` #### Returns () => `boolean` ### onClose() > **onClose**(`callback`): () => `boolean` #### Parameters ##### callback (`data`) => `void` #### Returns () => `boolean` ### onError() > **onError**(`callback`): () => `boolean` #### Parameters ##### callback (`event`) => `void` #### Returns () => `boolean` ### onEvent > **onEvent**: <`Event`>(`eventName`, `callback`) => () => `boolean` #### Type Parameters ##### Event `Event` *extends* `string` | `number` | `symbol` #### Parameters ##### eventName `Event` ##### callback (`data`) => `void` #### Returns () => `boolean` ### onRequest > **onRequest**: <`Name`>(`name`, `handler`) => () => `boolean` #### Type Parameters ##### Name `Name` *extends* `string` | `number` | `symbol` #### Parameters ##### name `Name` ##### handler (`input`) => `MaybePromise`<`T`\[`"serverRpcMap"`]\[`Name`]\[`"output"`]> #### Returns () => `boolean` ### call > **call**: <`Command`>(`command`, ...`data`) => `void` #### Type Parameters ##### Command `Command` *extends* `string` | `number` | `symbol` #### Parameters ##### command `Command` ##### data ...`T`\[`"commandMap"`]\[`Command`] *extends* `never` ? \[] : \[`T`\[`"commandMap"`]\[`Command`]] #### Returns `void` ### request > **request**: <`Command`>(`command`, `input`, `options?`) => `Promise`<`T`\[`"rpcMap"`]\[`Command`]\[`"output"`]> #### Type Parameters ##### Command `Command` *extends* `string` | `number` | `symbol` #### Parameters ##### command `Command` ##### input `T`\[`"rpcMap"`]\[`Command`]\[`"input"`] ##### options? [`RequestOptions`](../interfaces/RequestOptions.md) #### Returns `Promise`<`T`\[`"rpcMap"`]\[`Command`]\[`"output"`]> ### stream > **stream**: <`Name`>(`name`, `input`) => `AsyncIterable`<`T`\[`"streamMap"`]\[`Name`]\[`"output"`]> Open a typed stream and consume it with `for await`. Stopping iteration (a `break`, `return`, or throw) sends a StreamStop so the server cancels the handler. A server-side error surfaces as a thrown `RpcError`. #### Type Parameters ##### Name `Name` *extends* `string` | `number` | `symbol` #### Parameters ##### name `Name` ##### input `T`\[`"streamMap"`]\[`Name`]\[`"input"`] #### Returns `AsyncIterable`<`T`\[`"streamMap"`]\[`Name`]\[`"output"`]> ### safeRequest > **safeRequest**: <`Command`>(`command`, `input`, `options?`) => `Promise`<[`SafeResult`](../type-aliases/SafeResult.md)<`T`\[`"rpcMap"`]\[`Command`]\[`"output"`], `T`\[`"rpcMap"`]\[`Command`]\[`"errors"`]>> Like [request](#websocketasyncapi), but never throws: returns a typed, discriminated `{ data, error }` result. Narrow on `error` (and `error.code`) to get the declared error's typed `data`. #### Type Parameters ##### Command `Command` *extends* `string` | `number` | `symbol` #### Parameters ##### command `Command` ##### input `T`\[`"rpcMap"`]\[`Command`]\[`"input"`] ##### options? [`RequestOptions`](../interfaces/RequestOptions.md) #### Returns `Promise`<[`SafeResult`](../type-aliases/SafeResult.md)<`T`\[`"rpcMap"`]\[`Command`]\[`"output"`], `T`\[`"rpcMap"`]\[`Command`]\[`"errors"`]>> ### authenticate > **authenticate**: (`credentials`) => `Promise`<`void`> Refresh credentials on the live connection (token refresh). The server re-runs `.onAuth` and replaces the connection context — no reconnect. The credentials are remembered and re-sent automatically after a reconnect. Rejects with a typed `RpcError` if the server rejects them. #### Parameters ##### credentials `T`\[`"authCredentials"`] #### Returns `Promise`<`void`> ### presence > **presence**: `object` #### presence.self > `readonly` **self**: `string` #### presence.set > **set**: (`state`) => `Promise`<`void`> ##### Parameters ###### state `T`\[`"presenceState"`] ##### Returns `Promise`<`void`> #### presence.update > **update**: (`patch`) => `void` ##### Parameters ###### patch `Partial`<`T`\[`"presenceState"`]> ##### Returns `void` #### presence.clear > **clear**: () => `Promise`<`void`> ##### Returns `Promise`<`void`> #### presence.get > **get**: () => `Map`<`string`, `T`\[`"presenceState"`]> ##### Returns `Map`<`string`, `T`\[`"presenceState"`]> #### presence.subscribe > **subscribe**: (`callback`) => () => `void` ##### Parameters ###### callback (`members`) => `void` ##### Returns () => `void` ### history > **history**: (`room`, `options?`) => `Promise`<`unknown`\[]> #### Parameters ##### room `string` ##### options? ###### limit? `number` #### Returns `Promise`<`unknown`\[]> ### close() > **close**(`code?`, `reason?`): `void` #### Parameters ##### code? `number` ##### reason? `string` #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/interfaces/Backplane.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / Backplane # Interface: Backplane Defined in: .api-entries/core/index.d.ts:314 ## Properties ### nodeId > `readonly` **nodeId**: `string` Defined in: .api-entries/core/index.d.ts:316 unique id of this server node ## Methods ### publish() > **publish**(`topic`, `payload`, `offset?`, `except?`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:322 Fan a message out to all nodes; each delivers locally to subscribers. When `offset` is supplied (recovery-capable backplanes) the message is also appended to the replay log under that offset. #### Parameters ##### topic `string` ##### payload `string` | `Uint8Array`<`ArrayBufferLike`> ##### offset? `string` | `number` ##### except? `string`\[] #### Returns `Promise`<`void`> *** ### onMessage() > **onMessage**(`handler`): `void` Defined in: .api-entries/core/index.d.ts:324 Register the local delivery callback (called once by the adapter). #### Parameters ##### handler (`message`) => `void` #### Returns `void` *** ### addToRoom() > **addToRoom**(`topic`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:326 Record that a local socket joined a room (topic). #### Parameters ##### topic `string` ##### socketId `string` #### Returns `Promise`<`void`> *** ### removeFromRoom() > **removeFromRoom**(`topic`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:328 Record that a local socket left a room (topic). #### Parameters ##### topic `string` ##### socketId `string` #### Returns `Promise`<`void`> *** ### removeSocket() > **removeSocket**(`socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:330 Remove a socket from all rooms (on disconnect). #### Parameters ##### socketId `string` #### Returns `Promise`<`void`> *** ### roomMembers() > **roomMembers**(`topic`): `Promise`<`string`\[]> Defined in: .api-entries/core/index.d.ts:332 Cluster-wide socket ids in a room (presence / fetchSockets). #### Parameters ##### topic `string` #### Returns `Promise`<`string`\[]> *** ### rooms() > **rooms**(`socketId`): `Promise`<`string`\[]> Defined in: .api-entries/core/index.d.ts:334 Rooms a socket currently belongs to. #### Parameters ##### socketId `string` #### Returns `Promise`<`string`\[]> *** ### assignOffset()? > `optional` **assignOffset**(): [`MaybePromise`](../type-aliases/MaybePromise.md)<`string` | `number`> Defined in: .api-entries/core/index.d.ts:336 Vend the next monotonic, cluster-wide offset for an outgoing event. #### Returns [`MaybePromise`](../type-aliases/MaybePromise.md)<`string` | `number`> *** ### replaySince()? > `optional` **replaySince**(`offset`, `topics`): `Promise`<[`BackplaneMessage`](BackplaneMessage.md)\[]> Defined in: .api-entries/core/index.d.ts:341 Replay buffered events for the given `topics` whose offset is strictly greater than `offset`, in global publish order. #### Parameters ##### offset `string` | `number` ##### topics `string`\[] #### Returns `Promise`<[`BackplaneMessage`](BackplaneMessage.md)\[]> *** ### setPresence()? > `optional` **setPresence**(`room`, `socketId`, `state`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:343 Store (or replace) a member's presence state in a room. #### Parameters ##### room `string` ##### socketId `string` ##### state `unknown` #### Returns `Promise`<`void`> *** ### clearPresence()? > `optional` **clearPresence**(`room`, `socketId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:345 Remove a member from a room's presence roster. #### Parameters ##### room `string` ##### socketId `string` #### Returns `Promise`<`void`> *** ### getPresence()? > `optional` **getPresence**(`room`): `Promise`<`Record`<`string`, `unknown`>> Defined in: .api-entries/core/index.d.ts:347 Current roster of a presence room: socket id → state. #### Parameters ##### room `string` #### Returns `Promise`<`Record`<`string`, `unknown`>> *** ### configureHistory()? > `optional` **configureHistory**(`events`): `void` Defined in: .api-entries/core/index.d.ts:349 Register which event names to retain and how many (event name → keep). #### Parameters ##### events `Record`<`string`, `number`> #### Returns `void` *** ### appendHistory()? > `optional` **appendHistory**(`topic`, `event`, `data`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:351 Append an event to a room's history (no-op if the event isn't retained). #### Parameters ##### topic `string` ##### event `string` ##### data `unknown` #### Returns `Promise`<`void`> *** ### getHistory()? > `optional` **getHistory**(`topic`, `limit?`): `Promise`<`object`\[]> Defined in: .api-entries/core/index.d.ts:353 Fetch a room's retained events (most-recent `limit`, or all), in order. #### Parameters ##### topic `string` ##### limit? `number` #### Returns `Promise`<`object`\[]> *** ### saveSession()? > `optional` **saveSession**(`sessionId`, `state`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:358 Persist a disconnecting connection's recoverable state for `ttlMs`. #### Parameters ##### sessionId `string` ##### state [`SessionState`](SessionState.md) #### Returns `Promise`<`void`> *** ### loadSession()? > `optional` **loadSession**(`sessionId`): `Promise`<[`SessionState`](SessionState.md)> Defined in: .api-entries/core/index.d.ts:360 Load a reconnecting connection's state, or null if expired/unknown. #### Parameters ##### sessionId `string` #### Returns `Promise`<[`SessionState`](SessionState.md)> *** ### dropSession()? > `optional` **dropSession**(`sessionId`): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:362 Drop a session once it has been recovered (or on hard close). #### Parameters ##### sessionId `string` #### Returns `Promise`<`void`> *** ### close() > **close**(): `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:363 #### Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/BackplaneMessage.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / BackplaneMessage # Interface: BackplaneMessage Defined in: .api-entries/core/index.d.ts:293 A message delivered to a node for local fan-out. ## Properties ### topic > **topic**: `string` Defined in: .api-entries/core/index.d.ts:294 *** ### payload > **payload**: `string` | `Uint8Array`<`ArrayBufferLike`> Defined in: .api-entries/core/index.d.ts:296 already codec-encoded frame, ready to hand to the server's publish *** ### origin > **origin**: `string` Defined in: .api-entries/core/index.d.ts:298 node id that originated the message (skip when it equals our nodeId) *** ### offset? > `optional` **offset?**: `string` | `number` Defined in: .api-entries/core/index.d.ts:300 monotonic, cluster-wide offset, when the backplane supports replay *** ### except? > `optional` **except?**: `string`\[] Defined in: .api-entries/core/index.d.ts:302 socket ids to skip on local delivery (e.g. exclude the sender) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/interfaces/CachedRpc.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / CachedRpc # Interface: CachedRpc Defined in: .api-entries/core/index.d.ts:534 The settled outcome of an RPC, replayable to duplicate requests. ## Properties ### ok > **ok**: `boolean` Defined in: .api-entries/core/index.d.ts:535 *** ### payload? > `optional` **payload?**: `unknown` Defined in: .api-entries/core/index.d.ts:537 present when `ok` — the reply payload *** ### code? > `optional` **code?**: `ErrorCode` Defined in: .api-entries/core/index.d.ts:539 present when `!ok` *** ### message? > `optional` **message?**: `string` Defined in: .api-entries/core/index.d.ts:540 *** ### data? > `optional` **data?**: `unknown` Defined in: .api-entries/core/index.d.ts:541 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/CloseEvent.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / CloseEvent # Interface: CloseEvent Defined in: .api-entries/client/index.d.ts:12 ## Properties ### wasClean > **wasClean**: `boolean` Defined in: .api-entries/client/index.d.ts:13 *** ### code > **code**: `number` Defined in: .api-entries/client/index.d.ts:14 *** ### reason > **reason**: `string` Defined in: .api-entries/client/index.d.ts:15 *** ### type > **type**: `string` Defined in: .api-entries/client/index.d.ts:16 *** ### target > **target**: `WebSocket` Defined in: .api-entries/client/index.d.ts:17 --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/interfaces/Connection.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / Connection # Interface: Connection Defined in: .api-entries/core/index.d.ts:465 Mutable per-connection state shared across a socket's lifetime. ## Properties ### ws > `readonly` **ws**: [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`any`, `any`> Defined in: .api-entries/core/index.d.ts:467 the adapter's WebSocket implementation for this socket *** ### request > `readonly` **request**: [`RequestData`](RequestData.md)<`any`, `any`, `any`> Defined in: .api-entries/core/index.d.ts:469 connection request data (query / headers / params) *** ### data > **data**: `any` Defined in: .api-entries/core/index.d.ts:471 derived context bag (filled by [openConnection](../functions/openConnection.md)) *** ### sessionId? > `optional` **sessionId?**: `string` Defined in: .api-entries/core/index.d.ts:473 recovery session id, assigned on the Hello handshake *** ### outbound? > `optional` **outbound?**: [`OutboundRpc`](../classes/OutboundRpc.md) Defined in: .api-entries/core/index.d.ts:475 pending server→client (outbound) RPCs for this connection *** ### streams? > `optional` **streams?**: [`StreamRegistry`](../classes/StreamRegistry.md) Defined in: .api-entries/core/index.d.ts:477 active streams for this connection (for cancel / abort-on-close) *** ### presenceRoom? > `optional` **presenceRoom?**: `string` Defined in: .api-entries/core/index.d.ts:479 this connection's presence room (set on open when `.presence` is enabled) *** ### isPresent? > `optional` **isPresent?**: `boolean` Defined in: .api-entries/core/index.d.ts:482 whether this connection currently has presence state announced (so close knows to emit a leave) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/interfaces/CursorPoint.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / CursorPoint # Interface: CursorPoint Defined in: .api-entries/cursors/index.d.ts:25 A 2D cursor point. ## Properties ### x > **x**: `number` Defined in: .api-entries/cursors/index.d.ts:26 *** ### y > **y**: `number` Defined in: .api-entries/cursors/index.d.ts:27 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/interfaces/CursorsClient.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / CursorsClient # Interface: CursorsClient\ Defined in: .api-entries/cursors/index.d.ts:49 The slice of a ws-asyncapi client [cursorsStore](../functions/cursorsStore.md) needs (structurally satisfied by `WsClient`); generic over the channel's presence state `S`. ## Type Parameters ### S `S` ## Properties ### presence > **presence**: `object` Defined in: .api-entries/cursors/index.d.ts:50 #### self > `readonly` **self**: `string` #### subscribe() > **subscribe**(`cb`): () => `void` ##### Parameters ###### cb (`members`) => `void` ##### Returns () => `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/interfaces/CursorSmoother.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / CursorSmoother # Interface: CursorSmoother Defined in: .api-entries/cursors/index.d.ts:35 Pluggable receiver-side smoothing. The interface is exactly what `perfect-cursors` implements (`new PerfectCursor(onChange)` has `addPoint`/`dispose`), so it's a drop-in **without being a dependency** — pass `(cb) => new PerfectCursor(cb)`, the built-in [lerpSmoother](../variables/lerpSmoother.md), or omit it. ## Methods ### addPoint() > **addPoint**(`point`): `void` Defined in: .api-entries/cursors/index.d.ts:36 #### Parameters ##### point \[`number`, `number`] #### Returns `void` *** ### dispose() > **dispose**(): `void` Defined in: .api-entries/cursors/index.d.ts:37 #### Returns `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/interfaces/CursorsOptions.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / CursorsOptions # Interface: CursorsOptions\ Defined in: .api-entries/cursors/index.d.ts:56 Options for [cursorsStore](../functions/cursorsStore.md). ## Type Parameters ### S `S` ## Properties ### field? > `optional` **field?**: (`state`) => [`CursorPoint`](CursorPoint.md) Defined in: .api-entries/cursors/index.d.ts:58 extract the cursor point from a member's presence state (default: `.cursor`) #### Parameters ##### state `S` #### Returns [`CursorPoint`](CursorPoint.md) *** ### smoothing? > `optional` **smoothing?**: `false` | [`SmootherFactory`](../type-aliases/SmootherFactory.md) Defined in: .api-entries/cursors/index.d.ts:61 receiver smoothing: a [SmootherFactory](../type-aliases/SmootherFactory.md), or `false` for raw last-write (default: [lerpSmoother](../variables/lerpSmoother.md)) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/emitter/interfaces/EmitterOptions.md --- [ws-asyncapi API](../../index.md) / [emitter](../index.md) / EmitterOptions # Interface: EmitterOptions Defined in: .api-entries/emitter/index.d.ts:3 ## Properties ### codec? > `optional` **codec?**: `Codec` Defined in: .api-entries/emitter/index.d.ts:5 wire codec (default: JSON). Must match the servers' codec. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/HeartbeatOptions.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / HeartbeatOptions # Interface: HeartbeatOptions Defined in: .api-entries/client/index.d.ts:34 ## Properties ### interval? > `optional` **interval?**: `number` Defined in: .api-entries/client/index.d.ts:36 how often to send a ping in ms (default: 25\_000) *** ### timeout? > `optional` **timeout?**: `number` Defined in: .api-entries/client/index.d.ts:38 how long to wait for a pong before reconnecting in ms (default: 10\_000) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/IdempotencyOptions.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / IdempotencyOptions # Interface: IdempotencyOptions Defined in: .api-entries/core/index.d.ts:543 ## Properties ### ttlMs? > `optional` **ttlMs?**: `number` Defined in: .api-entries/core/index.d.ts:545 how long a key's result is retained (default: 120\_000ms, matching NATS) *** ### maxKeys? > `optional` **maxKeys?**: `number` Defined in: .api-entries/core/index.d.ts:547 max distinct keys retained; oldest evicted past this (default: 10\_000) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/LocalBackplaneOptions.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / LocalBackplaneOptions # Interface: LocalBackplaneOptions Defined in: .api-entries/core/index.d.ts:370 In-process backplane: delivers published messages straight back to the local node and tracks membership in memory. Behaviorally identical to the original single-process pub/sub, but also powers presence/`roomMembers` on one node. ## Properties ### recovery? > `optional` **recovery?**: `false` | { `bufferSize?`: `number`; `sessionTTL?`: `number`; } Defined in: .api-entries/core/index.d.ts:375 Connection-state-recovery tuning. Pass `false` to disable the replay log (smaller memory footprint, no recovery). Default: enabled. #### Union Members `false` *** ##### Type Literal { `bufferSize?`: `number`; `sessionTTL?`: `number`; } ##### bufferSize? > `optional` **bufferSize?**: `number` max events retained in the replay log (default: 10\_000) ##### sessionTTL? > `optional` **sessionTTL?**: `number` how long a disconnected session is recoverable (default: 120\_000ms) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/MessageHandlerSchema.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / MessageHandlerSchema # Interface: MessageHandlerSchema\ Defined in: .api-entries/core/index.d.ts:230 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Message `Message` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Properties ### handler > **handler**: [`MessageHandler`](../type-aliases/MessageHandler.md)<`WebsocketData`, `Topics`, `Message`, `Query`, `Headers`, `Params`, `Data`> Defined in: .api-entries/core/index.d.ts:231 *** ### validation? > `optional` **validation?**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:232 --- --- url: 'https://ws-asyncapi.github.io/documentation/api/client/interfaces/OpenEvent.md' --- [ws-asyncapi API](../../index.md) / [client](../index.md) / OpenEvent # Interface: OpenEvent Defined in: .api-entries/client/index.d.ts:19 ## Properties ### type > **type**: `string` Defined in: .api-entries/client/index.d.ts:20 *** ### target > **target**: `WebSocket` Defined in: .api-entries/client/index.d.ts:21 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/solid/interfaces/PresenceAccessors.md --- [ws-asyncapi API](../../index.md) / [solid](../index.md) / PresenceAccessors # Interface: PresenceAccessors\ Defined in: .api-entries/solid/index.d.ts:41 Reactive presence surface from [SolidClient.createPresence](SolidClient.md#createpresence). ## Type Parameters ### State `State` ## Properties ### members > **members**: `Accessor`<`Map`<`string`, `State`>> Defined in: .api-entries/solid/index.d.ts:42 *** ### self > **self**: `Accessor`<`string`> Defined in: .api-entries/solid/index.d.ts:43 *** ### set > **set**: (`state`) => `Promise`<`void`> Defined in: .api-entries/solid/index.d.ts:44 #### Parameters ##### state `State` #### Returns `Promise`<`void`> *** ### update > **update**: (`patch`) => `void` Defined in: .api-entries/solid/index.d.ts:46 volatile, fire-and-forget update (cursor hot path) — see `presence.update` #### Parameters ##### patch `Partial`<`State`> #### Returns `void` *** ### clear > **clear**: () => `Promise`<`void`> Defined in: .api-entries/solid/index.d.ts:47 #### Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/PresenceApi.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / PresenceApi # Interface: PresenceApi\ Defined in: .api-entries/client/index.d.ts:189 The `client.presence` surface, typed by the channel's `.presence` schema. ## Type Parameters ### State `State` ## Properties ### self > `readonly` **self**: `string` Defined in: .api-entries/client/index.d.ts:191 this connection's own socket id (known once the roster is hydrated) ## Methods ### set() > **set**(`state`): `Promise`<`void`> Defined in: .api-entries/client/index.d.ts:197 Announce or update this connection's presence state. Resolves once the server has accepted it and returned the current roster (which hydrates [get](#get)/[subscribe](#subscribe)); rejects with an `RpcError` if rejected. #### Parameters ##### state `State` #### Returns `Promise`<`void`> *** ### update() > **update**(`patch`): `void` Defined in: .api-entries/client/index.d.ts:205 **Volatile** presence update — the cursor hot path. Fire-and-forget (no ack, no roster snapshot), last-write-wins, dropped while offline, and coalesced to the latest per `presenceThrottle` window. Merges the patch into the last-known state, so `update({ cursor })` keeps other fields. Call [set](#set) once first to join the roster. #### Parameters ##### patch `Partial`<`State`> #### Returns `void` *** ### clear() > **clear**(): `Promise`<`void`> Defined in: .api-entries/client/index.d.ts:207 Leave presence (stay connected). Other members receive a leave diff. #### Returns `Promise`<`void`> *** ### get() > **get**(): `Map`<`string`, `State`> Defined in: .api-entries/client/index.d.ts:209 The current cached roster: socket id → state. #### Returns `Map`<`string`, `State`> *** ### subscribe() > **subscribe**(`callback`): () => `void` Defined in: .api-entries/client/index.d.ts:215 Observe the roster live. The callback fires with the full roster on every change (join/leave/update). Returns an unsubscribe function. The first subscriber triggers a snapshot fetch if the roster isn't hydrated yet. #### Parameters ##### callback (`members`) => `void` #### Returns () => `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/react/interfaces/PresenceResult.md --- [ws-asyncapi API](../../index.md) / [react](../index.md) / PresenceResult # Interface: PresenceResult\ Defined in: .api-entries/react/index.d.ts:37 ## Type Parameters ### State `State` ## Properties ### members > **members**: `Map`<`string`, `State`> Defined in: .api-entries/react/index.d.ts:38 *** ### self > **self**: `string` Defined in: .api-entries/react/index.d.ts:39 *** ### set > **set**: (`state`) => `Promise`<`void`> Defined in: .api-entries/react/index.d.ts:40 #### Parameters ##### state `State` #### Returns `Promise`<`void`> *** ### update > **update**: (`patch`) => `void` Defined in: .api-entries/react/index.d.ts:42 volatile, fire-and-forget update (cursor hot path) — see `presence.update` #### Parameters ##### patch `Partial`<`State`> #### Returns `void` *** ### clear > **clear**: () => `Promise`<`void`> Defined in: .api-entries/react/index.d.ts:43 #### Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/interfaces/PresenceSnapshotState.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / PresenceSnapshotState # Interface: PresenceSnapshotState Defined in: .api-entries/query-core/index.d.ts:99 Snapshot of a [presenceStore](../functions/presenceStore.md). ## Properties ### members > **members**: `Map`<`string`, `unknown`> Defined in: .api-entries/query-core/index.d.ts:100 *** ### self > **self**: `string` Defined in: .api-entries/query-core/index.d.ts:101 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/interfaces/QueryCoreClient.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / QueryCoreClient # Interface: QueryCoreClient Defined in: .api-entries/query-core/index.d.ts:20 The subset of a ws-asyncapi client these helpers use (structurally satisfied by `WsClient`). Kept loose here; the bindings layer on the precise types. ## Properties ### connected > `readonly` **connected**: `boolean` Defined in: .api-entries/query-core/index.d.ts:33 *** ### recovered > `readonly` **recovered**: `boolean` Defined in: .api-entries/query-core/index.d.ts:34 *** ### presence > **presence**: `object` Defined in: .api-entries/query-core/index.d.ts:35 #### get() > **get**(): `Map`<`string`, `unknown`> ##### Returns `Map`<`string`, `unknown`> #### self > `readonly` **self**: `string` #### set() > **set**(`state`): `Promise`<`void`> ##### Parameters ###### state `unknown` ##### Returns `Promise`<`void`> #### update() > **update**(`patch`): `void` ##### Parameters ###### patch `unknown` ##### Returns `void` #### clear() > **clear**(): `Promise`<`void`> ##### Returns `Promise`<`void`> #### subscribe() > **subscribe**(`cb`): () => `void` ##### Parameters ###### cb (`members`) => `void` ##### Returns () => `void` ## Methods ### request() > **request**(`command`, `input`, `options?`): `Promise`<`unknown`> Defined in: .api-entries/query-core/index.d.ts:21 #### Parameters ##### command `string` ##### input `unknown` ##### options? `unknown` #### Returns `Promise`<`unknown`> *** ### history() > **history**(`room`, `options?`): `Promise`<`object`\[]> Defined in: .api-entries/query-core/index.d.ts:22 #### Parameters ##### room `string` ##### options? ###### limit? `number` #### Returns `Promise`<`object`\[]> *** ### stream() > **stream**(`name`, `input`): `AsyncIterable`<`unknown`> Defined in: .api-entries/query-core/index.d.ts:28 #### Parameters ##### name `string` ##### input `unknown` #### Returns `AsyncIterable`<`unknown`> *** ### onEvent() > **onEvent**(`event`, `cb`): () => `void` Defined in: .api-entries/query-core/index.d.ts:29 #### Parameters ##### event `string` ##### cb (`data`) => `void` #### Returns () => `void` *** ### onOpen() > **onOpen**(`cb`): () => `void` Defined in: .api-entries/query-core/index.d.ts:30 #### Parameters ##### cb () => `void` #### Returns () => `void` *** ### onClose() > **onClose**(`cb`): () => `void` Defined in: .api-entries/query-core/index.d.ts:31 #### Parameters ##### cb () => `void` #### Returns () => `void` *** ### onRecover() > **onRecover**(`cb`): () => `void` Defined in: .api-entries/query-core/index.d.ts:32 #### Parameters ##### cb (`recovered`) => `void` #### Returns () => `void` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/react/interfaces/ReactClient.md --- [ws-asyncapi API](../../index.md) / [react](../index.md) / ReactClient # Interface: ReactClient\ Defined in: .api-entries/react/index.d.ts:45 ## Type Parameters ### T `T` *extends* `Shape` ## Properties ### client > **client**: `WsClient`<`T`> Defined in: .api-entries/react/index.d.ts:48 the underlying, precisely-typed client (escape hatch: `opened`, raw `request`, `presence.update`, …; also what `cursorsStore` consumes) ## Methods ### useRequest() > **useRequest**<`C`>(`command`, `input`, `options?`): `UseQueryResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> Defined in: .api-entries/react/index.d.ts:49 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### input `T`\[`"rpcMap"`]\[`C`]\[`"input"`] ##### options? `Omit`<`UseQueryOptions`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>>, `"queryKey"` | `"queryFn"`> #### Returns `UseQueryResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> *** ### useMutate() > **useMutate**<`C`>(`command`, `options?`): `UseMutationResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>, `T`\[`"rpcMap"`]\[`C`]\[`"input"`]> Defined in: .api-entries/react/index.d.ts:50 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### options? `Omit`<`UseMutationOptions`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>, `T`\[`"rpcMap"`]\[`C`]\[`"input"`]>, `"mutationFn"`> #### Returns `UseMutationResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>, `T`\[`"rpcMap"`]\[`C`]\[`"input"`]> *** ### usePresence() > **usePresence**(): [`PresenceResult`](PresenceResult.md)<`T`\[`"presenceState"`]> Defined in: .api-entries/react/index.d.ts:51 #### Returns [`PresenceResult`](PresenceResult.md)<`T`\[`"presenceState"`]> *** ### useHistory() > **useHistory**(`room`, `options?`): `UseQueryResult`<`HistoryEntry`<`T`\[`"eventMap"`]>\[], [`RpcError`](../../client/classes/RpcError.md)> Defined in: .api-entries/react/index.d.ts:52 #### Parameters ##### room `string` ##### options? ###### liveEvent? keyof `T`\[`"eventMap"`] & `string` ###### limit? `number` #### Returns `UseQueryResult`<`HistoryEntry`<`T`\[`"eventMap"`]>\[], [`RpcError`](../../client/classes/RpcError.md)> *** ### useStream() #### Call Signature > **useStream**<`N`>(`name`, `input`): [`StreamResult`](StreamResult.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> Defined in: .api-entries/react/index.d.ts:56 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ##### Returns [`StreamResult`](StreamResult.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> #### Call Signature > **useStream**<`N`>(`name`, `input`, `options`): [`StreamResult`](StreamResult.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]\[]> Defined in: .api-entries/react/index.d.ts:57 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ###### options ###### reduce `"append"` ###### max? `number` ##### Returns [`StreamResult`](StreamResult.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]\[]> #### Call Signature > **useStream**<`N`, `Acc`>(`name`, `input`, `options`): [`StreamResult`](StreamResult.md)<`Acc`> Defined in: .api-entries/react/index.d.ts:61 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ###### Acc `Acc` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ###### options ###### reduce (`acc`, `item`) => `Acc` ###### initial `Acc` ##### Returns [`StreamResult`](StreamResult.md)<`Acc`> *** ### useLastEvent() > **useLastEvent**<`E`>(`event`): `T`\[`"eventMap"`]\[`E`] Defined in: .api-entries/react/index.d.ts:65 #### Type Parameters ##### E `E` *extends* `string` | `number` | `symbol` #### Parameters ##### event `E` #### Returns `T`\[`"eventMap"`]\[`E`] *** ### useEvent() > **useEvent**<`E`>(`event`, `handler`): `void` Defined in: .api-entries/react/index.d.ts:66 #### Type Parameters ##### E `E` *extends* `string` | `number` | `symbol` #### Parameters ##### event `E` ##### handler (`data`, `queryClient`) => `void` #### Returns `void` *** ### useConnection() > **useConnection**(): `object` Defined in: .api-entries/react/index.d.ts:67 #### Returns `object` ##### connected > **connected**: `boolean` ##### recovered > **recovered**: `boolean` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/ReconnectOptions.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / ReconnectOptions # Interface: ReconnectOptions Defined in: .api-entries/client/index.d.ts:26 ## Properties ### maxRetries? > `optional` **maxRetries?**: `number` Defined in: .api-entries/client/index.d.ts:28 max reconnection attempts before giving up (default: Infinity) *** ### baseDelay? > `optional` **baseDelay?**: `number` Defined in: .api-entries/client/index.d.ts:30 base backoff delay in ms (default: 500) *** ### maxDelay? > `optional` **maxDelay?**: `number` Defined in: .api-entries/client/index.d.ts:32 max backoff delay in ms (default: 10\_000) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/RemoteSocketInfo.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / RemoteSocketInfo # Interface: RemoteSocketInfo Defined in: .api-entries/core/index.d.ts:660 A socket as seen by server-side listing (`channel.fetchSockets`). ## Properties ### id > **id**: `string` Defined in: .api-entries/core/index.d.ts:661 *** ### rooms > **rooms**: `string`\[] Defined in: .api-entries/core/index.d.ts:663 rooms (topics) the socket is in, excluding its reserved per-socket room --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/interfaces/RequestData.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / RequestData # Interface: RequestData\ Defined in: .api-entries/core/index.d.ts:219 ## Type Parameters ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ## Properties ### query > **query**: `Query` Defined in: .api-entries/core/index.d.ts:220 *** ### headers > **headers**: `Headers` Defined in: .api-entries/core/index.d.ts:221 *** ### params > **params**: `Params` Defined in: .api-entries/core/index.d.ts:222 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/RequestOptions.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / RequestOptions # Interface: RequestOptions Defined in: .api-entries/client/index.d.ts:95 ## Properties ### timeout? > `optional` **timeout?**: `number` Defined in: .api-entries/client/index.d.ts:97 override the default RPC timeout for this call (ms) *** ### idempotencyKey? > `optional` **idempotencyKey?**: `string` Defined in: .api-entries/client/index.d.ts:104 Stable idempotency key. When set, the server runs the handler once per key and replays the cached result to duplicates — so retrying the same call (e.g. after a reconnect) won't execute side effects twice. Generate one key per logical action and reuse it across retries. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/RpcDefinition.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / RpcDefinition # Interface: RpcDefinition Defined in: .api-entries/core/index.d.ts:666 Stored RPC definition (input/output schemas + handler) on a channel. ## Properties ### input > **input**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:667 *** ### output > **output**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:668 *** ### errors? > `optional` **errors?**: `Record`<`string`, [`AnySchema`](../type-aliases/AnySchema.md)> Defined in: .api-entries/core/index.d.ts:674 Declared, recoverable error codes for this RPC, each with the schema of its `data` payload. Surfaced in the contract + generated client so the caller gets a typed, discriminated error union (see [Channel.rpc](../classes/Channel.md#rpc)). *** ### handler > **handler**: [`RpcHandler`](../type-aliases/RpcHandler.md)<`any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`> Defined in: .api-entries/core/index.d.ts:675 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/ServerPlugin.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ServerPlugin # Interface: ServerPlugin Defined in: .api-entries/core/index.d.ts:67 ## Properties ### name? > `optional` **name?**: `string` Defined in: .api-entries/core/index.d.ts:69 optional name (diagnostics) ## Methods ### onConnection()? > `optional` **onConnection**(`ctx`): `void` | `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:71 a connection opened (after derives/onOpen ran) #### Parameters ##### ctx [`ServerPluginContext`](ServerPluginContext.md) & `object` #### Returns `void` | `Promise`<`void`> *** ### onDisconnect()? > `optional` **onDisconnect**(`ctx`): `void` | `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:75 a connection closed #### Parameters ##### ctx [`ServerPluginContext`](ServerPluginContext.md) #### Returns `void` | `Promise`<`void`> *** ### onMessage()? > `optional` **onMessage**(`ctx`): `void` | `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:78 an inbound frame was received (`kind` is the numeric `Frame`; `name` is the event/command/rpc/stream name when the frame carries one) #### Parameters ##### ctx [`ServerPluginContext`](ServerPluginContext.md) & `object` #### Returns `void` | `Promise`<`void`> *** ### onError()? > `optional` **onError**(`ctx`): `void` | `Promise`<`void`> Defined in: .api-entries/core/index.d.ts:83 a command/middleware/handler error surfaced #### Parameters ##### ctx [`ServerPluginContext`](ServerPluginContext.md) & `object` #### Returns `void` | `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/ServerPluginContext.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ServerPluginContext # Interface: ServerPluginContext Defined in: .api-entries/core/index.d.ts:61 Context shared by every server-plugin hook. ## Properties ### channel > **channel**: [`AnyChannel`](../type-aliases/AnyChannel.md) Defined in: .api-entries/core/index.d.ts:63 the channel the event occurred on *** ### socketId > **socketId**: `string` Defined in: .api-entries/core/index.d.ts:65 the socket id involved --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/ServerRpcDefinition.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ServerRpcDefinition # Interface: ServerRpcDefinition Defined in: .api-entries/core/index.d.ts:679 Stored server→client RPC definition (input/output schemas only; the handler lives on the client). Used by the doc generator to emit the contract. ## Properties ### input > **input**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:680 *** ### output > **output**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:681 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/SessionState.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / SessionState # Interface: SessionState Defined in: .api-entries/core/index.d.ts:310 A connection's recoverable state, persisted while it is briefly disconnected so a reconnecting client can be restored (rooms re-joined + missed events replayed). Held for a short TTL by the backplane. ## Properties ### rooms > **rooms**: `string`\[] Defined in: .api-entries/core/index.d.ts:312 rooms (topics) the socket was subscribed to at disconnect --- --- url: >- https://ws-asyncapi.github.io/documentation/api/solid/interfaces/SolidClient.md --- [ws-asyncapi API](../../index.md) / [solid](../index.md) / SolidClient # Interface: SolidClient\ Defined in: .api-entries/solid/index.d.ts:49 ## Type Parameters ### T `T` *extends* `Shape` ## Properties ### client > **client**: `WsClient`<`T`> Defined in: .api-entries/solid/index.d.ts:52 the underlying, precisely-typed client (escape hatch: `opened`, raw `request`, `presence.update`, …; also what `cursorsStore` consumes) ## Methods ### createRequest() > **createRequest**<`C`>(`command`, `input`): `UseQueryResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> Defined in: .api-entries/solid/index.d.ts:53 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### input `T`\[`"rpcMap"`]\[`C`]\[`"input"`] | `Accessor`<`T`\[`"rpcMap"`]\[`C`]\[`"input"`]> #### Returns `UseQueryResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> *** ### createMutate() > **createMutate**<`C`>(`command`): `UseMutationResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>, `T`\[`"rpcMap"`]\[`C`]\[`"input"`]> Defined in: .api-entries/solid/index.d.ts:54 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` #### Returns `UseMutationResult`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `TypedRpcError`<`T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>, `T`\[`"rpcMap"`]\[`C`]\[`"input"`]> *** ### createPresence() > **createPresence**(): [`PresenceAccessors`](PresenceAccessors.md)<`T`\[`"presenceState"`]> Defined in: .api-entries/solid/index.d.ts:55 #### Returns [`PresenceAccessors`](PresenceAccessors.md)<`T`\[`"presenceState"`]> *** ### createHistory() > **createHistory**(`room`, `options?`): `UseQueryResult`<`HistoryEntry`<`T`\[`"eventMap"`]>\[], [`RpcError`](../../client/classes/RpcError.md)> Defined in: .api-entries/solid/index.d.ts:56 #### Parameters ##### room `string` ##### options? ###### liveEvent? keyof `T`\[`"eventMap"`] & `string` ###### limit? `number` #### Returns `UseQueryResult`<`HistoryEntry`<`T`\[`"eventMap"`]>\[], [`RpcError`](../../client/classes/RpcError.md)> *** ### createStream() #### Call Signature > **createStream**<`N`>(`name`, `input`): [`StreamAccessors`](StreamAccessors.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> Defined in: .api-entries/solid/index.d.ts:60 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ##### Returns [`StreamAccessors`](StreamAccessors.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> #### Call Signature > **createStream**<`N`>(`name`, `input`, `options`): [`StreamAccessors`](StreamAccessors.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]\[]> Defined in: .api-entries/solid/index.d.ts:61 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ###### options ###### reduce `"append"` ###### max? `number` ##### Returns [`StreamAccessors`](StreamAccessors.md)<`T`\[`"streamMap"`]\[`N`]\[`"output"`]\[]> #### Call Signature > **createStream**<`N`, `Acc`>(`name`, `input`, `options`): [`StreamAccessors`](StreamAccessors.md)<`Acc`> Defined in: .api-entries/solid/index.d.ts:65 ##### Type Parameters ###### N `N` *extends* `string` | `number` | `symbol` ###### Acc `Acc` ##### Parameters ###### name `N` ###### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] ###### options ###### reduce (`acc`, `item`) => `Acc` ###### initial `Acc` ##### Returns [`StreamAccessors`](StreamAccessors.md)<`Acc`> *** ### createLastEvent() > **createLastEvent**<`E`>(`event`): `Accessor`<`T`\[`"eventMap"`]\[`E`]> Defined in: .api-entries/solid/index.d.ts:69 #### Type Parameters ##### E `E` *extends* `string` | `number` | `symbol` #### Parameters ##### event `E` #### Returns `Accessor`<`T`\[`"eventMap"`]\[`E`]> *** ### createEvent() > **createEvent**<`E`>(`event`, `handler`): `void` Defined in: .api-entries/solid/index.d.ts:70 #### Type Parameters ##### E `E` *extends* `string` | `number` | `symbol` #### Parameters ##### event `E` ##### handler (`data`, `queryClient`) => `void` #### Returns `void` *** ### createConnection() > **createConnection**(): `object` Defined in: .api-entries/solid/index.d.ts:71 #### Returns `object` ##### connected > **connected**: `Accessor`<`boolean`> ##### recovered > **recovered**: `Accessor`<`boolean`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/solid/interfaces/StreamAccessors.md --- [ws-asyncapi API](../../index.md) / [solid](../index.md) / StreamAccessors # Interface: StreamAccessors\ Defined in: .api-entries/solid/index.d.ts:35 Reactive result of [SolidClient.createStream](SolidClient.md#createstream). ## Type Parameters ### Data `Data` ## Properties ### data > **data**: `Accessor`<`Data`> Defined in: .api-entries/solid/index.d.ts:36 *** ### isDone > **isDone**: `Accessor`<`boolean`> Defined in: .api-entries/solid/index.d.ts:37 *** ### error > **error**: `Accessor`<[`RpcError`](../../client/classes/RpcError.md)> Defined in: .api-entries/solid/index.d.ts:38 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/StreamDefinition.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / StreamDefinition # Interface: StreamDefinition Defined in: .api-entries/core/index.d.ts:684 Stored stream definition (input/output schemas + async-generator handler). ## Properties ### input > **input**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:685 *** ### output > **output**: [`AnySchema`](../type-aliases/AnySchema.md) Defined in: .api-entries/core/index.d.ts:686 *** ### handler > **handler**: [`StreamHandler`](../type-aliases/StreamHandler.md)<`any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`> Defined in: .api-entries/core/index.d.ts:687 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/react/interfaces/StreamResult.md --- [ws-asyncapi API](../../index.md) / [react](../index.md) / StreamResult # Interface: StreamResult\ Defined in: .api-entries/react/index.d.ts:32 ## Type Parameters ### Data `Data` ## Properties ### data > **data**: `Data` Defined in: .api-entries/react/index.d.ts:33 *** ### isDone > **isDone**: `boolean` Defined in: .api-entries/react/index.d.ts:34 *** ### error > **error**: [`RpcError`](../../client/classes/RpcError.md) Defined in: .api-entries/react/index.d.ts:35 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/interfaces/StreamSnapshot.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / StreamSnapshot # Interface: StreamSnapshot\ Defined in: .api-entries/query-core/index.d.ts:93 Snapshot of a [streamStore](../functions/streamStore.md). ## Type Parameters ### Data `Data` ## Properties ### data > **data**: `Data` Defined in: .api-entries/query-core/index.d.ts:94 *** ### isDone > **isDone**: `boolean` Defined in: .api-entries/query-core/index.d.ts:95 *** ### error > **error**: [`RpcError`](../../client/classes/RpcError.md) Defined in: .api-entries/query-core/index.d.ts:96 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/interfaces/Subscribable.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / Subscribable # Interface: Subscribable\ Defined in: .api-entries/query-core/index.d.ts:46 The external-store contract every framework binding adapts (React's `useSyncExternalStore`, Solid `from`, Vue `ref`, …). ## Type Parameters ### T `T` ## Methods ### subscribe() > **subscribe**(`onChange`): () => `void` Defined in: .api-entries/query-core/index.d.ts:47 #### Parameters ##### onChange () => `void` #### Returns () => `void` *** ### getSnapshot() > **getSnapshot**(): `T` Defined in: .api-entries/query-core/index.d.ts:48 #### Returns `T` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/testing/interfaces/TestConnectOptions.md --- [ws-asyncapi API](../../index.md) / [testing](../index.md) / TestConnectOptions # Interface: TestConnectOptions Defined in: .api-entries/testing/index.d.ts:12 ## Properties ### path? > `optional` **path?**: `string` Defined in: .api-entries/testing/index.d.ts:14 connection path; defaults to the channel address with params filled `1` *** ### query? > `optional` **query?**: `Record`<`string`, `string`> Defined in: .api-entries/testing/index.d.ts:15 *** ### headers? > `optional` **headers?**: `Record`<`string`, `string`> Defined in: .api-entries/testing/index.d.ts:16 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/testing/interfaces/TestHarness.md --- [ws-asyncapi API](../../index.md) / [testing](../index.md) / TestHarness # Interface: TestHarness\ Defined in: .api-entries/testing/index.d.ts:18 ## Type Parameters ### C `C` *extends* `AnyChannel` ## Properties ### channel > **channel**: `C` Defined in: .api-entries/testing/index.d.ts:20 the channel under test *** ### backplane > **backplane**: `Backplane` Defined in: .api-entries/testing/index.d.ts:22 the backplane the harness drives (publish to it to simulate other nodes) ## Methods ### connect() > **connect**(`options?`): `WsClient`<`InferClient`<`C`>> Defined in: .api-entries/testing/index.d.ts:24 open a typed client connected in-memory to the channel #### Parameters ##### options? [`TestConnectOptions`](TestConnectOptions.md) #### Returns `WsClient`<`InferClient`<`C`>> *** ### close() > **close**(): `Promise`<`void`> Defined in: .api-entries/testing/index.d.ts:26 disconnect all clients and close the backplane #### Returns `Promise`<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/testing/interfaces/TestHarnessOptions.md --- [ws-asyncapi API](../../index.md) / [testing](../index.md) / TestHarnessOptions # Interface: TestHarnessOptions Defined in: .api-entries/testing/index.d.ts:4 ## Properties ### codec? > `optional` **codec?**: `Codec` Defined in: .api-entries/testing/index.d.ts:6 wire codec (default: JSON). Client and server share it automatically. *** ### backplane? > `optional` **backplane?**: `Backplane` Defined in: .api-entries/testing/index.d.ts:8 backplane (default: a fresh in-process LocalBackplane with recovery on). *** ### plugins? > `optional` **plugins?**: `ServerPlugin`\[] Defined in: .api-entries/testing/index.d.ts:10 server-level plugins (metrics/tracing/logging) tapping the channel --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/ValidationIssue.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ValidationIssue # Interface: ValidationIssue Defined in: .api-entries/core/index.d.ts:162 ## Properties ### path? > `optional` **path?**: `string` Defined in: .api-entries/core/index.d.ts:164 JSON-pointer-ish path to the offending value, e.g. "/beneficiary/id" *** ### message > **message**: `string` Defined in: .api-entries/core/index.d.ts:165 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/WebsocketAsyncAPIMap.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / WebsocketAsyncAPIMap # Interface: WebsocketAsyncAPIMap Defined in: .api-entries/client/index.d.ts:10 Augmented by the generated file from `@ws-asyncapi/cli`. Each channel exposes its `addresses`, and per-channel `query`/`headers`/`commandMap`/`eventMap`/ `rpcMap`. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/WebsocketAsyncAPIOptions.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / WebsocketAsyncAPIOptions # Interface: WebsocketAsyncAPIOptions\ Defined in: .api-entries/client/index.d.ts:40 ## Type Parameters ### Query `Query` *extends* `Record`<`string`, `string`> = `Record`<`string`, `string`> ### Headers `Headers` *extends* `Record`<`string`, `string`> = `Record`<`string`, `string`> ## Properties ### query? > `optional` **query?**: `Query` Defined in: .api-entries/client/index.d.ts:41 *** ### headers? > `optional` **headers?**: `Headers` Defined in: .api-entries/client/index.d.ts:46 Kept for API parity / SSR; browser `WebSocket` cannot set request headers, so this is ignored in the browser. *** ### codec? > `optional` **codec?**: `Codec` Defined in: .api-entries/client/index.d.ts:48 wire codec (default: JSON) *** ### reconnect? > `optional` **reconnect?**: `boolean` | [`ReconnectOptions`](ReconnectOptions.md) Defined in: .api-entries/client/index.d.ts:50 auto-reconnect with exponential backoff (default: true) *** ### heartbeat? > `optional` **heartbeat?**: `boolean` | [`HeartbeatOptions`](HeartbeatOptions.md) Defined in: .api-entries/client/index.d.ts:52 heartbeat ping/pong liveness detection (default: true) *** ### requestTimeout? > `optional` **requestTimeout?**: `number` Defined in: .api-entries/client/index.d.ts:54 default RPC timeout in ms (default: 30\_000) *** ### maxBufferSize? > `optional` **maxBufferSize?**: `number` Defined in: .api-entries/client/index.d.ts:56 max outbound frames buffered while disconnected (default: 1024) *** ### presenceThrottle? > `optional` **presenceThrottle?**: `number` Defined in: .api-entries/client/index.d.ts:62 Coalesce volatile `presence.update` calls (cursors) to the latest, flushed at most every N ms (default: 0 = send each immediately). ~50ms (~20Hz) is a good cursor default; the receiver smooths between samples. *** ### socket? > `optional` **socket?**: (`url`) => [`WebSocketLike`](WebSocketLike.md) Defined in: .api-entries/client/index.d.ts:67 Custom transport factory (default: `new WebSocket(url)`). Supply one for a non-browser environment or an in-memory pipe (see `@ws-asyncapi/testing`). #### Parameters ##### url `string` #### Returns [`WebSocketLike`](WebSocketLike.md) *** ### contractVersion? > `optional` **contractVersion?**: `string` Defined in: .api-entries/client/index.d.ts:75 Contract version sent in the handshake. If the server's contract hash differs, the server rejects the connection (close 4409) and the client stops reconnecting and rejects `opened`. The CLI-generated client supplies this automatically; for the codegen-free client pass `contractHash(channel)` if you want runtime contract checking. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/WebsocketClientData.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / WebsocketClientData # Interface: WebsocketClientData\ Defined in: .api-entries/core/index.d.ts:212 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` *extends* `unknown` | `undefined` ## Properties ### ws > **ws**: [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`WebsocketData`, `Topics`> Defined in: .api-entries/core/index.d.ts:213 *** ### request > **request**: [`RequestData`](RequestData.md)<`Query`, `Headers`, `Params`> Defined in: .api-entries/core/index.d.ts:214 *** ### data > **data**: `Data` Defined in: .api-entries/core/index.d.ts:215 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/interfaces/WebsocketDataType.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / WebsocketDataType # Interface: WebsocketDataType Defined in: .api-entries/core/index.d.ts:6 ## Properties ### client > **client**: `Record`<`string`, `any`> Defined in: .api-entries/core/index.d.ts:7 *** ### server > **server**: `Record`<`string`, `any`> Defined in: .api-entries/core/index.d.ts:8 *** ### serverRpc? > `optional` **serverRpc?**: `Record`<`string`, { `input`: `any`; `output`: `any`; }> Defined in: .api-entries/core/index.d.ts:10 server→client (acknowledged) RPCs: `{ input; output }` per name --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/interfaces/WebSocketLike.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / WebSocketLike # Interface: WebSocketLike Defined in: .api-entries/client/index.d.ts:82 Minimal WebSocket surface the client drives — enough to plug in a custom transport (SSR/Node, React Native, or an in-memory pipe for tests) via the `socket` option. The browser `WebSocket` satisfies it. ## Properties ### binaryType? > `optional` **binaryType?**: `string` Defined in: .api-entries/client/index.d.ts:83 *** ### readyState > `readonly` **readyState**: `number` Defined in: .api-entries/client/index.d.ts:85 0 CONNECTING · 1 OPEN · 2 CLOSING · 3 CLOSED *** ### onopen > **onopen**: (`event`) => `void` Defined in: .api-entries/client/index.d.ts:88 #### Parameters ##### event `unknown` #### Returns `void` *** ### onmessage > **onmessage**: (`event`) => `void` Defined in: .api-entries/client/index.d.ts:89 #### Parameters ##### event ###### data `unknown` #### Returns `void` *** ### onerror > **onerror**: (`event`) => `void` Defined in: .api-entries/client/index.d.ts:92 #### Parameters ##### event `unknown` #### Returns `void` *** ### onclose > **onclose**: (`event`) => `void` Defined in: .api-entries/client/index.d.ts:93 #### Parameters ##### event `unknown` #### Returns `void` ## Methods ### send() > **send**(`data`): `void` Defined in: .api-entries/client/index.d.ts:86 #### Parameters ##### data `string` | `Uint8Array`<`ArrayBufferLike`> #### Returns `void` *** ### close() > **close**(`code?`, `reason?`): `void` Defined in: .api-entries/client/index.d.ts:87 #### Parameters ##### code? `number` ##### reason? `string` #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/client/interfaces/WsClient.md' --- [ws-asyncapi API](../../index.md) / [client](../index.md) / WsClient # Interface: WsClient\ Defined in: .api-entries/client/index.d.ts:111 The fully-typed client surface, parameterized by a channel's maps. Returned by `createClient()` (codegen-free) and structurally identical to what `websocketAsyncAPI` returns for a CLI-generated channel. ## Type Parameters ### T `T` *extends* `object` ## Properties ### ~original > `readonly` **~original**: `WebSocket` Defined in: .api-entries/client/index.d.ts:131 the underlying browser WebSocket (current connection) *** ### connected > `readonly` **connected**: `boolean` Defined in: .api-entries/client/index.d.ts:132 *** ### sessionId > `readonly` **sessionId**: `string` Defined in: .api-entries/client/index.d.ts:134 server-assigned session id (stable across reconnects) *** ### recovered > `readonly` **recovered**: `boolean` Defined in: .api-entries/client/index.d.ts:136 whether the most recent (re)connect recovered missed events *** ### opened > `readonly` **opened**: `Promise`<`void`> Defined in: .api-entries/client/index.d.ts:138 resolves once the first connection opens *** ### presence > **presence**: [`PresenceApi`](PresenceApi.md)<`T`\[`"presenceState"`]> Defined in: .api-entries/client/index.d.ts:166 Typed presence: announce this connection's state, observe the room roster, or leave. Available when the channel declares `.presence(...)`. Join/leave/ update changes are delivered as diffs and reconciled into a live roster; the last announced state is re-sent automatically after a reconnect. ## Methods ### onOpen() > **onOpen**(`callback`): () => `void` Defined in: .api-entries/client/index.d.ts:139 #### Parameters ##### callback (`event`) => `void` #### Returns () => `void` *** ### onClose() > **onClose**(`callback`): () => `void` Defined in: .api-entries/client/index.d.ts:140 #### Parameters ##### callback (`event`) => `void` #### Returns () => `void` *** ### onError() > **onError**(`callback`): () => `void` Defined in: .api-entries/client/index.d.ts:141 #### Parameters ##### callback (`event`) => `void` #### Returns () => `void` *** ### onRecover() > **onRecover**(`callback`): () => `void` Defined in: .api-entries/client/index.d.ts:142 #### Parameters ##### callback (`recovered`) => `void` #### Returns () => `void` *** ### onEvent() > **onEvent**<`E`>(`event`, `callback`): () => `void` Defined in: .api-entries/client/index.d.ts:143 #### Type Parameters ##### E `E` *extends* `string` | `number` | `symbol` #### Parameters ##### event `E` ##### callback (`data`) => `void` #### Returns () => `void` *** ### onRequest() > **onRequest**<`N`>(`name`, `handler`): () => `void` Defined in: .api-entries/client/index.d.ts:145 Answer a server→client RPC: receive the server's input, return output. #### Type Parameters ##### N `N` *extends* `string` | `number` | `symbol` #### Parameters ##### name `N` ##### handler (`input`) => `T`\[`"serverRpcMap"`]\[`N`]\[`"output"`] | `Promise`<`T`\[`"serverRpcMap"`]\[`N`]\[`"output"`]> #### Returns () => `void` *** ### call() > **call**<`C`>(`command`, ...`data`): `void` Defined in: .api-entries/client/index.d.ts:146 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### data ...`T`\[`"commandMap"`]\[`C`] *extends* `never` ? \[] : \[`T`\[`"commandMap"`]\[`C`]] #### Returns `void` *** ### request() > **request**<`C`>(`command`, `input`, `options?`): `Promise`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`]> Defined in: .api-entries/client/index.d.ts:147 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### input `T`\[`"rpcMap"`]\[`C`]\[`"input"`] ##### options? [`RequestOptions`](RequestOptions.md) #### Returns `Promise`<`T`\[`"rpcMap"`]\[`C`]\[`"output"`]> *** ### safeRequest() > **safeRequest**<`C`>(`command`, `input`, `options?`): `Promise`<[`SafeResult`](../type-aliases/SafeResult.md)<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> Defined in: .api-entries/client/index.d.ts:148 #### Type Parameters ##### C `C` *extends* `string` | `number` | `symbol` #### Parameters ##### command `C` ##### input `T`\[`"rpcMap"`]\[`C`]\[`"input"`] ##### options? [`RequestOptions`](RequestOptions.md) #### Returns `Promise`<[`SafeResult`](../type-aliases/SafeResult.md)<`T`\[`"rpcMap"`]\[`C`]\[`"output"`], `T`\[`"rpcMap"`]\[`C`]\[`"errors"`]>> *** ### stream() > **stream**<`N`>(`name`, `input`): `AsyncIterable`<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> Defined in: .api-entries/client/index.d.ts:151 Open a typed stream; consume with `for await`. Stopping iteration cancels it server-side; a server error throws an `RpcError` into the loop. #### Type Parameters ##### N `N` *extends* `string` | `number` | `symbol` #### Parameters ##### name `N` ##### input `T`\[`"streamMap"`]\[`N`]\[`"input"`] #### Returns `AsyncIterable`<`T`\[`"streamMap"`]\[`N`]\[`"output"`]> *** ### authenticate() > **authenticate**(`credentials`): `Promise`<`void`> Defined in: .api-entries/client/index.d.ts:159 Refresh credentials on the live connection (token refresh) — the server re-runs its `.onAuth` handler and replaces the connection context without a reconnect. Resolves once accepted; rejects with a typed `RpcError` if the server rejects the credentials. The last credentials passed are re-sent automatically after a reconnect, so the refreshed identity survives drops. #### Parameters ##### credentials `T`\[`"authCredentials"`] #### Returns `Promise`<`void`> *** ### history() > **history**(`room`, `options?`): `Promise`<[`HistoryEntry`](../type-aliases/HistoryEntry.md)<`T`\[`"eventMap"`]>\[]> Defined in: .api-entries/client/index.d.ts:173 Fetch a room's retained recent events (history / rewind) — e.g. the chat backlog when opening a room. Returns a typed, discriminated list (narrow on `entry.event`). Only rooms this connection is subscribed to are readable. Requires `.history(event)` on the server; otherwise resolves to `[]`. #### Parameters ##### room `string` ##### options? ###### limit? `number` #### Returns `Promise`<[`HistoryEntry`](../type-aliases/HistoryEntry.md)<`T`\[`"eventMap"`]>\[]> *** ### close() > **close**(`code?`, `reason?`): `void` Defined in: .api-entries/client/index.d.ts:176 #### Parameters ##### code? `number` ##### reason? `string` #### Returns `void` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/query-core.md' --- [ws-asyncapi API](../index.md) / query-core # query-core ## Interfaces * [QueryCoreClient](interfaces/QueryCoreClient.md) * [Subscribable](interfaces/Subscribable.md) * [StreamSnapshot](interfaces/StreamSnapshot.md) * [PresenceSnapshotState](interfaces/PresenceSnapshotState.md) ## Type Aliases * [StreamReduce](type-aliases/StreamReduce.md) ## Functions * [rpcQueryKey](functions/rpcQueryKey.md) * [historyQueryKey](functions/historyQueryKey.md) * [requestQueryOptions](functions/requestQueryOptions.md) * [mutationOptions](functions/mutationOptions.md) * [historyQueryOptions](functions/historyQueryOptions.md) * [subscribeHistoryLive](functions/subscribeHistoryLive.md) * [streamFold](functions/streamFold.md) * [presenceStore](functions/presenceStore.md) * [streamStore](functions/streamStore.md) * [lastEventStore](functions/lastEventStore.md) * [connectionStore](functions/connectionStore.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/react.md' --- [ws-asyncapi API](../index.md) / react # react ## Interfaces * [StreamResult](interfaces/StreamResult.md) * [PresenceResult](interfaces/PresenceResult.md) * [ReactClient](interfaces/ReactClient.md) ## Type Aliases * [StreamReduce](type-aliases/StreamReduce.md) ## Functions * [useStore](functions/useStore.md) * [createReactClient](functions/createReactClient.md) * [streamFold](functions/streamFold.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/solid.md' --- [ws-asyncapi API](../index.md) / solid # solid ## Interfaces * [StreamAccessors](interfaces/StreamAccessors.md) * [PresenceAccessors](interfaces/PresenceAccessors.md) * [SolidClient](interfaces/SolidClient.md) ## Functions * [fromStore](functions/fromStore.md) * [createSolidClient](functions/createSolidClient.md) ## References ### StreamReduce Re-exports [StreamReduce](../react/type-aliases/StreamReduce.md) *** ### streamFold Re-exports [streamFold](../react/functions/streamFold.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/testing.md' --- [ws-asyncapi API](../index.md) / testing # testing ## Interfaces * [TestHarnessOptions](interfaces/TestHarnessOptions.md) * [TestConnectOptions](interfaces/TestConnectOptions.md) * [TestHarness](interfaces/TestHarness.md) ## Functions * [createTestHarness](functions/createTestHarness.md) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/AddressPattern.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / AddressPattern # Type Alias: AddressPattern\

> **AddressPattern**<`P`> = `P` *extends* `` `${infer Head}:${string}/${infer Rest}` `` ? `` `${Head}${string}/${AddressPattern}` `` : `P` *extends* `` `${infer Head}:${string}` `` ? `` `${Head}${string}` `` : `P` Defined in: .api-entries/core/index.d.ts:626 Turn a channel address into the literal pattern a client connects to: `"/chat/:room"` → `` `/chat/${string}` ``. ## Type Parameters ### P `P` *extends* `string` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/AnyChannel.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / AnyChannel # Type Alias: AnyChannel > **AnyChannel** = [`Channel`](../classes/Channel.md)<`any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`> Defined in: .api-entries/core/index.d.ts:621 --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/type-aliases/AnySchema.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / AnySchema # Type Alias: AnySchema > **AnySchema** = `StandardSchemaV1` Defined in: .api-entries/core/index.d.ts:148 A schema accepted by the builder: any Standard Schema validator. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/AuthHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / AuthHandler # Type Alias: AuthHandler\ > **AuthHandler**<`WebsocketData`, `Topics`, `Credentials`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => [`MaybePromise`](MaybePromise.md)<`Partial`<`Data`> | `Record`<`string`, `unknown`> | `void`> Defined in: .api-entries/core/index.d.ts:267 Handler for credential refresh (`.onAuth()`). Runs when a client sends fresh credentials on a live connection (an import("./wire.ts").Frame.Auth frame). It receives the validated `credentials` plus the current context and returns the fields to merge into that context (e.g. the re-decoded user), or throws an import("./wire.ts").RpcError to reject the refresh. ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Credentials `Credentials` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Parameters ### data #### ws [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`WebsocketData`, `Topics`> #### credentials `Credentials` #### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> #### data `Data` ## Returns [`MaybePromise`](MaybePromise.md)<`Partial`<`Data`> | `Record`<`string`, `unknown`> | `void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/BeforeUpgradeHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / BeforeUpgradeHandler # Type Alias: BeforeUpgradeHandler\ > **BeforeUpgradeHandler**<`Query`, `Headers`, `Params`, `Data`> = (`request`) => [`MaybePromise`](MaybePromise.md)<`void` | `Response` | `Data`> Defined in: .api-entries/core/index.d.ts:278 ## Type Parameters ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Parameters ### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> ## Returns [`MaybePromise`](MaybePromise.md)<`void` | `Response` | `Data`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/type-aliases/BuiltinErrorCode.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / BuiltinErrorCode # Type Alias: BuiltinErrorCode > **BuiltinErrorCode** = `"VALIDATION"` | `"NOT_FOUND"` | `"INTERNAL"` | `"TIMEOUT"` | `"OVERLOADED"` Defined in: .api-entries/client/index.d.ts:218 Built-in error codes the runtime can produce in addition to declared ones. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/emitter/type-aliases/Emitter.md --- [ws-asyncapi API](../../index.md) / [emitter](../index.md) / Emitter # Type Alias: Emitter\ > **Emitter**<`C`> = `ReturnType`<*typeof* [`createEmitter`](../functions/createEmitter.md)> Defined in: .api-entries/emitter/index.d.ts:36 ## Type Parameters ### C `C` *extends* `AnyChannel` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/ExtractRouteParams.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ExtractRouteParams # Type Alias: ExtractRouteParams\ > **ExtractRouteParams**<`T`> = `T` *extends* `` `${string}:${infer Param}/${infer Rest}` `` ? `{ [K in Param]: string }` & `ExtractRouteParams`<`Rest`> : `T` *extends* `` `${string}:${infer Param}` `` ? `{ [K in Param]: string }` : `T` *extends* `` `${string}*` `` ? `object` : `object` Defined in: .api-entries/core/index.d.ts:273 ## Type Parameters ### T `T` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/type-aliases/FindMatchingAddressKey.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / FindMatchingAddressKey # Type Alias: FindMatchingAddressKey\ > **FindMatchingAddressKey**<`T`, `Input`> = `{ [K in keyof T]: Input extends T[K] ? K : never }`\[keyof `T`] Defined in: .api-entries/client/index.d.ts:23 ## Type Parameters ### T `T` *extends* `Record`<`string`, `string`> ### Input `Input` *extends* `string` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/GetWebSocketType.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / GetWebSocketType # Type Alias: GetWebSocketType\ > **GetWebSocketType**<`ChannelThis`> = `ChannelThis` *extends* [`Channel`](../classes/Channel.md)\ ? [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<{ `client`: `WebsocketClientData`; `server`: `WebsocketServerData`; `serverRpc`: `ServerRpcMap`; }, `Topics`> : `never` Defined in: .api-entries/core/index.d.ts:279 ## Type Parameters ### ChannelThis `ChannelThis` *extends* [`AnyChannel`](AnyChannel.md) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/type-aliases/HistoryEntry.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / HistoryEntry # Type Alias: HistoryEntry\ > **HistoryEntry**<`EventMap`> = `{ [E in keyof EventMap]: { event: E; data: EventMap[E] } }`\[keyof `EventMap`] Defined in: .api-entries/client/index.d.ts:182 One entry from [WsClient.history](../interfaces/WsClient.md#history): a discriminated union over the channel's events, so `if (entry.event === "message")` narrows `entry.data`. ## Type Parameters ### EventMap `EventMap` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/InferClient.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / InferClient # Type Alias: InferClient\ > **InferClient**<`C`> = `C` *extends* [`Channel`](../classes/Channel.md)\ ? `object` : `never` Defined in: .api-entries/core/index.d.ts:639 Derive the typed client shape directly from a server [Channel](../classes/Channel.md) type — no codegen. Use with `typeof channel`: ```ts import { createClient } from "@ws-asyncapi/client"; const client = createClient("ws://localhost:3000", "/chat/1"); ``` Yields `{ commandMap, eventMap, rpcMap, query, headers, address }` — the same contract the CLI-generated `WebsocketAsyncAPIMap` provides, inferred instead. ## Type Parameters ### C `C` *extends* [`AnyChannel`](AnyChannel.md) --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/type-aliases/InferIn.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / InferIn # Type Alias: InferIn\ > **InferIn**<`S`> = `S` *extends* `StandardSchemaV1` ? `StandardSchemaV1.InferInput`<`S`> : `unknown` Defined in: .api-entries/core/index.d.ts:159 Static type that goes onto the wire / into validation (pre-parse). ## Type Parameters ### S `S` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/type-aliases/InferOut.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / InferOut # Type Alias: InferOut\ > **InferOut**<`S`> = `S` *extends* `StandardSchemaV1` ? `StandardSchemaV1.InferOutput`<`S`> : `unknown` Defined in: .api-entries/core/index.d.ts:157 Static type a handler receives after a schema validates (post-parse). ## Type Parameters ### S `S` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/JsonSchemaTarget.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / JsonSchemaTarget # Type Alias: JsonSchemaTarget > **JsonSchemaTarget** = `"draft-07"` | `"draft-2020-12"` | `"openapi-3.0"` Defined in: .api-entries/core/index.d.ts:151 The JSON Schema draft a converter should target. AsyncAPI 3.0's Schema Object is a superset of draft-07, so that is the default and the recommended target. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/MaybePromise.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / MaybePromise # Type Alias: MaybePromise\ > **MaybePromise**<`T`> = `T` | `Promise`<`T`> Defined in: .api-entries/core/index.d.ts:211 ## Type Parameters ### T `T` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/MessageHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / MessageHandler # Type Alias: MessageHandler\ > **MessageHandler**<`WebsocketData`, `Topics`, `Message`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => [`MaybePromise`](MaybePromise.md)<`void`> Defined in: .api-entries/core/index.d.ts:224 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Message `Message` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Parameters ### data #### ws [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`WebsocketData`, `Topics`> #### message `Message` #### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> #### data `Data` ## Returns [`MaybePromise`](MaybePromise.md)<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/NamedPlugin.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / NamedPlugin # Type Alias: NamedPlugin\ > **NamedPlugin**<`Setup`> = `Setup` & `object` Defined in: .api-entries/core/index.d.ts:603 A plugin function tagged with a stable name for idempotent application. ## Type Declaration ### \[PLUGIN\_NAME] > `readonly` **\[PLUGIN\_NAME]**: `string` ## Type Parameters ### Setup `Setup` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/NodeCommand.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / NodeCommand # Type Alias: NodeCommand > **NodeCommand** = { `op`: `"join"`; `channel`: `string`; `room`: `string` | `null`; `rooms`: `string`\[]; } | { `op`: `"leave"`; `channel`: `string`; `room`: `string` | `null`; `rooms`: `string`\[]; } | { `op`: `"disconnect"`; `channel`: `string`; `room`: `string` | `null`; } | { `op`: `"sse"`; `channel`: `string`; `event`: `string`; `data`: `unknown`; } Defined in: .api-entries/core/index.d.ts:105 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/OnCloseHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / OnCloseHandler # Type Alias: OnCloseHandler\ > **OnCloseHandler**<`WebsocketData`, `Topics`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => [`MaybePromise`](MaybePromise.md)<`void`> Defined in: .api-entries/core/index.d.ts:218 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` *extends* `unknown` | `undefined` ## Parameters ### data [`WebsocketClientData`](../interfaces/WebsocketClientData.md)<`WebsocketData`, `Topics`, `Query`, `Headers`, `Params`, `Data`> ## Returns [`MaybePromise`](MaybePromise.md)<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/OnOpenHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / OnOpenHandler # Type Alias: OnOpenHandler\ > **OnOpenHandler**<`WebsocketData`, `Topics`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => [`MaybePromise`](MaybePromise.md)<`void`> Defined in: .api-entries/core/index.d.ts:217 ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` *extends* `unknown` | `undefined` ## Parameters ### data [`WebsocketClientData`](../interfaces/WebsocketClientData.md)<`WebsocketData`, `Topics`, `Query`, `Headers`, `Params`, `Data`> ## Returns [`MaybePromise`](MaybePromise.md)<`void`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/RpcHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / RpcHandler # Type Alias: RpcHandler\ > **RpcHandler**<`WebsocketData`, `Topics`, `Message`, `Output`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => [`MaybePromise`](MaybePromise.md)<`Output`> Defined in: .api-entries/core/index.d.ts:239 Handler for an RPC (`.rpc()`) message. Identical context to [MessageHandler](MessageHandler.md), but it returns a value that is sent back to the caller as the typed reply. ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Message `Message` ### Output `Output` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Parameters ### data #### ws [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`WebsocketData`, `Topics`> #### message `Message` #### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> #### data `Data` ## Returns [`MaybePromise`](MaybePromise.md)<`Output`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/type-aliases/SafeResult.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / SafeResult # Type Alias: SafeResult\ > **SafeResult**<`Output`, `Errors`> = { `data`: `Output`; `error`: `null`; } | { `data`: `null`; `error`: [`TypedRpcError`](TypedRpcError.md)<`Errors`>; } Defined in: .api-entries/client/index.d.ts:242 Result of `safeRequest`: a discriminated union you narrow on `error`. On success `error` is `null`; on failure `data` is `null` and `error` carries a typed, discriminated code. ## Type Parameters ### Output `Output` ### Errors `Errors` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/type-aliases/SchemaIO.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / SchemaIO # Type Alias: SchemaIO > **SchemaIO** = `"input"` | `"output"` Defined in: .api-entries/core/index.d.ts:155 Whether a schema describes the value going *into* validation (the wire shape a client sends) or *out of* it (the parsed value a handler receives / a server sends). They differ for validators with transforms/coercion/defaults. --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/type-aliases/SmootherFactory.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / SmootherFactory # Type Alias: SmootherFactory > **SmootherFactory** = (`onChange`) => [`CursorSmoother`](../interfaces/CursorSmoother.md) Defined in: .api-entries/cursors/index.d.ts:39 ## Parameters ### onChange (`point`) => `void` ## Returns [`CursorSmoother`](../interfaces/CursorSmoother.md) --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/StreamHandler.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / StreamHandler # Type Alias: StreamHandler\ > **StreamHandler**<`WebsocketData`, `Topics`, `Message`, `Output`, `Query`, `Headers`, `Params`, `Data`> = (`data`) => `AsyncIterable`<`Output`> Defined in: .api-entries/core/index.d.ts:252 Handler for a stream (`.stream()`). Same context as [RpcHandler](RpcHandler.md), but it returns an async iterable (typically an `async function*`) whose yielded values are each validated against `output` and pushed to the client as they arrive. The client consumes them with `for await`. If the consumer stops iterating, the iterator is `return()`-ed so a `try/finally` in the generator can clean up. ## Type Parameters ### WebsocketData `WebsocketData` *extends* [`WebsocketDataType`](../interfaces/WebsocketDataType.md) ### Topics `Topics` *extends* `string` ### Message `Message` ### Output `Output` ### Query `Query` *extends* `unknown` | `undefined` ### Headers `Headers` *extends* `unknown` | `undefined` ### Params `Params` *extends* `unknown` | `undefined` ### Data `Data` ## Parameters ### data #### ws [`WebSocketImplementation`](../classes/WebSocketImplementation.md)<`WebsocketData`, `Topics`> #### message `Message` #### request [`RequestData`](../interfaces/RequestData.md)<`Query`, `Headers`, `Params`> #### data `Data` #### signal `AbortSignal` aborts when the client cancels or disconnects — wire long tasks to it ## Returns `AsyncIterable`<`Output`> --- --- url: >- https://ws-asyncapi.github.io/documentation/api/query-core/type-aliases/StreamReduce.md --- [ws-asyncapi API](../../index.md) / [query-core](../index.md) / StreamReduce # Type Alias: StreamReduce\ > **StreamReduce**<`Item`, `Acc`> = { `reduce`: `"append"`; `max?`: `number`; } | { `reduce`: (`acc`, `item`) => `Acc`; `initial`: `Acc`; } Defined in: .api-entries/query-core/index.d.ts:79 How a stream's yielded items are reduced into the observed value. ## Type Parameters ### Item `Item` ### Acc `Acc` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/react/type-aliases/StreamReduce.md --- [ws-asyncapi API](../../index.md) / [react](../index.md) / StreamReduce # Type Alias: StreamReduce\ > **StreamReduce**<`Item`, `Acc`> = { `reduce`: `"append"`; `max?`: `number`; } | { `reduce`: (`acc`, `item`) => `Acc`; `initial`: `Acc`; } Defined in: node\_modules/@ws-asyncapi/query-core/dist/index.d.ts:79 How a stream's yielded items are reduced into the observed value. ## Type Parameters ### Item `Item` ### Acc `Acc` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/client/type-aliases/TypedRpcError.md --- [ws-asyncapi API](../../index.md) / [client](../index.md) / TypedRpcError # Type Alias: TypedRpcError\ > **TypedRpcError**<`Errors`> = `{ [C in keyof Errors]: { code: C; message: string; data: Errors[C] } }`\[keyof `Errors`] | { `code`: [`BuiltinErrorCode`](BuiltinErrorCode.md); `message`: `string`; `data`: `unknown`; } Defined in: .api-entries/client/index.d.ts:226 A typed RPC error: either one of the codes declared in the contract (with its `data` payload typed), or a built-in runtime code (`data` is `unknown`). The codes are kept as distinct literals so `if (error.code === "X")` narrows to the typed `data` for that code. (Undeclared custom codes still arrive at runtime — reach them via `request()` + `catch` on the open-coded `RpcError`.) ## Type Parameters ### Errors `Errors` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/ValidationResult.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / ValidationResult # Type Alias: ValidationResult > **ValidationResult** = { `ok`: `true`; `value`: `unknown`; } | { `ok`: `false`; `issues`: [`ValidationIssue`](../interfaces/ValidationIssue.md)\[]; } Defined in: .api-entries/core/index.d.ts:167 --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/type-aliases/VendorJsonSchemaConverter.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / VendorJsonSchemaConverter # Type Alias: VendorJsonSchemaConverter > **VendorJsonSchemaConverter** = (`schema`, `io`, `target`) => `object` | `undefined` Defined in: .api-entries/core/index.d.ts:187 JSON Schema converter for a validator that implements StandardSchemaV1 (validation) but **not** StandardJSONSchemaV1 (native JSON Schema) — e.g. Valibot, whose converter ships separately in `@valibot/to-json-schema`. Return `undefined` to fall through. ## Parameters ### schema `StandardSchemaV1` ### io [`SchemaIO`](SchemaIO.md) ### target [`JsonSchemaTarget`](JsonSchemaTarget.md) ## Returns `object` | `undefined` --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/variables/AuthFrame.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / AuthFrame # Variable: AuthFrame > **AuthFrame**: `any` --- --- url: >- https://ws-asyncapi.github.io/documentation/api/core/variables/COMMAND_TOPIC.md --- [ws-asyncapi API](../../index.md) / [core](../index.md) / COMMAND\_TOPIC # Variable: COMMAND\_TOPIC > `const` **COMMAND\_TOPIC**: `"#wsaa:cmd"` = `"#wsaa:cmd"` Defined in: .api-entries/core/index.d.ts:104 Reserved backplane topic carrying [NodeCommand](../type-aliases/NodeCommand.md) messages (JSON). --- --- url: >- https://ws-asyncapi.github.io/documentation/api/cursors/variables/lerpSmoother.md --- [ws-asyncapi API](../../index.md) / [cursors](../index.md) / lerpSmoother # Variable: lerpSmoother > `const` **lerpSmoother**: [`SmootherFactory`](../type-aliases/SmootherFactory.md) Defined in: .api-entries/cursors/index.d.ts:46 Zero-dependency smoother: lerps toward each new point over the measured inter-sample interval via `requestAnimationFrame` (60fps from a slower wire rate). Degrades to passthrough (immediate, last-write) when there's no `requestAnimationFrame` (SSR / tests). --- --- url: 'https://ws-asyncapi.github.io/documentation/api/core/variables/PLUGIN_NAME.md' --- [ws-asyncapi API](../../index.md) / [core](../index.md) / PLUGIN\_NAME # Variable: PLUGIN\_NAME > `const` **PLUGIN\_NAME**: unique `symbol` Defined in: .api-entries/core/index.d.ts:601 Symbol carrying a plugin's name on its function value (read by `.use`).