UNPKG

plug-n-play-ws

Version:

A plug-and-play WebSocket layer on top of Socket.IO with full TypeScript support, zero manual wiring, and production-ready features

1 lines 26.9 kB
{"version":3,"sources":["../../src/types.ts","../../src/client/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// Core types and interfaces for the plug-n-play-ws package\r\n\r\nimport { z } from 'zod';\r\n\r\n/**\r\n * Base event schema for type-safe messaging\r\n */\r\nexport interface BaseEvent {\r\n type: string;\r\n payload?: unknown;\r\n timestamp?: number;\r\n sessionId?: string;\r\n}\r\n\r\n/**\r\n * Connection status enum\r\n */\r\nexport enum ConnectionStatus {\r\n CONNECTING = 'connecting',\r\n CONNECTED = 'connected',\r\n DISCONNECTED = 'disconnected',\r\n RECONNECTING = 'reconnecting',\r\n ERROR = 'error',\r\n}\r\n\r\n/**\r\n * Session metadata interface\r\n */\r\nexport interface SessionMetadata {\r\n id: string;\r\n userId?: string;\r\n tabId?: string;\r\n userAgent?: string;\r\n ip?: string;\r\n connectedAt: Date;\r\n lastSeenAt: Date;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Search query interface\r\n */\r\nexport interface SearchQuery {\r\n query: string;\r\n limit?: number;\r\n offset?: number;\r\n filters?: Record<string, unknown>;\r\n streaming?: boolean;\r\n}\r\n\r\n/**\r\n * Search result interface\r\n */\r\nexport interface SearchResult<T = unknown> {\r\n id: string;\r\n score: number;\r\n data: T;\r\n highlights?: string[];\r\n}\r\n\r\n/**\r\n * Search response interface\r\n */\r\nexport interface SearchResponse<T = unknown> {\r\n query: string;\r\n results: SearchResult<T>[];\r\n total: number;\r\n took: number;\r\n hasMore?: boolean;\r\n}\r\n\r\n/**\r\n * Logger interface for structured logging\r\n */\r\nexport interface Logger {\r\n debug(message: string, meta?: Record<string, unknown>): void;\r\n info(message: string, meta?: Record<string, unknown>): void;\r\n warn(message: string, meta?: Record<string, unknown>): void;\r\n error(message: string, meta?: Record<string, unknown>): void;\r\n}\r\n\r\n/**\r\n * Default console logger implementation\r\n */\r\nexport class ConsoleLogger implements Logger {\r\n debug(message: string, meta?: Record<string, unknown>): void {\r\n console.debug(`[DEBUG] ${message}`, meta || '');\r\n }\r\n\r\n info(message: string, meta?: Record<string, unknown>): void {\r\n console.info(`[INFO] ${message}`, meta || '');\r\n }\r\n\r\n warn(message: string, meta?: Record<string, unknown>): void {\r\n console.warn(`[WARN] ${message}`, meta || '');\r\n }\r\n\r\n error(message: string, meta?: Record<string, unknown>): void {\r\n console.error(`[ERROR] ${message}`, meta || '');\r\n }\r\n}\r\n\r\n/**\r\n * Configuration options for the WebSocket server\r\n */\r\nexport interface ServerConfig {\r\n port?: number;\r\n cors?: {\r\n origin?: string | string[] | boolean;\r\n methods?: string[];\r\n credentials?: boolean;\r\n };\r\n heartbeatInterval?: number;\r\n heartbeatTimeout?: number;\r\n logger?: Logger;\r\n adapter?: IAdapter;\r\n gracefulShutdownTimeout?: number;\r\n maxConnections?: number;\r\n}\r\n\r\n/**\r\n * Configuration options for the WebSocket client\r\n */\r\nexport interface ClientConfig {\r\n url: string;\r\n autoConnect?: boolean;\r\n reconnection?: boolean;\r\n reconnectionAttempts?: number;\r\n reconnectionDelay?: number;\r\n reconnectionDelayMax?: number;\r\n timeout?: number;\r\n forceNew?: boolean;\r\n searchTimeout?: number; // Default: 30000ms (timeout for search operations)\r\n logger?: Logger;\r\n auth?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Generic storage adapter interface\r\n */\r\nexport interface IAdapter {\r\n // Session management\r\n setSession(sessionId: string, metadata: SessionMetadata): Promise<void>;\r\n getSession(sessionId: string): Promise<SessionMetadata | null>;\r\n deleteSession(sessionId: string): Promise<void>;\r\n getAllSessions(): Promise<SessionMetadata[]>;\r\n updateLastSeen(sessionId: string): Promise<void>;\r\n\r\n // Search indexing\r\n indexDocument(id: string, content: string, metadata?: Record<string, unknown>): Promise<void>;\r\n removeDocument(id: string): Promise<void>;\r\n search(query: SearchQuery): Promise<SearchResponse>;\r\n\r\n // Cleanup and maintenance\r\n cleanup(): Promise<void>;\r\n disconnect(): Promise<void>;\r\n}\r\n\r\n/**\r\n * Event type mapping for type-safe messaging\r\n */\r\nexport interface EventMap extends Record<string, unknown> {\r\n // Connection events\r\n connect: { sessionId: string; metadata: SessionMetadata };\r\n disconnect: { sessionId: string; reason: string };\r\n error: { sessionId: string; error: Error };\r\n \r\n // Heartbeat events\r\n ping: { timestamp: number };\r\n pong: { timestamp: number };\r\n \r\n // Search events\r\n search: SearchQuery;\r\n 'search-result': SearchResponse;\r\n 'search-stream': { chunk: SearchResult; isLast: boolean };\r\n \r\n // Custom events (can be extended)\r\n message: { content: string; from?: string };\r\n notification: { title: string; body: string; type?: string };\r\n}\r\n\r\n/**\r\n * Type-safe event emitter interface\r\n */\r\nexport interface TypedEventEmitter<T extends Record<string, unknown> = EventMap> {\r\n on<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\r\n off<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\r\n emit<K extends keyof T>(event: K, data: T[K]): boolean;\r\n once<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\r\n removeAllListeners<K extends keyof T>(event?: K): this;\r\n}\r\n\r\n/**\r\n * Zod schemas for runtime validation\r\n */\r\nexport const SessionMetadataSchema = z.object({\r\n id: z.string(),\r\n userId: z.string().optional(),\r\n tabId: z.string().optional(),\r\n userAgent: z.string().optional(),\r\n ip: z.string().optional(),\r\n connectedAt: z.date(),\r\n lastSeenAt: z.date(),\r\n metadata: z.record(z.unknown()).optional(),\r\n});\r\n\r\nexport const SearchQuerySchema = z.object({\r\n query: z.string().min(1),\r\n limit: z.number().int().positive().max(1000).default(10),\r\n offset: z.number().int().min(0).default(0),\r\n filters: z.record(z.unknown()).optional(),\r\n streaming: z.boolean().default(false),\r\n});\r\n\r\nexport const SearchResultSchema = z.object({\r\n id: z.string(),\r\n score: z.number(),\r\n data: z.unknown(),\r\n highlights: z.array(z.string()).optional(),\r\n});\r\n\r\nexport const SearchResponseSchema = z.object({\r\n query: z.string(),\r\n results: z.array(SearchResultSchema),\r\n total: z.number().int().min(0),\r\n took: z.number().min(0),\r\n hasMore: z.boolean().optional(),\r\n});\r\n\r\n/**\r\n * Utility type for extracting event data from typed event map\r\n */\r\nexport type EventData<T extends Record<string, unknown>, K extends keyof T> = T[K];\r\n\r\n/**\r\n * Utility type for creating custom event maps that extend the base EventMap\r\n */\r\nexport type ExtendEventMap<T extends Record<string, unknown>> = EventMap & T;\r\n","// WebSocket client implementation with Socket.IO\r\n\r\nimport { io, Socket } from 'socket.io-client';\r\nimport { EventEmitter } from 'eventemitter3';\r\nimport {\r\n ClientConfig,\r\n EventMap,\r\n ConnectionStatus,\r\n SearchQuery,\r\n SearchResponse,\r\n SearchResult,\r\n SessionMetadata,\r\n Logger,\r\n ConsoleLogger,\r\n SearchQuerySchema,\r\n} from '../types';\r\n\r\n/**\r\n * Plug-and-play WebSocket client with full type safety and auto-reconnection\r\n */\r\nexport class PlugNPlayClient<T extends Record<string, unknown> = EventMap> {\r\n \r\n private socket: Socket | undefined;\r\n private emitter: EventEmitter;\r\n private logger: Logger;\r\n private status: ConnectionStatus = ConnectionStatus.DISCONNECTED;\r\n private sessionId?: string;\r\n private sessionMetadata?: SessionMetadata;\r\n private reconnectAttempts = 0;\r\n private heartbeatInterval?: ReturnType<typeof setInterval>;\r\n private lastPongTime = 0;\r\n\r\n constructor(private config: ClientConfig) {\r\n this.emitter = new EventEmitter();\r\n this.logger = config.logger || new ConsoleLogger();\r\n \r\n if (config.autoConnect !== false) {\r\n void this.connect();\r\n }\r\n }\r\n\r\n // Event emitter methods\r\n on<K extends keyof T>(event: K, listener: (data: T[K]) => void): this {\r\n this.emitter.on(event as string, listener);\r\n return this;\r\n }\r\n\r\n off<K extends keyof T>(event: K, listener: (data: T[K]) => void): this {\r\n this.emitter.off(event as string, listener);\r\n return this;\r\n }\r\n\r\n emit<K extends keyof T>(event: K, data: T[K]): boolean {\r\n return this.emitter.emit(event as string, data);\r\n }\r\n\r\n once<K extends keyof T>(event: K, listener: (data: T[K]) => void): this {\r\n this.emitter.once(event as string, listener);\r\n return this;\r\n }\r\n\r\n removeAllListeners<K extends keyof T>(event?: K): this {\r\n this.emitter.removeAllListeners(event as string);\r\n return this;\r\n }\r\n\r\n /**\r\n * Connect to the WebSocket server\r\n */\r\n async connect(): Promise<void> {\r\n if (this.socket?.connected) {\r\n return;\r\n }\r\n\r\n this.setStatus(ConnectionStatus.CONNECTING);\r\n this.logger.info('Connecting to WebSocket server', { url: this.config.url });\r\n\r\n return new Promise((resolve, reject) => {\r\n this.socket = io(this.config.url, {\r\n autoConnect: false,\r\n reconnection: this.config.reconnection !== false,\r\n reconnectionAttempts: this.config.reconnectionAttempts || 5,\r\n reconnectionDelay: this.config.reconnectionDelay || 1000,\r\n reconnectionDelayMax: this.config.reconnectionDelayMax || 5000,\r\n timeout: this.config.timeout || 20000,\r\n forceNew: this.config.forceNew || false,\r\n auth: this.config.auth || {},\r\n });\r\n\r\n this.setupSocketHandlers(resolve, reject);\r\n this.socket.connect();\r\n });\r\n }\r\n\r\n /**\r\n * Disconnect from the WebSocket server\r\n */\r\n disconnect(): void {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n delete this.heartbeatInterval;\r\n }\r\n\r\n if (this.socket) {\r\n this.socket.disconnect();\r\n this.socket = undefined;\r\n }\r\n \r\n this.setStatus(ConnectionStatus.DISCONNECTED);\r\n // Don't clear session data immediately - preserve for potential reconnection\r\n // Session data will be refreshed on successful reconnection\r\n this.reconnectAttempts = 0;\r\n }\r\n\r\n /**\r\n * Completely clear session and disconnect\r\n */\r\n clearSession(): void {\r\n this.disconnect();\r\n delete this.sessionId;\r\n delete this.sessionMetadata;\r\n }\r\n\r\n /**\r\n * Send a typed message to the server\r\n */\r\n send<K extends keyof T>(event: K, data: T[K]): boolean {\r\n if (!this.socket?.connected) {\r\n this.logger.warn('Cannot send message: not connected', { event: event as string });\r\n return false;\r\n }\r\n\r\n this.socket.emit(event as string, data);\r\n return true;\r\n }\r\n\r\n /**\r\n * Perform a search query\r\n */\r\n async search(query: SearchQuery): Promise<SearchResponse | null> {\r\n if (!this.socket?.connected) {\r\n this.logger.warn('Cannot search: not connected');\r\n return null;\r\n }\r\n\r\n try {\r\n // Validate search query on client side\r\n const validatedQuery = SearchQuerySchema.parse(query) as SearchQuery;\r\n \r\n return new Promise((resolve) => {\r\n const timeout = setTimeout(() => {\r\n this.socket?.off('search-result', handleResult);\r\n this.socket?.off('error', handleError);\r\n resolve(null);\r\n }, this.config.searchTimeout ?? 30000);\r\n\r\n const handleResult = (result: SearchResponse) => {\r\n clearTimeout(timeout);\r\n this.socket?.off('search-result', handleResult);\r\n this.socket?.off('error', handleError);\r\n resolve(result);\r\n };\r\n\r\n const handleError = (error: { error: Error }) => {\r\n clearTimeout(timeout);\r\n this.socket?.off('search-result', handleResult);\r\n this.socket?.off('error', handleError);\r\n this.logger.error('Search failed', { error: error.error.message });\r\n resolve(null);\r\n };\r\n\r\n this.socket?.once('search-result', handleResult);\r\n this.socket?.once('error', handleError);\r\n this.socket?.emit('search', validatedQuery);\r\n });\r\n } catch (error) {\r\n this.logger.error('Invalid search query', { \r\n error: error instanceof Error ? error.message : 'Unknown validation error' \r\n });\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get current connection status\r\n */\r\n getStatus(): ConnectionStatus {\r\n return this.status;\r\n }\r\n\r\n /**\r\n * Get current session information\r\n */\r\n getSession(): { id?: string; metadata?: SessionMetadata } {\r\n return {\r\n ...(this.sessionId && { id: this.sessionId }),\r\n ...(this.sessionMetadata && { metadata: this.sessionMetadata }),\r\n };\r\n }\r\n\r\n /**\r\n * Check if client is connected\r\n */\r\n isConnected(): boolean {\r\n return this.status === ConnectionStatus.CONNECTED && !!this.socket?.connected;\r\n }\r\n\r\n /**\r\n * Get connection statistics\r\n */\r\n getStats() {\r\n return {\r\n status: this.status,\r\n sessionId: this.sessionId,\r\n reconnectAttempts: this.reconnectAttempts,\r\n lastPongTime: this.lastPongTime,\r\n connected: this.isConnected(),\r\n };\r\n }\r\n\r\n private setupSocketHandlers(\r\n resolve: () => void, \r\n reject: (error: Error) => void\r\n ): void {\r\n if (!this.socket) return;\r\n\r\n // Connection successful\r\n this.socket.on('connect', () => {\r\n this.setStatus(ConnectionStatus.CONNECTED);\r\n this.reconnectAttempts = 0;\r\n this.logger.info('Connected to WebSocket server');\r\n this.startHeartbeat();\r\n resolve();\r\n });\r\n\r\n // Handle session data from server \r\n this.socket.on('session', (data: { sessionId: string; metadata: SessionMetadata }) => {\r\n this.sessionId = data.sessionId;\r\n this.sessionMetadata = data.metadata;\r\n this.emit('connect', data as T['connect']);\r\n });\r\n\r\n // Connection error\r\n this.socket.on('connect_error', (error: Error) => {\r\n this.setStatus(ConnectionStatus.ERROR);\r\n this.logger.error('Connection error', { error: error.message });\r\n \r\n if (this.reconnectAttempts === 0) {\r\n reject(error);\r\n }\r\n });\r\n\r\n // Disconnection\r\n this.socket.on('disconnect', (reason: string) => {\r\n this.setStatus(ConnectionStatus.DISCONNECTED);\r\n this.logger.info('Disconnected from WebSocket server', { reason });\r\n \r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n delete this.heartbeatInterval;\r\n }\r\n\r\n this.emit('disconnect', { sessionId: this.sessionId || '', reason } as T['disconnect']);\r\n });\r\n\r\n // Reconnection attempt\r\n this.socket.on('reconnect_attempt', (attemptNumber: number) => {\r\n this.setStatus(ConnectionStatus.RECONNECTING);\r\n this.reconnectAttempts = attemptNumber;\r\n this.logger.info('Reconnection attempt', { attempt: attemptNumber });\r\n });\r\n\r\n // Reconnection successful\r\n this.socket.on('reconnect', (attemptNumber: number) => {\r\n this.setStatus(ConnectionStatus.CONNECTED);\r\n this.logger.info('Reconnected to WebSocket server', { attempts: attemptNumber });\r\n this.startHeartbeat();\r\n });\r\n\r\n // Handle heartbeat response\r\n this.socket.on('pong', (data: { timestamp: number }) => {\r\n this.lastPongTime = data.timestamp;\r\n });\r\n\r\n // Handle search stream results\r\n this.socket.on('search-stream', (data: { chunk: SearchResult; isLast: boolean }) => {\r\n this.emit('search-stream' as keyof T, data as T[keyof T]);\r\n });\r\n\r\n // Forward all other events\r\n this.socket.onAny((event: string, data: unknown) => {\r\n if (!['connect', 'connect_error', 'disconnect', 'reconnect_attempt', 'reconnect', 'pong', 'search-stream'].includes(event)) {\r\n this.emit(event as keyof T, data as T[keyof T]);\r\n }\r\n });\r\n }\r\n\r\n private setStatus(status: ConnectionStatus): void {\r\n if (this.status !== status) {\r\n const oldStatus = this.status;\r\n this.status = status;\r\n this.logger.debug('Status changed', { from: oldStatus, to: status });\r\n }\r\n }\r\n\r\n private startHeartbeat(): void {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n }\r\n\r\n // Send ping every 30 seconds\r\n this.heartbeatInterval = setInterval(() => {\r\n if (this.socket?.connected) {\r\n this.socket.emit('ping', { timestamp: Date.now() });\r\n }\r\n }, 30000);\r\n }\r\n}\r\n"]}