honeydrop 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,748 @@
1
+ import { Socket, ManagerOptions, SocketOptions } from 'socket.io-client';
2
+
3
+ /**
4
+ * Honeydrop Logger
5
+ * Debug and logging utilities for development
6
+ */
7
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
8
+ interface LoggerOptions {
9
+ level?: LogLevel;
10
+ prefix?: string;
11
+ enabled?: boolean;
12
+ }
13
+ declare class Logger {
14
+ private level;
15
+ private prefix;
16
+ private enabled;
17
+ private isBrowser;
18
+ constructor(options?: LoggerOptions);
19
+ /**
20
+ * Set the logging level
21
+ */
22
+ setLevel(level: LogLevel): void;
23
+ /**
24
+ * Enable or disable logging
25
+ */
26
+ setEnabled(enabled: boolean): void;
27
+ /**
28
+ * Check if logging is enabled for a specific level
29
+ */
30
+ private shouldLog;
31
+ /**
32
+ * Format the log message
33
+ */
34
+ private formatMessage;
35
+ /**
36
+ * Log a debug message
37
+ */
38
+ debug(message: string, ...args: unknown[]): void;
39
+ /**
40
+ * Log an info message
41
+ */
42
+ info(message: string, ...args: unknown[]): void;
43
+ /**
44
+ * Log a warning message
45
+ */
46
+ warn(message: string, ...args: unknown[]): void;
47
+ /**
48
+ * Log an error message
49
+ */
50
+ error(message: string, ...args: unknown[]): void;
51
+ /**
52
+ * Log a connection event
53
+ */
54
+ connection(event: 'connected' | 'disconnected' | 'reconnecting' | 'reconnected', details?: unknown): void;
55
+ /**
56
+ * Log an event emission
57
+ */
58
+ emit(event: string, data?: unknown): void;
59
+ /**
60
+ * Log an event reception
61
+ */
62
+ receive(event: string, data?: unknown): void;
63
+ }
64
+
65
+ /**
66
+ * Honeydrop Reconnection Handler
67
+ * Manages automatic reconnection with customizable retry strategies
68
+ */
69
+
70
+ type ReconnectionStrategy = 'linear' | 'exponential';
71
+ interface ReconnectionOptions {
72
+ enabled?: boolean;
73
+ maxAttempts?: number;
74
+ delay?: number;
75
+ maxDelay?: number;
76
+ strategy?: ReconnectionStrategy;
77
+ onReconnecting?: (attempt: number) => void;
78
+ onReconnected?: () => void;
79
+ onFailed?: () => void;
80
+ }
81
+ declare class ReconnectionHandler {
82
+ private options;
83
+ private callbacks;
84
+ private socket;
85
+ private logger;
86
+ private attempts;
87
+ private timer;
88
+ private isReconnecting;
89
+ constructor(options: ReconnectionOptions, logger: Logger);
90
+ /**
91
+ * Set the socket instance to manage
92
+ */
93
+ setSocket(socket: Socket): void;
94
+ /**
95
+ * Calculate the delay for the next reconnection attempt
96
+ */
97
+ private calculateDelay;
98
+ /**
99
+ * Setup socket event listeners for reconnection
100
+ */
101
+ private setupListeners;
102
+ /**
103
+ * Start the reconnection process
104
+ */
105
+ private startReconnection;
106
+ /**
107
+ * Attempt a single reconnection
108
+ */
109
+ private attemptReconnection;
110
+ /**
111
+ * Manually trigger a reconnection
112
+ */
113
+ reconnect(): void;
114
+ /**
115
+ * Reset reconnection state
116
+ */
117
+ private reset;
118
+ /**
119
+ * Stop reconnection attempts
120
+ */
121
+ stop(): void;
122
+ /**
123
+ * Get current reconnection status
124
+ */
125
+ getStatus(): {
126
+ isReconnecting: boolean;
127
+ attempts: number;
128
+ };
129
+ /**
130
+ * Update reconnection options
131
+ */
132
+ updateOptions(options: Partial<ReconnectionOptions>): void;
133
+ }
134
+
135
+ /**
136
+ * Honeydrop Namespaced Events
137
+ * Provides namespaced event prefixing for cleaner event organization
138
+ */
139
+ interface NamespacedEmitter {
140
+ on(event: string, handler: (...args: unknown[]) => void): void;
141
+ once(event: string, handler: (...args: unknown[]) => void): void;
142
+ off(event: string, handler?: (...args: unknown[]) => void): void;
143
+ emit(event: string, ...args: unknown[]): void;
144
+ }
145
+ type NamespaceDelimiter = ':' | '/' | '.' | '_';
146
+ interface NamespaceOptions {
147
+ delimiter?: NamespaceDelimiter;
148
+ }
149
+ declare class NamespacedEvents {
150
+ private name;
151
+ private delimiter;
152
+ private emitter;
153
+ constructor(name: string, emitter: NamespacedEmitter, options?: NamespaceOptions);
154
+ /**
155
+ * Get the full namespaced event name
156
+ */
157
+ private getEventName;
158
+ /**
159
+ * Register an event listener with namespace prefix
160
+ */
161
+ on(event: string, handler: (...args: unknown[]) => void): void;
162
+ /**
163
+ * Register a one-time event listener with namespace prefix
164
+ */
165
+ once(event: string, handler: (...args: unknown[]) => void): void;
166
+ /**
167
+ * Remove an event listener from namespaced event
168
+ */
169
+ off(event: string, handler?: (...args: unknown[]) => void): void;
170
+ /**
171
+ * Emit an event with namespace prefix
172
+ */
173
+ emit(event: string, ...args: unknown[]): void;
174
+ /**
175
+ * Get the namespace name
176
+ */
177
+ getName(): string;
178
+ /**
179
+ * Get the delimiter used for this namespace
180
+ */
181
+ getDelimiter(): NamespaceDelimiter;
182
+ /**
183
+ * Create a sub-namespace
184
+ */
185
+ sub(name: string): NamespacedEvents;
186
+ }
187
+
188
+ /**
189
+ * Honeydrop Offline Queue
190
+ * Stores events when disconnected and flushes them on reconnect
191
+ */
192
+
193
+ interface QueuedEvent {
194
+ event: string;
195
+ args: unknown[];
196
+ timestamp: number;
197
+ }
198
+ interface OfflineQueueOptions {
199
+ /** Enable offline queueing (default: true) */
200
+ enabled?: boolean;
201
+ /** Maximum number of events to queue (default: 100, 0 = unlimited) */
202
+ maxSize?: number;
203
+ /** Maximum age of events in ms before they're discarded (default: 0 = no expiry) */
204
+ maxAge?: number;
205
+ /** Called when an event is queued */
206
+ onQueued?: (event: QueuedEvent) => void;
207
+ /** Called when events are flushed */
208
+ onFlushed?: (count: number) => void;
209
+ /** Called when queue is full and event is dropped */
210
+ onDropped?: (event: QueuedEvent) => void;
211
+ }
212
+ declare class OfflineQueue {
213
+ private queue;
214
+ private options;
215
+ private logger;
216
+ private socket;
217
+ constructor(options: OfflineQueueOptions | undefined, logger: Logger);
218
+ /**
219
+ * Set the socket instance
220
+ */
221
+ setSocket(socket: Socket): void;
222
+ /**
223
+ * Add an event to the queue
224
+ * Returns true if queued, false if dropped
225
+ */
226
+ enqueue(event: string, ...args: unknown[]): boolean;
227
+ /**
228
+ * Flush all queued events to the socket
229
+ */
230
+ flush(): void;
231
+ /**
232
+ * Get current queue length
233
+ */
234
+ get length(): number;
235
+ /**
236
+ * Get all queued events (read-only copy)
237
+ */
238
+ getQueue(): readonly QueuedEvent[];
239
+ /**
240
+ * Clear all queued events
241
+ */
242
+ clear(): void;
243
+ /**
244
+ * Check if queueing is enabled
245
+ */
246
+ get enabled(): boolean;
247
+ /**
248
+ * Enable or disable queueing
249
+ */
250
+ setEnabled(enabled: boolean): void;
251
+ }
252
+
253
+ /**
254
+ * Honeydrop Connection Monitor
255
+ * Tracks connection health, latency, and quality
256
+ */
257
+
258
+ type ConnectionQuality = 'excellent' | 'good' | 'fair' | 'poor' | 'disconnected';
259
+ interface ConnectionMonitorOptions {
260
+ /** Enable automatic ping monitoring (default: true) */
261
+ enabled?: boolean;
262
+ /** Ping interval in ms (default: 5000) */
263
+ pingInterval?: number;
264
+ /** Ping timeout in ms (default: 3000) */
265
+ pingTimeout?: number;
266
+ /** Number of pings to average for latency (default: 5) */
267
+ sampleSize?: number;
268
+ /** Quality thresholds in ms */
269
+ thresholds?: {
270
+ excellent?: number;
271
+ good?: number;
272
+ fair?: number;
273
+ };
274
+ /** Called when connection quality changes */
275
+ onQualityChange?: (quality: ConnectionQuality, latency: number) => void;
276
+ }
277
+ declare class ConnectionMonitor {
278
+ private socket;
279
+ private options;
280
+ private logger;
281
+ private intervalId;
282
+ private latencySamples;
283
+ private currentQuality;
284
+ private lastPingTime;
285
+ constructor(options: ConnectionMonitorOptions | undefined, logger: Logger);
286
+ /**
287
+ * Set the socket instance and start monitoring
288
+ */
289
+ setSocket(socket: Socket): void;
290
+ /**
291
+ * Start automatic ping monitoring
292
+ */
293
+ start(): void;
294
+ /**
295
+ * Stop automatic ping monitoring
296
+ */
297
+ stop(): void;
298
+ /**
299
+ * Perform a single ping and return the latency
300
+ */
301
+ ping(): Promise<number>;
302
+ /**
303
+ * Record a latency sample and update quality
304
+ */
305
+ private recordLatency;
306
+ /**
307
+ * Update the current quality and notify listeners
308
+ */
309
+ private updateQuality;
310
+ /**
311
+ * Calculate quality based on latency thresholds
312
+ */
313
+ private calculateQuality;
314
+ /**
315
+ * Get average latency from samples
316
+ */
317
+ getAverageLatency(): number;
318
+ /**
319
+ * Get the last recorded latency
320
+ */
321
+ getLatency(): number;
322
+ /**
323
+ * Get current connection quality
324
+ */
325
+ getQuality(): ConnectionQuality;
326
+ /**
327
+ * Get all latency samples
328
+ */
329
+ getLatencySamples(): readonly number[];
330
+ /**
331
+ * Check if monitoring is active
332
+ */
333
+ get isMonitoring(): boolean;
334
+ /**
335
+ * Enable or disable monitoring
336
+ */
337
+ setEnabled(enabled: boolean): void;
338
+ }
339
+
340
+ /**
341
+ * Honeydrop Room Manager
342
+ * Client-side helpers for room-based event patterns
343
+ */
344
+
345
+ interface RoomEmitter {
346
+ /** Emit an event to the room */
347
+ emit(event: string, ...args: unknown[]): void;
348
+ }
349
+ interface RoomManagerOptions {
350
+ /** Event name used to join rooms (default: 'join') */
351
+ joinEvent?: string;
352
+ /** Event name used to leave rooms (default: 'leave') */
353
+ leaveEvent?: string;
354
+ }
355
+ declare class RoomManager {
356
+ private socket;
357
+ private options;
358
+ private logger;
359
+ private joinedRooms;
360
+ constructor(options: RoomManagerOptions | undefined, logger: Logger);
361
+ /**
362
+ * Set the socket instance
363
+ */
364
+ setSocket(socket: Socket): void;
365
+ /**
366
+ * Join a room
367
+ * @param room - Room name to join
368
+ * @param data - Optional data to send with join request
369
+ */
370
+ join(room: string, data?: unknown): void;
371
+ /**
372
+ * Leave a room
373
+ * @param room - Room name to leave
374
+ * @param data - Optional data to send with leave request
375
+ */
376
+ leave(room: string, data?: unknown): void;
377
+ /**
378
+ * Create an emitter scoped to a room
379
+ * Events are emitted with room as first argument
380
+ * @param room - Target room
381
+ */
382
+ toRoom(room: string): RoomEmitter;
383
+ /**
384
+ * Get list of currently joined rooms
385
+ */
386
+ getRooms(): string[];
387
+ /**
388
+ * Check if currently in a room
389
+ */
390
+ isInRoom(room: string): boolean;
391
+ /**
392
+ * Leave all rooms
393
+ */
394
+ leaveAll(): void;
395
+ }
396
+
397
+ /**
398
+ * Honeydrop Utility Functions
399
+ * Helper functions for common Socket.IO operations
400
+ */
401
+
402
+ interface EmitItem {
403
+ event: string;
404
+ data?: unknown;
405
+ }
406
+ interface EmitWithAckItem extends EmitItem {
407
+ timeout?: number;
408
+ }
409
+ /**
410
+ * Emit multiple events at once
411
+ */
412
+ declare function emitMultiple(socket: Socket, events: EmitItem[]): void;
413
+ /**
414
+ * Emit multiple events with acknowledgment support
415
+ */
416
+ declare function emitMultipleWithAck(socket: Socket, events: EmitWithAckItem[]): Promise<unknown[]>;
417
+ /**
418
+ * Wait for a specific event with optional timeout
419
+ */
420
+ declare function waitForEvent(socket: Socket, event: string, timeout?: number): Promise<unknown>;
421
+ /**
422
+ * Wait for any of the specified events
423
+ */
424
+ declare function waitForAnyEvent(socket: Socket, events: string[], timeout?: number): Promise<{
425
+ event: string;
426
+ data: unknown;
427
+ }>;
428
+ /**
429
+ * Create a promise-based emit with acknowledgment
430
+ */
431
+ declare function emitWithAck(socket: Socket, event: string, data?: unknown, timeout?: number): Promise<unknown>;
432
+ /**
433
+ * Check if socket is connected
434
+ */
435
+ declare function isConnected(socket: Socket | null): boolean;
436
+ /**
437
+ * Get socket connection info
438
+ */
439
+ declare function getConnectionInfo(socket: Socket | null): {
440
+ connected: boolean;
441
+ id: string | null;
442
+ transport: string | null;
443
+ };
444
+ /**
445
+ * Create a throttled emit function
446
+ */
447
+ declare function createThrottledEmit(socket: Socket, event: string, intervalMs: number): (data?: unknown) => void;
448
+ /**
449
+ * Create a debounced emit function
450
+ */
451
+ declare function createDebouncedEmit(socket: Socket, event: string, delayMs: number): (data?: unknown) => void;
452
+
453
+ /**
454
+ * Honeydrop - Main Class
455
+ * The core Socket.IO helper providing easy connection management and event handling
456
+ */
457
+
458
+ interface HoneydropOptions {
459
+ /** Enable debug logging */
460
+ debug?: boolean;
461
+ /** Log level */
462
+ logLevel?: LogLevel;
463
+ /** Reconnection configuration */
464
+ reconnection?: ReconnectionOptions;
465
+ /** Offline queue configuration */
466
+ offlineQueue?: OfflineQueueOptions;
467
+ /** Connection monitor configuration */
468
+ connectionMonitor?: ConnectionMonitorOptions;
469
+ /** Room manager configuration */
470
+ roomManager?: RoomManagerOptions;
471
+ /** Default namespace delimiter */
472
+ namespaceDelimiter?: NamespaceDelimiter;
473
+ /** Socket.IO client options */
474
+ socketOptions?: Partial<ManagerOptions & SocketOptions>;
475
+ /** Auto-connect on instantiation */
476
+ autoConnect?: boolean;
477
+ }
478
+ declare class Honeydrop {
479
+ private socket;
480
+ private url;
481
+ private options;
482
+ private logger;
483
+ private eventManager;
484
+ private reconnectionHandler;
485
+ private offlineQueue;
486
+ private connectionMonitor;
487
+ private roomManager;
488
+ private namespaces;
489
+ constructor(url: string, options?: HoneydropOptions);
490
+ /**
491
+ * Connect to the Socket.IO server
492
+ */
493
+ connect(): Socket;
494
+ /**
495
+ * Disconnect from the server and cleanup all listeners
496
+ */
497
+ disconnect(): void;
498
+ /**
499
+ * Register an event listener
500
+ */
501
+ on(event: string, handler: (...args: unknown[]) => void): this;
502
+ /**
503
+ * Register a one-time event listener
504
+ */
505
+ once(event: string, handler: (...args: unknown[]) => void): this;
506
+ /**
507
+ * Remove event listener(s)
508
+ */
509
+ off(event: string, handler?: (...args: unknown[]) => void): this;
510
+ /**
511
+ * Emit an event
512
+ * If disconnected and offline queue is enabled, the event will be queued
513
+ */
514
+ emit(event: string, ...args: unknown[]): this;
515
+ /**
516
+ * Emit multiple events at once
517
+ */
518
+ emitMultiple(events: EmitItem[]): this;
519
+ /**
520
+ * Emit with acknowledgment
521
+ */
522
+ emitWithAck(event: string, data?: unknown, timeout?: number): Promise<unknown>;
523
+ /**
524
+ * Request/Response pattern (RPC-style)
525
+ * Emits an event and waits for a response event
526
+ * @param event - Event to emit
527
+ * @param data - Data to send
528
+ * @param options - Request options
529
+ */
530
+ request<T = unknown>(event: string, data?: unknown, options?: {
531
+ timeout?: number;
532
+ responseEvent?: string;
533
+ }): Promise<T>;
534
+ /**
535
+ * Emit with automatic retry on failure
536
+ * @param event - Event to emit
537
+ * @param data - Data to send
538
+ * @param options - Retry options
539
+ */
540
+ emitWithRetry(event: string, data?: unknown, options?: {
541
+ maxRetries?: number;
542
+ retryDelay?: number;
543
+ timeout?: number;
544
+ onRetry?: (attempt: number, error: Error) => void;
545
+ }): Promise<unknown>;
546
+ /**
547
+ * Emit multiple events with acknowledgment
548
+ */
549
+ emitMultipleWithAck(events: EmitWithAckItem[]): Promise<unknown[]>;
550
+ /**
551
+ * Register handlers for multiple events at once
552
+ */
553
+ onMultiple(events: string[], handler: (event: string, ...args: unknown[]) => void): this;
554
+ /**
555
+ * Register a handler that fires once when any of the specified events occur
556
+ */
557
+ onceAny(events: string[], handler: (event: string, ...args: unknown[]) => void): this;
558
+ /**
559
+ * Wait for a specific event
560
+ */
561
+ waitFor(event: string, timeout?: number): Promise<unknown>;
562
+ /**
563
+ * Wait for any of the specified events
564
+ */
565
+ waitForAny(events: string[], timeout?: number): Promise<{
566
+ event: string;
567
+ data: unknown;
568
+ }>;
569
+ /**
570
+ * Create a namespaced event emitter
571
+ */
572
+ namespace(name: string, options?: NamespaceOptions): NamespacedEvents;
573
+ /**
574
+ * Create a throttled emit function for an event
575
+ */
576
+ throttle(event: string, intervalMs: number): (data?: unknown) => void;
577
+ /**
578
+ * Create a debounced emit function for an event
579
+ */
580
+ debounce(event: string, delayMs: number): (data?: unknown) => void;
581
+ /**
582
+ * Get the underlying Socket.IO socket instance
583
+ */
584
+ getSocket(): Socket | null;
585
+ /**
586
+ * Check if connected
587
+ */
588
+ get connected(): boolean;
589
+ /**
590
+ * Get socket ID
591
+ */
592
+ get id(): string | undefined;
593
+ /**
594
+ * Get connection info
595
+ */
596
+ getConnectionInfo(): {
597
+ connected: boolean;
598
+ id: string | null;
599
+ transport: string | null;
600
+ };
601
+ /**
602
+ * Manually trigger reconnection
603
+ */
604
+ reconnect(): void;
605
+ /**
606
+ * Get reconnection status
607
+ */
608
+ getReconnectionStatus(): {
609
+ isReconnecting: boolean;
610
+ attempts: number;
611
+ } | null;
612
+ /**
613
+ * Get event listener count
614
+ */
615
+ listenerCount(event: string): number;
616
+ /**
617
+ * Get all registered event names
618
+ */
619
+ eventNames(): string[];
620
+ /**
621
+ * Enable or disable debug logging
622
+ */
623
+ setDebug(enabled: boolean): this;
624
+ /**
625
+ * Set log level
626
+ */
627
+ setLogLevel(level: LogLevel): this;
628
+ /**
629
+ * Get the number of queued events (when offline)
630
+ */
631
+ getQueueLength(): number;
632
+ /**
633
+ * Get all queued events (read-only)
634
+ */
635
+ getQueuedEvents(): readonly {
636
+ event: string;
637
+ args: unknown[];
638
+ timestamp: number;
639
+ }[];
640
+ /**
641
+ * Clear the offline queue
642
+ */
643
+ clearQueue(): this;
644
+ /**
645
+ * Enable or disable offline queueing
646
+ */
647
+ setOfflineQueue(enabled: boolean): this;
648
+ /**
649
+ * Ping the server and get latency
650
+ */
651
+ ping(): Promise<number>;
652
+ /**
653
+ * Get average latency to server
654
+ */
655
+ getLatency(): number;
656
+ /**
657
+ * Get current connection quality
658
+ */
659
+ getConnectionQuality(): ConnectionQuality;
660
+ /**
661
+ * Enable or disable connection monitoring
662
+ */
663
+ setConnectionMonitoring(enabled: boolean): this;
664
+ /**
665
+ * Join a room
666
+ */
667
+ join(room: string, data?: unknown): this;
668
+ /**
669
+ * Leave a room
670
+ */
671
+ leave(room: string, data?: unknown): this;
672
+ /**
673
+ * Create a room-scoped emitter
674
+ */
675
+ toRoom(room: string): RoomEmitter;
676
+ /**
677
+ * Get list of joined rooms
678
+ */
679
+ getRooms(): string[];
680
+ /**
681
+ * Check if in a specific room
682
+ */
683
+ isInRoom(room: string): boolean;
684
+ }
685
+
686
+ /**
687
+ * Honeydrop Event Manager
688
+ * Tracks and manages event listeners with auto-cleanup capabilities
689
+ */
690
+
691
+ declare class EventManager {
692
+ private listeners;
693
+ private socket;
694
+ private logger;
695
+ constructor(logger: Logger);
696
+ /**
697
+ * Set the socket instance to manage
698
+ */
699
+ setSocket(socket: Socket): void;
700
+ /**
701
+ * Register an event listener
702
+ */
703
+ on(event: string, handler: (...args: unknown[]) => void): void;
704
+ /**
705
+ * Register a one-time event listener
706
+ */
707
+ once(event: string, handler: (...args: unknown[]) => void): void;
708
+ /**
709
+ * Remove a specific event listener or all listeners for an event
710
+ */
711
+ off(event: string, handler?: (...args: unknown[]) => void): void;
712
+ /**
713
+ * Register handlers for multiple events at once
714
+ */
715
+ onMultiple(events: string[], handler: (event: string, ...args: unknown[]) => void): void;
716
+ /**
717
+ * Register a handler that fires once when any of the specified events occur
718
+ */
719
+ onceAny(events: string[], handler: (event: string, ...args: unknown[]) => void): void;
720
+ /**
721
+ * Get the count of listeners for an event
722
+ */
723
+ listenerCount(event: string): number;
724
+ /**
725
+ * Get all registered event names
726
+ */
727
+ eventNames(): string[];
728
+ /**
729
+ * Remove all event listeners (auto-cleanup)
730
+ */
731
+ removeAllListeners(): void;
732
+ /**
733
+ * Track a listener internally
734
+ */
735
+ private addListener;
736
+ /**
737
+ * Remove a listener from internal tracking
738
+ */
739
+ private removeListener;
740
+ }
741
+
742
+ /**
743
+ * Honeydrop - Socket.IO Helper Library
744
+ * A lightweight, developer-friendly helper for Socket.IO applications
745
+ */
746
+
747
+ export { ConnectionMonitor, EventManager, Honeydrop, Logger, NamespacedEvents, OfflineQueue, ReconnectionHandler, RoomManager, createDebouncedEmit, createThrottledEmit, Honeydrop as default, emitMultiple, emitMultipleWithAck, emitWithAck, getConnectionInfo, isConnected, waitForAnyEvent, waitForEvent };
748
+ export type { ConnectionMonitorOptions, ConnectionQuality, EmitItem, EmitWithAckItem, HoneydropOptions, LogLevel, NamespaceDelimiter, NamespaceOptions, NamespacedEmitter, OfflineQueueOptions, QueuedEvent, ReconnectionOptions, ReconnectionStrategy, RoomEmitter, RoomManagerOptions };