UNPKG

opinionated-machine

Version:

Very opinionated DI framework for fastify, built on top of awilix

140 lines (139 loc) 5.13 kB
import type { SSELogger, SSEMessage } from '../sseTypes.js'; import type { RoomBroadcastOptions, SSERoomAdapter, SSERoomManagerConfig, SSERoomMessageHandler } from './types.js'; /** * Manages room membership for SSE connections. * * Provides Socket.IO-style room support for SSE connections with optional * cross-node propagation via adapters (e.g., Redis). * * **Data Structures (per node):** * - `connectionRooms: Map<ConnectionId, Set<RoomId>>` - tracks which rooms each connection is in * - `roomConnections: Map<RoomId, Set<ConnectionId>>` - tracks which connections are in each room * * @example Basic usage (single node) * ```typescript * const roomManager = new SSERoomManager() * * // Join rooms * roomManager.join(connectionId, 'announcements') * roomManager.join(connectionId, ['project:123', 'team:eng']) * * // Query rooms * roomManager.getRooms(connectionId) // ['announcements', 'project:123', 'team:eng'] * roomManager.getConnectionsInRoom('team:eng') // [connectionId, ...] * * // Leave rooms * roomManager.leave(connectionId, 'project:123') * roomManager.leaveAll(connectionId) // Called automatically on disconnect * ``` * * @example With Redis adapter (multi-node) * ```typescript * import { RedisAdapter } from '@opinionated-machine/sse-rooms-redis' * * const roomManager = new SSERoomManager({ * adapter: new RedisAdapter({ pubClient, subClient }) * }) * ``` */ export declare class SSERoomManager { /** Map of connection ID to set of room names */ private readonly connectionRooms; /** Map of room name to set of connection IDs */ private readonly roomConnections; /** Adapter for cross-node communication */ readonly adapter: SSERoomAdapter; /** Unique identifier for this node */ readonly nodeId: string; /** Handler for remote messages from adapter */ private messageHandler?; constructor(config?: SSERoomManagerConfig); /** * Connect the adapter (if applicable). * Call this during server startup. */ connect(): Promise<void>; /** * Disconnect the adapter (if applicable). * Call this during graceful shutdown. */ disconnect(): Promise<void>; /** * Register a handler for messages from other nodes. * The controller uses this to forward messages to local connections. * * @param handler - Callback invoked when a remote message is received */ onRemoteMessage(handler: SSERoomMessageHandler): void; /** * Join one or more rooms. * * @param connectionId - The connection to add to rooms * @param room - Room name or array of room names * @param logger - Used to report adapter subscription failures (optional) */ join(connectionId: string, room: string | string[], logger?: SSELogger): void; /** * Leave one or more rooms. * * @param connectionId - The connection to remove from rooms * @param room - Room name or array of room names * @param logger - Used to report adapter unsubscription failures (optional) */ leave(connectionId: string, room: string | string[], logger?: SSELogger): void; /** * Leave all rooms for a connection. * Called automatically when a connection disconnects. * * @param connectionId - The connection to remove from all rooms * @returns Array of room names the connection was in */ leaveAll(connectionId: string): string[]; /** * Get all rooms a connection is in. * * @param connectionId - The connection to query * @returns Array of room names */ getRooms(connectionId: string): string[]; /** * Get all connection IDs in a room. * * @param room - The room to query * @returns Array of connection IDs */ getConnectionsInRoom(room: string): string[]; /** * Get the number of connections in a room. * * @param room - The room to query * @returns Number of connections */ getConnectionCountInRoom(room: string): number; /** * Check if a connection is in a specific room. * * @param connectionId - The connection to check * @param room - The room to check * @returns true if the connection is in the room */ isInRoom(connectionId: string, room: string): boolean; /** * Get all room names that have at least one connection. * * @returns Array of room names */ getAllRooms(): string[]; /** * Publish a message to a room via the adapter. * This propagates the message to other nodes. * * @param room - The room to publish to * @param message - The SSE message to broadcast * @param options - Broadcast options (e.g. `local: true` to skip adapter) * @param metadata - Optional opaque metadata propagated to other nodes * alongside the message. Used by `SSESubscriptionManager` for cross-node * resolver evaluation; not delivered to clients. */ publish(room: string, message: SSEMessage, options?: RoomBroadcastOptions, metadata?: Record<string, unknown>): Promise<void>; }