UNPKG

@utsp/network-client

Version:

UTSP Network Client - Client-side communication adapters

311 lines (307 loc) 9.1 kB
import { INetworkClient, NetworkClientOptions, NetworkState, NetworkEventHandler } from '@utsp/types'; export { AnyNetworkMessage, ChatMessage, ClientInfo, ErrorMessage, INetworkClient, InputMessage, JoinMessage, JoinResponseMessage, LeaveMessage, LoadMessage, MessageType, NetworkClientOptions, NetworkEventHandler, NetworkMessage, NetworkState, PingMessage, PongMessage, UpdateMessage } from '@utsp/types'; /** * Socket.IO Client Implementation * * Production-ready Socket.IO client for real-time communication with UTSP servers. * Implements the INetworkClient interface with automatic reconnection, latency monitoring, * and comprehensive error handling. Browser-safe with no Node.js dependencies. * * @example Basic Usage * ```typescript * import { SocketIOClient } from '@utsp/network-client'; * * const client = new SocketIOClient({ * url: 'http://localhost:3000', * autoReconnect: true, * debug: false * }); * * await client.connect(); * console.log('Connected:', client.isConnected()); * * client.on('update', (data) => { * console.log('Received update:', data); * }); * * client.send('input', { key: 'ArrowUp' }); * ``` * * @example With Authentication * ```typescript * const client = new SocketIOClient({ * url: 'https://game.example.com', * auth: { * token: 'user-auth-token', * userId: '12345' * } * }); * * await client.connect(); * ``` * * @example Request-Response Pattern * ```typescript * try { * const response = await client.request('getPlayerStats', { playerId: '123' }, 5000); * console.log('Stats:', response); * } catch (error) { * console.error('Request failed:', error); * } * ``` */ /** * Socket.IO client implementation for UTSP network communication * * Features: * - Automatic reconnection with exponential backoff * - Real-time latency monitoring (ping/pong) * - Request-response pattern with timeout * - Type-safe event handling * - Connection state management * - Debug logging * * @implements {INetworkClient} */ declare class SocketIOClient implements INetworkClient { private socket; private options; private _state; private pingTimestamp; private latency; private pingInterval; /** * Create a new Socket.IO client instance * * @param options - Client configuration options * @throws {Error} If URL is invalid or options are malformed * * @example * ```typescript * const client = new SocketIOClient({ * url: 'http://localhost:3000', * autoReconnect: true, * reconnectDelay: 1000, * maxReconnectAttempts: 10, * timeout: 5000, * debug: false * }); * ``` */ constructor(options: NetworkClientOptions); /** * Get current connection state * * @returns Current network state (Disconnected, Connecting, Connected, Reconnecting, Error) * * @example * ```typescript * console.log('State:', client.state); // NetworkState.Connected * ``` */ get state(): NetworkState; /** * Check if client is currently connected * * @returns true if connected and socket is active, false otherwise * * @example * ```typescript * if (client.isConnected()) { * client.send('message', data); * } * ``` */ isConnected(): boolean; /** * Connect to the server * * Establishes a WebSocket connection to the configured server URL. * Automatically sets up reconnection logic if enabled. * * @returns Promise that resolves when connected, rejects on connection error * @throws {Error} If connection fails or times out * * @example * ```typescript * try { * await client.connect(); * console.log('Connected successfully'); * } catch (error) { * console.error('Connection failed:', error); * } * ``` */ connect(): Promise<void>; /** * Disconnect from the server * * Gracefully closes the WebSocket connection and stops all monitoring. * Safe to call multiple times. * * @example * ```typescript * client.disconnect(); * console.log('Disconnected'); * ``` */ disconnect(): void; /** * Send an event to the server * * Uses volatile emit to prevent message queuing during disconnection. * Events sent while disconnected will be silently dropped. * * @param event - Event name to emit * @param data - Event payload (any serializable data) * * @example * ```typescript * client.send('input', { key: 'ArrowUp', timestamp: Date.now() }); * client.send('chat', { message: 'Hello world!' }); * ``` */ send(event: string, data: any): void; /** * Register an event listener * * Listens for events from the server. Multiple handlers can be registered * for the same event. * * @param event - Event name to listen for * @param handler - Callback function to handle event data * * @example * ```typescript * client.on<UpdateMessage>('update', (data) => { * console.log('Game update:', data); * }); * * client.on('chat', (message) => { * console.log('Chat:', message); * }); * ``` */ on<T = any>(event: string, handler: NetworkEventHandler<T>): void; /** * Unregister a specific event listener * * Removes a previously registered handler for an event. The handler reference * must be the exact same function object that was registered. * * @param event - Event name * @param handler - Handler function to remove (must be same reference) * * @example * ```typescript * const handler = (data) => console.log(data); * client.on('update', handler); * // ... later * client.off('update', handler); * ``` */ off<T = any>(event: string, handler: NetworkEventHandler<T>): void; /** * Remove all listeners for an event or all events * * If event name is provided, removes all listeners for that specific event. * If no event name, removes all listeners for all events. * * @param event - Optional event name. If omitted, removes all listeners. * * @example * ```typescript * // Remove all 'update' listeners * client.removeAllListeners('update'); * * // Remove ALL listeners * client.removeAllListeners(); * ``` */ removeAllListeners(event?: string): void; /** * Send a request and wait for response (request-response pattern) * * Implements a request-response pattern on top of Socket.IO events. * Automatically listens for `${event}_response` and handles timeout. * * @param event - Request event name * @param data - Request payload * @param timeout - Timeout in milliseconds (default: 5000ms) * @returns Promise resolving to the response data * @throws {Error} If not connected, request times out, or server returns error * * @example * ```typescript * try { * const stats = await client.request<PlayerStats>( * 'getPlayerStats', * { playerId: '123' }, * 3000 * ); * console.log('Stats:', stats); * } catch (error) { * console.error('Request failed:', error); * } * ``` */ request<T = any>(event: string, data: any, timeout?: number): Promise<T>; /** * Get current network latency (ping time) * * Returns the round-trip time in milliseconds of the most recent ping. * Updated every 2 seconds while connected. * * @returns Latency in milliseconds, or 0 if not yet measured * * @example * ```typescript * console.log('Latency:', client.getPing(), 'ms'); * ``` */ getPing(): number; /** * Destroy the client and clean up all resources * * Disconnects from server, removes all listeners, and releases resources. * Client instance cannot be reused after calling destroy(). * * @example * ```typescript * // Cleanup before page unload * window.addEventListener('beforeunload', () => { * client.destroy(); * }); * ``` */ destroy(): void; /** * Start ping monitoring for latency measurement * * Sends a ping every 2 seconds to measure round-trip time. * Only runs while connected. * * @private */ private startPingMonitor; /** * Stop ping monitoring * * Clears the ping interval timer. * * @private */ private stopPingMonitor; /** * Debug logging utility * * Logs messages when debug mode is enabled. Uses console.warn * to ensure visibility in production environments. * * @param message - Log message * @param data - Optional data to log * @private */ private log; } export { SocketIOClient, SocketIOClient as SocketIOClientType };