import { ref, onUnmounted } from "vue"; import { io, Socket } from "socket.io-client"; // Singleton socket instance let socketInstance: Socket | null = null; export function useSocket() { const connected = ref(false); const error = ref(null); // Get or create socket instance const getSocket = (): Socket => { if (!socketInstance) { // Determine the server URL based on environment const isDev = import.meta.env?.DEV ?? import.meta.env?.MODE === "development"; let serverUrl: string; if (isDev) { // Development: Use same host as frontend, port 3000 // This allows accessing from local IP (e.g., 192.168.x.x:5173) const currentHost = window.location.hostname; serverUrl = `http://${currentHost}:3000`; } else { // Production: same origin serverUrl = window.location.origin; } console.log("[Socket.io] Connecting to:", serverUrl); socketInstance = io(serverUrl, { autoConnect: true, reconnection: true, reconnectionDelay: 1000, reconnectionAttempts: 5 }); // Connection event handlers socketInstance.on("connect", () => { connected.value = true; error.value = null; console.log("[Socket.io] Connected:", socketInstance?.id); }); socketInstance.on("disconnect", (reason) => { connected.value = false; console.log("[Socket.io] Disconnected:", reason); }); socketInstance.on("connect_error", (err) => { error.value = err.message; console.error("[Socket.io] Connection error:", err.message); }); } return socketInstance; }; // Send echo test message const sendEcho = (message: string): Promise => { return new Promise((resolve, reject) => { const socket = getSocket(); if (!socket.connected) { reject(new Error("Socket not connected")); return; } // Send echo request and wait for response socket.emit( "echo", { message, timestamp: new Date().toISOString() }, (response: any) => { if (response.error) { reject(new Error(response.error)); } else { resolve(response.message); } } ); // Timeout after 5 seconds setTimeout(() => { reject(new Error("Echo request timeout")); }, 5000); }); }; // Clean up on unmount onUnmounted(() => { // Note: We don't disconnect the singleton instance // It will be reused by other components }); return { socket: getSocket(), connected, error, sendEcho }; } // Export function to manually disconnect (for cleanup) export function disconnectSocket() { if (socketInstance) { socketInstance.disconnect(); socketInstance = null; } }