/* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { EventEmitter } from "events"; import { isNode } from "browser-or-node"; import { wait } from "./Utils"; const WebSocket = isNode ? require("ws") : window.WebSocket; export class WssClient extends EventEmitter { private _retryTimeout: number; private _connected: boolean; private _wss: any; constructor(readonly wssUrl: string) { super(); this._retryTimeout = 15000; // set default at 15 seconds this._connected = false; // set default to not connected this._wss = null; // set default to not connected } public get isConnected(): boolean { return this._connected; } public async connect(): Promise { await this._createConnection(); } public close(): void { this.emit("closing"); if (this._wss) { this._wss.removeAllListeners(); this._wss.on("close", () => this.emit("closed")); this._wss.on("error", (error: { message: string }): void => { if (error.message !== "websocket was closed before the connection was established") return; this.emit("error", error); }); this._wss.close(); } } public send(data: string) { console.log("websocket send", data, this._connected); if (this._connected) { try { this._wss.send(data); console.log("sent!"); } catch (error) { this.emit("error", error); } } } private async _createConnection(): Promise { return new Promise(resolve => { this._wss = new WebSocket(this.wssUrl, { perMessageDeflate: false, handshakeTimeout: 15000, }); this._wss.on("open", () => { this._connected = true; resolve(); }); this._wss.on("connection", () => console.log("websocket handshake")); this._wss.on("upgrade", () => console.log("websocket upgrade")); this._wss.on("close", () => this._closeCallback()); this._wss.on("error", (error: any) => this.emit("error", error)); this._wss.on("message", (message: any): boolean => this.emit("message", message)); }); } private _closeCallback(): void { this._connected = false; this._wss = null; this.emit("disconnected"); void this._retryConnect(); } private async _retryConnect(): Promise { // eslint-disable-next-line no-constant-condition while (true) { try { await wait(this._retryTimeout); await this._createConnection(); return; } catch (error) { this.emit("error", error); } } } }