@thunderclapjs/client
thunderclapJS, for browsers, React Native, Node.js 22+, Deno and Bun. No dependencies. Install it with npm install @thunderclapjs/client.
Thunderclap
The client. It connects to Thunderclap, keeps subscriptions alive across reconnects and reports gaps so your app can backfill from its own store.
constructornew Thunderclap
Creates a client and, unless autoConnect is false, connects right away.
new Thunderclap(options: ThunderclapOptions)Parameters
keystringrequiredYour app's public key.
tokenstring | (() => Promise<string>)A connection token granting private and presence channels up front, or a function fetching a fresh one on every connect.
authorize(input: { channel, socketId }) => Promise<string>Fetches a token for one private or presence channel the connection token doesn't cover. Called only when a subscription is refused.
autoConnectbooleandefaulttrueConnect immediately.
urlstringdefault"https://realtime.thunderclap.dev"The Thunderclap endpoint. Set it only for a custom domain.
reconnect.minDelayMsnumberdefault500Base delay of the exponential backoff (with full jitter).
reconnect.maxDelayMsnumberdefault30000Backoff ceiling.
pongTimeoutMsnumberdefault15000How long to wait for a pong before considering the connection dead.
WebSocketWebSocketFactoryWebSocket implementation, for runtimes without a global one.
Example
const thunderclap = new Thunderclap({
key: process.env.NEXT_PUBLIC_THUNDERCLAP_KEY,
token: () => fetch("/api/realtime-token").then((r) => r.text()),
});methodsubscribe
Subscribes to a channel, or returns the existing subscription. Subscriptions are restored after every reconnect. presence-* channels return a PresenceChannel.
subscribe<Events, Info>(name: string): Channel<Events> | PresenceChannel<Events, Info>Parameters
namestringrequiredChannel name.
Returns
The channel.
Example
const room = thunderclap.subscribe<{ message: { text: string } }>("room-42");methodunsubscribe
Unsubscribes from a channel and forgets it.
unsubscribe(name: string): voidParameters
namestringrequiredChannel name.
methodchannel
Finds an existing subscription without creating one.
channel<Events>(name: string): Channel<Events> | undefinedParameters
namestringrequiredChannel name.
Returns
The channel, or undefined when not subscribed.
methodconnect
Connects, or reconnects now if a reconnect is pending. Does nothing while connecting or connected. Needed after autoConnect: false or disconnect().
connect(): voidmethoddisconnect
Closes the connection and stops reconnecting. Subscriptions are kept for the next connect().
disconnect(): voidmethodon
Listens to connection events.
on(event: "state" | "error", listener): () => voidEvents
| Event | Listener | Description |
|---|---|---|
state | ({ previous, current }: StateChange) => void | The connection state changed: initialized, connecting, connected, reconnecting, closed or failed. |
error | ({ code, message }: ThunderclapError) => void | A connection-level error, such as a rejected key or token. See error codes. |
Returns
A function removing the listener.
propertysocketId
The current connection's id, null while not connected. Send it to your server and pass it as exclude to skip this client when publishing.
readonly socketId: string | nullChannel
A subscription, returned by subscribe. It survives reconnects.
methodbind
Listens to one event. meta carries the event name, the channel and its sequence seq; for client events, seq is null and userId names the sender on presence channels.
bind<K>(event: K, listener: (data: Events[K], meta: EventMeta) => void): () => voidParameters
eventstringrequiredEvent name.
listener(data, meta) => voidrequiredCalled with each event.
Returns
A function removing the listener.
methodbindAll
Listens to every event on the channel.
bindAll(listener: (event: string, data: unknown, meta: EventMeta) => void): () => voidReturns
A function removing the listener.
methodtrigger
Sends a client event to the channel's other subscribers. The name must start with client-, the channel must be private or presence, and client events must be enabled for the app.
trigger<K>(event: K, data: Events[K]): booleanParameters
eventstringrequiredEvent name, starting with
client-.dataunknownrequiredJSON-serializable data, up to 10 KB.
Returns
true when sent, false when the channel isn't subscribed or can't carry client events. Refusals by the server arrive as error events (code 4306).
methodonGap
Called when events may have been missed: { from, to } for a range of sequences, or { reset: true } when the channel's counter restarted.
onGap(listener: (gap: Gap) => void): () => voidReturns
A function removing the listener.
methodon
Listens to the subscription's status.
on(event: "subscribed" | "error" | "gap" | "cache_miss", listener): () => voidEvents
| Event | Listener | Description |
|---|---|---|
subscribed | () => void | The server confirmed the subscription, again after each reconnect. |
error | ({ code, message }: ChannelError) => void | The subscription was refused or failed, or a client event was refused. |
gap | (gap: Gap) => void | Same as onGap. |
cache_miss | () => void | Cache channels: nothing is cached, so your server may publish a fresh value. |
Returns
A function removing the listener.
propertysubscribed
Whether the server confirmed the subscription on the current connection.
readonly subscribed: booleanpropertylastSeq
The last sequence received, null before the first event or confirmation.
readonly lastSeq: [epoch: number, n: number] | nullPresenceChannel
A subscription to a presence-* channel: everything a Channel does, plus who is subscribed. A user connected from several devices is one member.
propertymembers
Current members keyed by user id, the subscriber included. Empty until the first confirmation, and kept as last known while reconnecting.
readonly members: ReadonlyMap<string, Member<Info>>Fields
idstringThe user id, from the token's
uid.infoInfo | undefinedPublic user info, from the token's
info.
propertyme
The subscriber's own member entry, null before the first confirmation.
readonly me: Member<Info> | nullmethodon
Listens to status events, like Channel.on, and to membership changes.
on(event: "member_added" | "member_removed" | ChannelEvent, listener): () => voidEvents
| Event | Listener | Description |
|---|---|---|
member_added | (member: Member<Info>) => void | A user joined, including joins missed while reconnecting. |
member_removed | (member: Member<Info>) => void | A user's last connection left. |
Returns
A function removing the listener.