Source

socket/websocket-client.js

import { EventEmitter } from "eventemitter3";
/**
 * Simple WebSocket client with event emitter
 */
export class WebSocketClient extends EventEmitter {
    ws;
    connectionId;
    userId;
    investigationId;
    logger;
    /**
     * Create a WebSocket client
     * @param {WebSocket} ws - WebSocket instance
     * @param {string} connectionId - Connection ID
     * @param {string} userId - User ID
     * @param {string | null} investigationId - Investigation ID
     * @param {Logger} logger - Logger instance
     */
    constructor(ws, connectionId, userId, investigationId, logger) {
        super();
        this.ws = ws;
        this.connectionId = connectionId;
        this.userId = userId;
        this.investigationId = investigationId;
        this.logger = logger;
        ws.on("close", (code, reason) => {
            this.logger.info({ code, reason: reason?.toString("utf8") }, "WebSocket client closed");
        });
        ws.on("error", (error) => {
            this.logger.error({ error }, "WebSocket client error");
        });
        // Listen for incoming messages
        ws.on("message", (rawData) => {
            try {
                let text;
                if (Buffer.isBuffer(rawData)) {
                    text = rawData.toString("utf8");
                }
                else if (Array.isArray(rawData)) {
                    text = Buffer.concat(rawData).toString("utf8");
                }
                else if (rawData instanceof ArrayBuffer) {
                    text = Buffer.from(rawData).toString("utf8");
                }
                else {
                    text = String(rawData);
                }
                const parsed = JSON.parse(text);
                const message = parsed;
                if (typeof message === "object" &&
                    message !== null &&
                    typeof message.type === "string" &&
                    message.data !== undefined) {
                    this.emit(message.type, message.data);
                }
            }
            catch (error) {
                logger.error({ error }, "Failed to parse message");
                this.send("error", { message: "Invalid JSON", code: "PARSE_ERROR" });
            }
        });
    }
    /**
     * Send an event to the client
     * @param {string} event - Event name
     * @param {unknown} data - Event data
     */
    send(event, data) {
        if (this.ws.readyState === 1) {
            try {
                this.ws.send(JSON.stringify({ type: event, data }), (error) => {
                    if (error) {
                        this.logger.error({ error, event }, "Failed to send websocket message");
                    }
                });
            }
            catch (error) {
                this.logger.error({ error, event }, "Websocket send threw an error");
            }
        }
    }
}