import { v4 as uuidv4 } from "uuid"; export const createWebSocket = (apiUrl) => { let socket; let messageStream = ""; let isStreaming = false; let onMessageCallback = () => {}; let currentUuid = uuidv4(); let formattedMessage = new Set(); const connect = () => { socket = new WebSocket(apiUrl); socket.onopen = () => { console.log("WebSocket connection opened."); isStreaming = true; }; socket.onmessage = (event) => { const message = event.data; messageStream += message; if (messageStream.includes("%S%")) { messageStream = ""; isStreaming = true; } if (messageStream.includes("%E%")) { if (!isStreaming) { currentUuid = uuidv4(); } } if (messageStream.includes("%E%")) { isStreaming = false; } onMessageCallback(JSON.stringify("%S%" + messageStream)); }; socket.onclose = (event) => { if (event.wasClean) { console.log("WebSocket connection closed cleanly."); } else { console.log("WebSocket connection closed unexpectedly."); } isStreaming = false; }; socket.onerror = (error) => { console.error("WebSocket error:", error); isStreaming = false; }; }; const sendMessage = (message) => { if (socket && socket.readyState === WebSocket.OPEN) { socket.send(message); } else { console.error("WebSocket is not open."); } }; const onMessage = (callback) => { onMessageCallback = callback; }; const formatStream = (rawMessage) => { let parsedData = JSON?.parse(rawMessage); if ( parsedData.includes("%S%") && !parsedData.endsWith("%S") && !parsedData.endsWith("%E") && !parsedData.endsWith("%") && !parsedData.includes("%J%") ) { // Check if an object with the current UUID already exists in the set let existingObj = Array.from(formattedMessage).find( (obj) => obj.id === currentUuid ); if (existingObj) { // Update the content of the existing object existingObj.content = parsedData.replace(/%S%|%J%\s*\{\s*\}|%E%/g, ""); } else { // Add a new object to the set formattedMessage.add({ id: currentUuid, content: parsedData.replace(/%S%|%J%\s*\{\s*\}|%E%/g, ""), }); } } return Array.from(formattedMessage); }; const refresh = () => { if (socket) { socket.close(); } connect(); }; connect(); return { sendMessage, onMessage, formatStream, isStreaming: () => isStreaming, refresh, }; };