Adapter
Adapter is a class that specifies how to communicate with the server. It defines the way to send and receive
data, handle errors, handle reconnects, and more. The @hyper-fetch/sockets package ships with two built-in adapters:
WebsocketAdapter and ServerSentEventsAdapter. Other integrations such as Firebase Realtime Database are available as
separate packages (e.g., @hyper-fetch/firebase).
Built in Adapters
There are two built in adapters - WebsocketAdapter and ServerSentEventsAdapter providing basic functionality for the
Websocket and Server Sent Events (SSE) connection types.
Websocket Adapter
The default adapter is used to communicate with the Websocket server.
import { WebsocketAdapter } from "@hyper-fetch/sockets"
import { createSocketClient, WebsocketAdapter } from "@hyper-fetch/sockets";
const socket = createSocketClient({
url: "ws://localhost:3000",
adapter: WebsocketAdapter(),
});
Options
You can pass adapter-specific options via the adapterOptions constructor option on Socket.
| Option | Type | Default | Description |
|---|---|---|---|
autoConnect | boolean | true | Automatically connect when the socket is created. |
protocols | string | string[] | — | Subprotocols passed to the WebSocket constructor (Sec-WebSocket-Protocol header). |
heartbeat | boolean | — | Enable heartbeat messages to keep the connection alive. |
heartbeatMessage | string | — | The message payload sent for heartbeats. |
pingTimeout | number | — | Timeout (ms) to wait for a ping response. |
pongTimeout | number | — | Timeout (ms) to wait for a pong response. |
const socket = createSocketClient({
url: "ws://localhost:3000",
adapterOptions: {
autoConnect: false,
protocols: ["v1"],
heartbeat: true,
heartbeatMessage: "ping",
},
});
Dynamic options
Every adapter option can be resolved right before a connection attempt with the onConnect interceptor on the socket.
It runs for the initial connection, automatic reconnects and manual reconnects, so short-lived values such as auth
tokens passed through protocols are always fresh.
const socket = createSocketClient({
url: "wss://example.com/ws",
}).onConnect(({ connection }) => ({
...connection,
adapterOptions: {
...connection.adapterOptions,
protocols: ["authorization", authStore.getState().accessToken],
},
}));
Server Sent Events (SSE) Adapter
The ServerSentEventsAdapter is used to communicate with the Server Sent Events (SSE) server.
The SSE adapter does not support emitting events. Calling emit on an emitter with this adapter will throw an
error. Use the WebsocketAdapter if you need bidirectional communication.
import { ServerSentEventsAdapter } from "@hyper-fetch/sockets"
import { createSocketClient, ServerSentEventsAdapter } from "@hyper-fetch/sockets";
const socket = createSocketClient({
url: "http://localhost:3000",
adapter: ServerSentEventsAdapter(),
});
Options
| Option | Type | Default | Description |
|---|---|---|---|
autoConnect | boolean | true | Automatically connect when the socket is created. |
eventSourceInit | EventSourceInit | — | Options passed to the underlying EventSource constructor (e.g., withCredentials). |
const socket = createSocketClient({
url: "http://localhost:3000",
adapter: ServerSentEventsAdapter(),
adapterOptions: {
autoConnect: false,
eventSourceInit: { withCredentials: true },
},
});
Custom Adapter
There is nothing to prevent you from changing this and creating the adapter you need. Thanks to event communication, you
can set your own adapter as you wish by only fulfilling the typescript requirements. This way you can create your own
adapters for existing libraries like socket.io. Refer to the SocketAdapter API reference for the full contract your
custom adapter must satisfy.
The connector receives a set of bindings that keep your adapter consistent with the rest of the system. The most
important one is onConnect - call it at the start of every connection attempt. It marks the socket as connecting, runs
the onConnect interceptors registered on the socket and resolves with the connection details to use (url,
queryParams, adapterOptions), or with null when no attempt should be made (already connected, offline, another
attempt in progress or an interceptor failed).
const connect = async () => {
const connection = await onConnect();
if (!connection) {
return socket.adapter.connected;
}
const url = getSocketUrl(connection.url, getQueryParams(connection.queryParams));
// ...open the transport with `url` and `connection.adapterOptions`
};
Use onConnectFailed({ error }) when the transport cannot be created, and onConnected / onDisconnected /
onError / onEvent to report what happens afterwards.
