# @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. ```typescript import { ManagedSocket } from "@endeavorance/socket"; const mySocket = new ManagedSocket("wss://socket.my-server.web"); ``` ### `.send(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. ```typescript 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. ```typescript 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. ```typescript 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. ```typescript 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. ```typescript import { SocketSpeak } from "@endeavorance/socket" ``` ### `createDataMessage(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(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.