import { io, type Socket } from 'socket.io-client'; import type { GameSessionAuth } from '../shared/p2p-types.js'; import { PRESENCE_RETRY_MS } from '../../constants/presence.js'; export function createPresence(counter: HTMLElement) { let socket: Socket | undefined, sessionId = ''; let retry: ReturnType | undefined; const unknown = () => { counter.textContent = '접속 확인 중'; }; window.addEventListener('pagehide', () => { clearTimeout(retry); socket?.disconnect(); unknown(); }); window.addEventListener('pageshow', () => { socket?.connect(); }); return { connect(auth: GameSessionAuth) { if (socket && sessionId === auth.gameSessionId) { socket.connect(); return; } clearTimeout(retry); socket?.removeAllListeners(); socket?.disconnect(); unknown(); sessionId = auth.gameSessionId; socket = io('/presence', { auth: { gameSessionId: auth.gameSessionId, token: auth.token }, forceNew: true, autoConnect: false }); socket.on('presence:count', (count: unknown) => { if (Number.isSafeInteger(count) && (count as number) >= 0) counter.textContent = `현재 ${count}명 접속 중`; }); socket.on('connect', () => clearTimeout(retry)); socket.on('disconnect', unknown); socket.on('connect_error', error => { unknown(); clearTimeout(retry); // Middleware errors do not trigger Socket.IO's transport reconnection loop. if (error.message !== 'INVALID_SESSION') retry = setTimeout(() => socket?.connect(), PRESENCE_RETRY_MS); }); socket.connect(); }, }; }