From ba73b0a1f707d853c174fcca69b47603b3dc93b4 Mon Sep 17 00:00:00 2001 From: Endeavorance Date: Tue, 7 Jan 2025 15:00:22 -0500 Subject: [PATCH] Add biome and autofix --- biome.json | 31 ++++ build.ts | 8 +- bun.lockb | Bin 10556 -> 14050 bytes package.json | 1 + src/constants.ts | 46 +++--- src/errors.ts | 24 +-- src/index.ts | 14 +- src/managed-socket.ts | 368 +++++++++++++++++++++--------------------- src/messages.ts | 64 ++++---- src/types.ts | 112 ++++++------- 10 files changed, 350 insertions(+), 318 deletions(-) create mode 100644 biome.json diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..99d3350 --- /dev/null +++ b/biome.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false, + "ignore": ["dist", ".next", "public", "*.d.ts", "*.json"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/build.ts b/build.ts index c3da698..b044b59 100644 --- a/build.ts +++ b/build.ts @@ -1,8 +1,8 @@ import dts from "bun-plugin-dts"; await Bun.build({ - entrypoints: ["./src/index.ts"], - outdir: "./dist", - plugins: [dts()], - target: "browser", + entrypoints: ["./src/index.ts"], + outdir: "./dist", + plugins: [dts()], + target: "browser", }); diff --git a/bun.lockb b/bun.lockb index e8b49fb48a11ef4909259031e2b1048a9a73bd33..ff63894f06a9c7e295f1694b6c41d6dd23a13ce5 100755 GIT binary patch delta 3866 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 delta 1542 zcmb_cZ)j9U5Z`@w=jA0aiAED&o;lBWxm-?o$z42hipfhP6wlzF2%*$U$TeCCBx+-Y zn7~D-#Re2S2O(H0Dt@wl5aYiO0YiewNehu;5nGFjAGFx^V@u1${$}4DR4fSM!0c~# zW_EUVW_O+rPHjJ7)z^r1=Hub1k}prsd@*|4)XqP7HMpth+^y}ke}AsmJqTV32}Nf5 z!xdu$EF zl)FslNO#%t3MDXVG>&nQG8k`=?zZ(TF42y? zOX;4gS+>%++m;t81C2oVtsXTm4i2_@mrg4lf zD1)(qblsNwDWNyhoaXMr@f@l^)&<-tL?Q$;%Bkr8koTahivEj|vPG2<)-DAzE(0S? z!pLD2km)s~mg34WwptG6SbSh!uK+VK@|uagGQYQ&;cKxFkgtj4bdc<$t28%QfWs zaqYITGtitmj^BzXr|#OZLcu42+Wa(M8>CRsN4>!c(+?3hg!GS>C;nLc=V*cKX|$qN zlMq9c4jM8=-v+-n^KBqIATRH)>3FEgo;8kDJ0^L60*0NTUsVJO8 zt@tY1T5km2)Q7nMpc8%tV$M%H!yR-c9IYBfskq@DiO0T^!zJ@#rDJj-M8AexCS$9Q Jd+A)&#J{e%1CRg! diff --git a/package.json b/package.json index db12c74..516e5dc 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ ], "type": "module", "devDependencies": { + "@biomejs/biome": "^1.9.4", "@types/bun": "latest", "bun-plugin-dts": "^0.2.3" }, diff --git a/src/constants.ts b/src/constants.ts index c1ce8f3..5cc91b9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,31 +1,31 @@ export enum SocketDisconnectCode { - CLOSE_NORMAL = 1000, - CLOSE_GOING_AWAY = 1001, - CLOSE_PROTOCOL_ERROR = 1002, - CLOSE_UNSUPPORTED = 1003, - CLOSE_NO_STATUS = 1005, - CLOSE_ABNORMAL = 1006, - CLOSE_TOO_LARGE = 1009, - CLOSE_EXTENSION_REQUIRED = 1010, - CLOSE_INTERNAL_ERROR = 1011, - CLOSE_SERVICE_RESTART = 1012, - CLOSE_TRY_AGAIN_LATER = 1013, - CLOSE_TLS_HANDSHAKE = 1015, + CLOSE_NORMAL = 1000, + CLOSE_GOING_AWAY = 1001, + CLOSE_PROTOCOL_ERROR = 1002, + CLOSE_UNSUPPORTED = 1003, + CLOSE_NO_STATUS = 1005, + CLOSE_ABNORMAL = 1006, + CLOSE_TOO_LARGE = 1009, + CLOSE_EXTENSION_REQUIRED = 1010, + CLOSE_INTERNAL_ERROR = 1011, + CLOSE_SERVICE_RESTART = 1012, + CLOSE_TRY_AGAIN_LATER = 1013, + CLOSE_TLS_HANDSHAKE = 1015, } export const NON_RECONNECT_CODES = [ - SocketDisconnectCode.CLOSE_NORMAL, - SocketDisconnectCode.CLOSE_GOING_AWAY, - SocketDisconnectCode.CLOSE_UNSUPPORTED, - SocketDisconnectCode.CLOSE_TOO_LARGE, - SocketDisconnectCode.CLOSE_EXTENSION_REQUIRED, - SocketDisconnectCode.CLOSE_TRY_AGAIN_LATER, - SocketDisconnectCode.CLOSE_TLS_HANDSHAKE, + SocketDisconnectCode.CLOSE_NORMAL, + SocketDisconnectCode.CLOSE_GOING_AWAY, + SocketDisconnectCode.CLOSE_UNSUPPORTED, + SocketDisconnectCode.CLOSE_TOO_LARGE, + SocketDisconnectCode.CLOSE_EXTENSION_REQUIRED, + SocketDisconnectCode.CLOSE_TRY_AGAIN_LATER, + SocketDisconnectCode.CLOSE_TLS_HANDSHAKE, ] as const; export enum ManagedSocketErrorType { - INVALID_MESSAGE_SHAPE = "Invalid message shape.", - CATOSTROPHIC_CLOSE = "Catostrophic close code", - SOCKET_ERROR = "WebSocket error", - CONNECTION_REJECTED = "Connection rejected", + INVALID_MESSAGE_SHAPE = "Invalid message shape.", + CATOSTROPHIC_CLOSE = "Catostrophic close code", + SOCKET_ERROR = "WebSocket error", + CONNECTION_REJECTED = "Connection rejected", } diff --git a/src/errors.ts b/src/errors.ts index 6acea1f..cbaa694 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -1,17 +1,17 @@ import { ManagedSocketErrorType } from "./constants"; export class ManagedSocketError extends Error { - public originalError: Error | ErrorEvent; - public type: ManagedSocketErrorType = ManagedSocketErrorType.SOCKET_ERROR; + public originalError: Error | ErrorEvent; + public type: ManagedSocketErrorType = ManagedSocketErrorType.SOCKET_ERROR; - constructor( - message: string, - originalError: Error | ErrorEvent, - type?: ManagedSocketErrorType, - ) { - super(message); - this.name = "ManagedSocketError"; - this.originalError = originalError; - this.type = type ?? this.type; - } + constructor( + message: string, + originalError: Error | ErrorEvent, + type?: ManagedSocketErrorType, + ) { + super(message); + this.name = "ManagedSocketError"; + this.originalError = originalError; + this.type = type ?? this.type; + } } diff --git a/src/index.ts b/src/index.ts index 246bf58..a0ebfc5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ +import { ManagedSocketErrorType, SocketDisconnectCode } from "./constants"; import { ManagedSocketError } from "./errors"; -import { SocketSpeak } from "./messages"; -import { SocketDisconnectCode, ManagedSocketErrorType } from "./constants"; import { ManagedSocket } from "./managed-socket"; +import { SocketSpeak } from "./messages"; export { - SocketSpeak, - ManagedSocket, - ManagedSocketError, - SocketDisconnectCode, - ManagedSocketErrorType, + SocketSpeak, + ManagedSocket, + ManagedSocketError, + SocketDisconnectCode, + ManagedSocketErrorType, }; diff --git a/src/managed-socket.ts b/src/managed-socket.ts index b67a46a..f9cdc54 100644 --- a/src/managed-socket.ts +++ b/src/managed-socket.ts @@ -13,231 +13,231 @@ type SocketCloseHandler = () => void; type SocketCatostrophicErrorHandler = (error: ManagedSocketError) => void; export type ManagedSocketConnectionState = - | "connecting" - | "open" - | "closing" - | "closed" - | "reconnecting" - | "terminated"; + | "connecting" + | "open" + | "closing" + | "closed" + | "reconnecting" + | "terminated"; export class ManagedSocket { - public readonly url: string; - public state: ManagedSocketConnectionState = "connecting"; - private ws: WebSocket; + public readonly url: string; + public state: ManagedSocketConnectionState = "connecting"; + private ws: WebSocket; - private onMessageHandler: SocketDataHandler | null = null; - private onErrorHandler: SocketErrorHandler | null = null; - private onOpenHandler: SocketOpenHandler | null = null; - private onCloseHandler: SocketCloseHandler | null = null; - private onCatostrophicErrorHandler: SocketCatostrophicErrorHandler | null = - null; + private onMessageHandler: SocketDataHandler | null = null; + private onErrorHandler: SocketErrorHandler | null = null; + private onOpenHandler: SocketOpenHandler | null = null; + private onCloseHandler: SocketCloseHandler | null = null; + private onCatostrophicErrorHandler: SocketCatostrophicErrorHandler | null = + null; - private reconnectAttempts: number; - private maxReconnectDelay: number; - private heartbeatInterval: Timer | null; - private messageQueue: unknown[] = []; - private attemptReconnect = true; + private reconnectAttempts: number; + private maxReconnectDelay: number; + private heartbeatInterval: Timer | null; + private messageQueue: unknown[] = []; + private attemptReconnect = true; - private debugMode = false; + private debugMode = false; - constructor(url: string) { - this.url = url; - this.ws = this.connect(); - this.reconnectAttempts = 0; - this.maxReconnectDelay = MAX_RECONNECT_DELAY; - this.heartbeatInterval = null; - } + constructor(url: string) { + this.url = url; + this.ws = this.connect(); + this.reconnectAttempts = 0; + this.maxReconnectDelay = MAX_RECONNECT_DELAY; + this.heartbeatInterval = null; + } - get connected() { - return this.ws.readyState === WebSocket.OPEN; - } + get connected() { + return this.ws.readyState === WebSocket.OPEN; + } - get native() { - return this.ws; - } + get native() { + return this.ws; + } - set debug(value: boolean) { - this.debugMode = value; - } + set debug(value: boolean) { + this.debugMode = value; + } - debugMessage(...args: unknown[]) { - if (this.debugMode) { - const output = ["[ManagedSocketDebug]", ...args]; - console.log(...output); - } - } + debugMessage(...args: unknown[]) { + if (this.debugMode) { + const output = ["[ManagedSocketDebug]", ...args]; + console.log(...output); + } + } - private sendQueuedMessages() { - // Make a copy of the queue and clear it first. - // this way if the messages fail to send again, - // they just get requeued - const messagesToSend = [...this.messageQueue]; - this.messageQueue = []; - for (const message of messagesToSend) { - this.send(message); - } - } + private sendQueuedMessages() { + // Make a copy of the queue and clear it first. + // this way if the messages fail to send again, + // they just get requeued + const messagesToSend = [...this.messageQueue]; + this.messageQueue = []; + for (const message of messagesToSend) { + this.send(message); + } + } - private connect() { - this.ws = new WebSocket(this.url); + private connect() { + this.ws = new WebSocket(this.url); - this.ws.addEventListener("open", () => { - this.reconnectAttempts = 0; + this.ws.addEventListener("open", () => { + this.reconnectAttempts = 0; - // Announce successful reconnects - if (this.state === "reconnecting") { - this.debugMessage("Reconnected to socket server"); - } + // Announce successful reconnects + if (this.state === "reconnecting") { + this.debugMessage("Reconnected to socket server"); + } - this.onOpenHandler?.(); - this.state = "open"; - this.startHeartbeat(); - this.sendQueuedMessages(); - }); + this.onOpenHandler?.(); + this.state = "open"; + this.startHeartbeat(); + this.sendQueuedMessages(); + }); - this.ws.addEventListener("close", (event) => { - const { code } = event; - this.debugMessage(code); - this.onCloseHandler?.(); + this.ws.addEventListener("close", (event) => { + const { code } = event; + this.debugMessage(code); + this.onCloseHandler?.(); - // If the code received was catostrophic, terminate the connection - if (SocketSpeak.isCatatrophicCloseCode(code)) { - this.handleCatostophicError(code); - } + // If the code received was catostrophic, terminate the connection + if (SocketSpeak.isCatatrophicCloseCode(code)) { + this.handleCatostophicError(code); + } - this.state = "closed"; + this.state = "closed"; - if (this.attemptReconnect) { - this.debugMessage( - "Socket connection closed. Attempting reconnection...", - ); - this.stopHeartbeat(); - this.reconnect(); - } - }); + if (this.attemptReconnect) { + this.debugMessage( + "Socket connection closed. Attempting reconnection...", + ); + this.stopHeartbeat(); + this.reconnect(); + } + }); - this.ws.addEventListener("error", (error) => { - this.debugMessage("WebSocket error", error); + this.ws.addEventListener("error", (error) => { + this.debugMessage("WebSocket error", error); - const errorType = - this.state === "connecting" - ? ManagedSocketErrorType.CONNECTION_REJECTED - : ManagedSocketErrorType.SOCKET_ERROR; + const errorType = + this.state === "connecting" + ? ManagedSocketErrorType.CONNECTION_REJECTED + : ManagedSocketErrorType.SOCKET_ERROR; - const socketError = new ManagedSocketError( - errorType, - new Error(error.currentTarget?.toString()), - errorType, - ); + const socketError = new ManagedSocketError( + errorType, + new Error(error.currentTarget?.toString()), + errorType, + ); - if (this.onErrorHandler !== null) { - return this.onErrorHandler(socketError); - } + if (this.onErrorHandler !== null) { + return this.onErrorHandler(socketError); + } - throw error; - }); + throw error; + }); - this.ws.addEventListener("message", (event) => { - const message = SocketSpeak.deserialize(event.data.toString()); + this.ws.addEventListener("message", (event) => { + const message = SocketSpeak.deserialize(event.data.toString()); - // Ignore heartbeats - if (message.type === "heartbeat") { - this.debugMessage("Received heartbeat"); - return; - } + // Ignore heartbeats + if (message.type === "heartbeat") { + this.debugMessage("Received heartbeat"); + return; + } - if (message.data === undefined || message.data === null) { - this.debugMessage("Received message with no data"); - return; - } + if (message.data === undefined || message.data === null) { + this.debugMessage("Received message with no data"); + return; + } - this.debugMessage("Received message", message.data); - this.onMessageHandler?.(message.data); - }); + this.debugMessage("Received message", message.data); + this.onMessageHandler?.(message.data); + }); - return this.ws; - } + return this.ws; + } - handleCatostophicError(code: SocketDisconnectCode) { - this.state = "terminated"; - this.attemptReconnect = false; - this.debugMessage( - "Socket connection terminated due to non-reconnect close code", - ); + handleCatostophicError(code: SocketDisconnectCode) { + this.state = "terminated"; + this.attemptReconnect = false; + this.debugMessage( + "Socket connection terminated due to non-reconnect close code", + ); - const socketError = new ManagedSocketError( - "Socket connection terminated due to non-reconnect close code", - new Error(code.toString()), - ManagedSocketErrorType.CATOSTROPHIC_CLOSE, - ); + const socketError = new ManagedSocketError( + "Socket connection terminated due to non-reconnect close code", + new Error(code.toString()), + ManagedSocketErrorType.CATOSTROPHIC_CLOSE, + ); - if (this.onCatostrophicErrorHandler !== null) { - return this.onCatostrophicErrorHandler(socketError); - } + if (this.onCatostrophicErrorHandler !== null) { + return this.onCatostrophicErrorHandler(socketError); + } - throw socketError; - } + throw socketError; + } - onMessage(handler: SocketDataHandler) { - this.onMessageHandler = handler; - } + onMessage(handler: SocketDataHandler) { + this.onMessageHandler = handler; + } - onError(handler: (error: ManagedSocketError) => void) { - this.onErrorHandler = handler; - } + onError(handler: (error: ManagedSocketError) => void) { + this.onErrorHandler = handler; + } - onOpen(handler: () => void) { - this.onOpenHandler = handler; - } + onOpen(handler: () => void) { + this.onOpenHandler = handler; + } - onClose(handler: () => void) { - this.onCloseHandler = handler; - } + onClose(handler: () => void) { + this.onCloseHandler = handler; + } - reconnect() { - this.attemptReconnect = true; - this.state = "reconnecting"; - const delay = Math.min( - 1000 * 2 ** this.reconnectAttempts, - this.maxReconnectDelay, - ); - this.debugMessage(`Attempting to reconnect in ${delay}ms`); - setTimeout(() => { - this.reconnectAttempts++; - this.connect(); - }, delay); - } + reconnect() { + this.attemptReconnect = true; + this.state = "reconnecting"; + const delay = Math.min( + 1000 * 2 ** this.reconnectAttempts, + this.maxReconnectDelay, + ); + this.debugMessage(`Attempting to reconnect in ${delay}ms`); + setTimeout(() => { + this.reconnectAttempts++; + this.connect(); + }, delay); + } - close() { - this.attemptReconnect = false; - this.state = "closing"; - this.ws.close(); - } + close() { + this.attemptReconnect = false; + this.state = "closing"; + this.ws.close(); + } - private startHeartbeat() { - this.heartbeatInterval = setInterval(() => { - if (this.ws.readyState === WebSocket.OPEN) { - this.ws.send( - SocketSpeak.serialize(SocketSpeak.createHeartbeatMessage()), - ); - } - }, HEARTBEAT_INTERVAL); - } + private startHeartbeat() { + this.heartbeatInterval = setInterval(() => { + if (this.ws.readyState === WebSocket.OPEN) { + this.ws.send( + SocketSpeak.serialize(SocketSpeak.createHeartbeatMessage()), + ); + } + }, HEARTBEAT_INTERVAL); + } - private stopHeartbeat() { - if (this.heartbeatInterval !== null) { - clearInterval(this.heartbeatInterval); - this.heartbeatInterval = null; - } - } + private stopHeartbeat() { + if (this.heartbeatInterval !== null) { + clearInterval(this.heartbeatInterval); + this.heartbeatInterval = null; + } + } - send(data: T) { - if (this.ws.readyState !== WebSocket.OPEN) { - this.debugMessage("WebSocket is not open. Queuing message."); - this.messageQueue.push(data); - return; - } + send(data: T) { + if (this.ws.readyState !== WebSocket.OPEN) { + this.debugMessage("WebSocket is not open. Queuing message."); + this.messageQueue.push(data); + return; + } - this.ws.send(SocketSpeak.prepare(data)); - } + this.ws.send(SocketSpeak.prepare(data)); + } } diff --git a/src/messages.ts b/src/messages.ts index 9f433b4..8c42a16 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,11 +1,11 @@ import { ManagedSocketErrorType, NON_RECONNECT_CODES } from "./constants"; import { ManagedSocketError } from "./errors"; import { - parseAnyScoketMessage, - type SerializedSocketMessage, - type SocketDataMessage, - type SocketHeartbeatMessage, - type SocketMessage, + type SerializedSocketMessage, + type SocketDataMessage, + type SocketHeartbeatMessage, + type SocketMessage, + parseAnyScoketMessage, } from "./types"; /** @@ -15,10 +15,10 @@ import { * @returns An object representing the socket data message with a type of "message" and the provided data. */ function createDataMessage(data: unknown): SocketDataMessage { - return { - type: "message", - data, - }; + return { + type: "message", + data, + }; } /** @@ -27,10 +27,10 @@ function createDataMessage(data: unknown): SocketDataMessage { * @returns {SocketHeartbeatMessage} An object representing a heartbeat message with the current timestamp. */ function createHeartbeatMessage(): SocketHeartbeatMessage { - return { - type: "heartbeat", - data: new Date().toISOString(), - }; + return { + type: "heartbeat", + data: new Date().toISOString(), + }; } /** @@ -40,7 +40,7 @@ function createHeartbeatMessage(): SocketHeartbeatMessage { * @returns {SerializedSocketMessage} The serialized JSON string representation of the message. */ function serialize(message: SocketMessage): SerializedSocketMessage { - return JSON.stringify(message) as SerializedSocketMessage; + return JSON.stringify(message) as SerializedSocketMessage; } /** @@ -51,16 +51,16 @@ function serialize(message: SocketMessage): SerializedSocketMessage { * @throws {ManagedSocketError} If the JSON string cannot be parsed or if the message shape is invalid. */ function deserialize(data: string): SocketMessage { - try { - const asObj = JSON.parse(data); - return parseAnyScoketMessage(asObj); - } catch (error) { - throw new ManagedSocketError( - "Failed to parse incoming message shape", - error instanceof Error ? error : new Error("Unknown error"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); - } + try { + const asObj = JSON.parse(data); + return parseAnyScoketMessage(asObj); + } catch (error) { + throw new ManagedSocketError( + "Failed to parse incoming message shape", + error instanceof Error ? error : new Error("Unknown error"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); + } } /** @@ -75,7 +75,7 @@ function deserialize(data: string): SocketMessage { * @returns {SerializedSocketMessage} - The serialized socket message. */ function prepare(data: T): SerializedSocketMessage { - return serialize(createDataMessage(data)); + return serialize(createDataMessage(data)); } /** @@ -85,14 +85,14 @@ function prepare(data: T): SerializedSocketMessage { * @returns `true` if the code is in the list of non-reconnect codes, otherwise `false`. */ function isCatatrophicCloseCode(code: number) { - return (NON_RECONNECT_CODES as readonly number[]).includes(code); + return (NON_RECONNECT_CODES as readonly number[]).includes(code); } export const SocketSpeak = { - createDataMessage, - createHeartbeatMessage, - serialize, - deserialize, - isCatatrophicCloseCode, - prepare, + createDataMessage, + createHeartbeatMessage, + serialize, + deserialize, + isCatatrophicCloseCode, + prepare, }; diff --git a/src/types.ts b/src/types.ts index ae19a3b..3d6e93c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,7 +8,7 @@ declare const serializedSocketMessageBrand: unique symbol; * This type is a branded string, ensuring type safety for serialized socket messages. */ export type SerializedSocketMessage = string & { - [serializedSocketMessageBrand]: true; + [serializedSocketMessageBrand]: true; }; /** @@ -16,16 +16,16 @@ export type SerializedSocketMessage = string & { * This message is used to indicate that the connection is still alive. */ export interface SocketHeartbeatMessage { - type: "heartbeat"; - data: string; + type: "heartbeat"; + data: string; } /** * Represents a message with data to be handled by the application */ export interface SocketDataMessage { - type: "message"; - data: unknown; + type: "message"; + data: unknown; } /** @@ -44,18 +44,18 @@ export type SocketMessageType = (typeof MESSAGE_TYPES)[number]; * @throws {ManagedSocketError} If the value is not a string or not included in `MESSAGE_TYPES`. */ export function parseMessageType(value: unknown): SocketMessageType { - if ( - typeof value !== "string" || - !(MESSAGE_TYPES as readonly string[]).includes(value) - ) { - throw new ManagedSocketError( - "Failed to parse incoming message shape", - new Error("Invalid message type"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); - } + if ( + typeof value !== "string" || + !(MESSAGE_TYPES as readonly string[]).includes(value) + ) { + throw new ManagedSocketError( + "Failed to parse incoming message shape", + new Error("Invalid message type"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); + } - return value as SocketMessageType; + return value as SocketMessageType; } /** @@ -66,50 +66,50 @@ export function parseMessageType(value: unknown): SocketMessageType { * @throws {ManagedSocketError} If the incoming message is not a parseable message */ export function parseAnyScoketMessage(value: unknown): SocketMessage { - if (typeof value !== "object" || value === null) { - throw new ManagedSocketError( - "Failed to parse incoming message shape: value was not an object", - new Error("Invalid message shape"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); - } + if (typeof value !== "object" || value === null) { + throw new ManagedSocketError( + "Failed to parse incoming message shape: value was not an object", + new Error("Invalid message shape"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); + } - if (!("type" in value) || !("data" in value)) { - throw new ManagedSocketError( - "Failed to parse incoming message shape: missing type or data", - new Error("Invalid message shape"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); - } + if (!("type" in value) || !("data" in value)) { + throw new ManagedSocketError( + "Failed to parse incoming message shape: missing type or data", + new Error("Invalid message shape"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); + } - const { type: incomingType, data: incomingData } = value; - const type = parseMessageType(incomingType); + const { type: incomingType, data: incomingData } = value; + const type = parseMessageType(incomingType); - if (type === "heartbeat") { - if (typeof incomingData !== "string") { - throw new ManagedSocketError( - "Failed to parse incoming message shape: heartbeat data was not a string", - new Error("Invalid message shape"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); - } + if (type === "heartbeat") { + if (typeof incomingData !== "string") { + throw new ManagedSocketError( + "Failed to parse incoming message shape: heartbeat data was not a string", + new Error("Invalid message shape"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); + } - return { - type, - data: incomingData, - }; - } + return { + type, + data: incomingData, + }; + } - if (type === "message") { - return { - type, - data: incomingData, - }; - } + if (type === "message") { + return { + type, + data: incomingData, + }; + } - throw new ManagedSocketError( - "Failed to parse incoming message shape", - new Error("Invalid message type"), - ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, - ); + throw new ManagedSocketError( + "Failed to parse incoming message shape", + new Error("Invalid message type"), + ManagedSocketErrorType.INVALID_MESSAGE_SHAPE, + ); }