API reference › @evolu/common › WebSocket › WebSocket
Defined in: packages/common/src/WebSocket.ts:98
WebSocket with auto-reconnect.
The API mirrors native WebSocket but retries connections indefinitely by default. This design accounts for the fact that browser and React Native online/offline detection APIs are unreliable — they may report online status incorrectly, so the only reliable approach is to keep attempting reconnection.
Created via createWebSocket which returns a Task.
Disposing starts closing the connection without waiting for the close event so disposal stays immediate. This wrapper treats disposal as local teardown, not as waiting for the full WebSocket close handshake to finish.
How Binary Messages Work
The Server Chooses the Message Type:
- Text (0x1) → Sent as UTF-8 encoded text (always received as a string in the browser).
- Binary (0x2) → Sent as raw binary data (received as a Blob or ArrayBuffer, depending on binaryType).
The Client's binaryType Controls How Binary Data is Processed:
-
If the server sends a text frame (0x1), the browser always delivers event.data as a string, regardless of binaryType.
-
If the server sends a binary frame (0x2), the browser delivers event.data as:
- A Blob (default: "blob")
- An ArrayBuffer ("arraybuffer")
Connecting and sending
import {
assertEqual,
assertLength,
assertOk,
assertSame,
createRun,
createWebSocket,
testCreateWebSocket,
type CreateWebSocket,
type Task,
type WebSocketSendError,
} from "@evolu/common";
const connectAndSend =
(
createSocket: CreateWebSocket = createWebSocket,
): Task<void, WebSocketSendError> =>
async (run) => {
await using socket = await run.ok(
createSocket("wss://example.com", {
protocols: ["evolu"],
binaryType: "arraybuffer",
}),
);
return socket.send("Hello");
};
const socketFactory = testCreateWebSocket();
await using run = createRun();
assertOk(await run(connectAndSend(socketFactory)), undefined);
assertLength(socketFactory.sentMessages, 1);
const message = socketFactory.sentMessages[0];
assertSame(typeof message.data, "string");
assertEqual(
{ url: message.url, data: message.data },
{ url: "wss://example.com", data: "Hello" },
);
Extends
Methods
[asyncDispose]()
[asyncDispose](): PromiseLike<void>;
Defined in: node_modules/@typescript/old/lib/lib.esnext.disposable.d.ts:38
Inherited from
AsyncDisposable.[asyncDispose]
Properties
getReadyState
readonly getReadyState: () => WebSocketReadyState;
Defined in: packages/common/src/WebSocket.ts:107
isOpen
readonly isOpen: () => boolean;
Defined in: packages/common/src/WebSocket.ts:110
Returns true if the WebSocket is open and ready to send data.
reconnect
readonly reconnect: () => void;
Defined in: packages/common/src/WebSocket.ts:131
Abandons the current connection and connects again.
Use it when the connection is dead although it never closed, for example when a request stays unanswered. The wrapper cannot detect that by itself: no close or error event arrives, so its own reconnect never runs.
The connection is dropped without waiting for a close handshake, and neither WebSocketOptions.onClose nor WebSocketOptions.shouldRetryOnClose is consulted, because the close is this call rather than something to learn about or veto. A connection that was open restarts the WebSocketOptions.schedule, as a close after WebSocketOptions.healthyConnectionDuration does; one that was still connecting keeps its backoff, having proved nothing.
A connection already closing or closed is left to settle on its own, and after disposal this does nothing, so a timer or handler that outlives the connection is safe to call it from.
send
send: (data: string | Uint8Array<ArrayBufferLike> | Blob | BufferSource) =>
Result<void, WebSocketSendError>;
Defined in: packages/common/src/WebSocket.ts:103
Send data through the WebSocket connection. Returns Result with an error if the data couldn't be sent.