socket/README.md
2025-04-21 15:18:34 -04:00

4.8 KiB

@endeavorance/socket

Lightweight reconnecting websocket interface

ManagedSocket

A self-reconnecting wrapped WebSocket with built-in heartbeats

new ManagedSocket(url: string): ManagedSocket

Create a new ManagedSocket instance and connect to the provided URL via WebSocket.

The provided URL should use the ws:// or wss:// protocol.

import { ManagedSocket } from "@endeavorance/socket";

const mySocket = new ManagedSocket("wss://socket.my-server.web");

.send<T>(data: T)

Sends the provided data over the socket.

The data can be of any shape as long as it can be serialized (using JSON.stringify under the hood).

If send() is called on a ManagedSocket instance that is not currently connected, it will be enqueued to be sent once the connection is reestablished.

const mySocket = new ManagedSocket("...");
mySocket.send("hello!");
mySocket.send({
  command: "do-something",
  args: ["hello", "world"],
});

.onMessage(handler: SocketDataHandler)

Provide a function to invoke whenever the socket receives a message meant to be handled by your application.

This handler will be passed the blob of data contained within the message, which is typed as unknown.

Your handler function should parse the incoming data to ensure it is of the shape you expect.

const handler = (data: unknown) => {
  console.log("Got some data: " + data);
}

const mySocket = new ManagedSocket("...");
mySocket.onMessage(handler);

.onError(handler: SocketErrorHandler)

Provide a function to invoke when the socket encounters a non-catastrophic error.

Not catastrophic errors may occur during the lifecycle of the WebSocket connection, but are different from Catastrophic errors which only occur if the connection was terminated with a non-reconnect code.

This function will be passed a ManagedSocketError. If no error handler is set, errors will instead be thrown.

const errorHandler = (error: ManagedSocketError) => {
  console.error(error);
}

const mySocket = new ManagedSocket("...");
mySocket.onError(handler);

.onCatastrophicError(handler: SocketCatastrophicErrorHandler)

Provide a function to invoke when the socket is terminated with a non-reconnect code. When this handler is invoked, it means the socket connection is terminated and unable to be recovered automatically. Your handler will be passed the SocketDisconnectCode associated with the connection termination.

You may still attempt to manuall reconnect using the .reconnect() method, but it will not be automatic.

const bigOops = (code) => {
  console.error(`Welp, we're done here. Closed with code: ${code}`);
}

const mySocket = new ManagedSocket("...");
mySocket.onCatastrophicError(bigOops);

.onOpen(SocketOpenHandler)

Provide a function to be invoked when the connection is opened.

No arguments are provided to this handler.

.onClose(SocketCloseHandler)

Provide a function to be invoked when the connection closes cleanly.

No arguments are provided to this handler.

.reconnect()

Attempts to reconnect the socket using an exponential backoff algorithm. Each failed connection attempt will wait a bit longer before the next try.

.close()

Safely close the socket connection.

SocketSpeak

SocketSpeak is a set of utilities for working with the ManagedSocket data interface. It is lower-level and meant primarily for writing servers.

All methods are defined on the SocketSpeak object, exported by the library.

import { SocketSpeak } from "@endeavorance/socket"

createDataMessage<T>(data: T): SocketDataMessage

Wraps the provided data in a well formatted message ready to serialize and send over the socket.

A SocketDataMessage is used for sending application data over the socket.

createHeartbeatMessage(): SocketHeartbeatMessage

Creates a well formatted heartbeat message to serialize and send over the socket.

A SocketHeartbeatMessage is used internally to keep the connection alive and carries a data payload of the current timestamp as a string.

serialize(message: SocketMessage): SerializedSocketMessage

Serialize any SocketMessage. Returns a SerializedSocketMessage which is a branded string type for type safety.

deserialize(data: string): SocketMessage

Attempts to deserialize the provided string into a SocketMessage. Throws a ManagedSocketError if the deserialization fails or the deserialized shape is invalid.

Note: This is not to deserialize your application data messages. The managed socket handles wrapping and unwrapping messages before handing the payload to your application.

prepare<T>(data: T)

Shorthand for `serialize(createDataMessage(data))

isCatastrophicCloseCode(code: SocketCloseCode)

Returns true if the provided SocketCloseCode is a non-reconnect close code, or false otherwise.