@fluxstack/live 0.1.0 → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -144,6 +144,10 @@ interface LiveWSData {
144
144
  userId?: string;
145
145
  /** Auth context for the connection */
146
146
  authContext?: LiveAuthContext;
147
+ /** Rooms joined by this connection (for per-connection limits) */
148
+ rooms?: Set<string>;
149
+ /** Origin header from the WebSocket upgrade request (set by transport adapter) */
150
+ origin?: string;
147
151
  }
148
152
  /** @deprecated Use GenericWebSocket instead */
149
153
  type FluxStackWebSocket = GenericWebSocket;
@@ -233,6 +237,8 @@ declare function createTypedRoomEventBus<TRoomEvents extends Record<string, Reco
233
237
  };
234
238
  declare class RoomEventBus {
235
239
  private subscriptions;
240
+ /** Reverse index: componentId -> Set of subscription keys for O(1) unsubscribeAll */
241
+ private componentIndex;
236
242
  private getKey;
237
243
  on(roomType: string, roomId: string, event: string, componentId: string, handler: EventHandler): () => void;
238
244
  emit(roomType: string, roomId: string, event: string, data: any, excludeComponentId?: string): number;
@@ -246,31 +252,319 @@ declare class RoomEventBus {
246
252
  };
247
253
  }
248
254
 
255
+ /**
256
+ * Adapter for room state storage.
257
+ *
258
+ * All methods return Promises to support async backends (Redis, DB, etc.).
259
+ * The InMemoryRoomAdapter resolves immediately for zero-overhead in single-instance mode.
260
+ */
261
+ interface IRoomStorageAdapter {
262
+ /** Create or get a room. Returns current state and whether it was newly created. */
263
+ getOrCreateRoom(roomId: string, initialState?: any): Promise<{
264
+ state: any;
265
+ created: boolean;
266
+ }>;
267
+ /** Get the state of a room. Returns empty object if room doesn't exist. */
268
+ getState(roomId: string): Promise<any>;
269
+ /** Update room state (merge partial updates). */
270
+ updateState(roomId: string, updates: any): Promise<void>;
271
+ /** Check if a room exists. */
272
+ hasRoom(roomId: string): Promise<boolean>;
273
+ /** Delete a room. Returns true if the room existed. */
274
+ deleteRoom(roomId: string): Promise<boolean>;
275
+ /** Get storage statistics. */
276
+ getStats(): Promise<{
277
+ totalRooms: number;
278
+ rooms: Record<string, any>;
279
+ }>;
280
+ }
281
+ /**
282
+ * Adapter for cross-instance pub/sub (horizontal scaling).
283
+ *
284
+ * When running multiple server instances, this adapter propagates room events
285
+ * between instances. In single-instance mode (InMemoryRoomAdapter), all pub/sub
286
+ * operations are no-ops since events are already local.
287
+ */
288
+ interface IRoomPubSubAdapter {
289
+ /** Publish an event to all server instances subscribed to this room. */
290
+ publish(roomId: string, event: string, data: any): Promise<void>;
291
+ /** Subscribe to events for a room (from other server instances). */
292
+ subscribe(roomId: string, handler: (event: string, data: any) => void): Promise<() => void>;
293
+ /** Publish a membership change (join/leave) to other instances. */
294
+ publishMembership(roomId: string, action: 'join' | 'leave', componentId: string): Promise<void>;
295
+ /** Publish a state change to other instances. */
296
+ publishStateChange(roomId: string, updates: any): Promise<void>;
297
+ }
298
+
299
+ interface LiveRoomManagerInterface {
300
+ joinRoom<TState = any>(componentId: string, roomId: string, ws: any, initialState?: TState, options?: {
301
+ deepDiff?: boolean;
302
+ deepDiffDepth?: number;
303
+ serverOnlyState?: boolean;
304
+ }, joinContext?: {
305
+ userId?: string;
306
+ payload?: any;
307
+ }): {
308
+ state: TState;
309
+ rejected?: false;
310
+ } | {
311
+ rejected: true;
312
+ reason: string;
313
+ };
314
+ leaveRoom(componentId: string, roomId: string, leaveReason?: 'leave' | 'disconnect' | 'cleanup'): void;
315
+ cleanupComponent(componentId: string): void;
316
+ emitToRoom(roomId: string, event: string, data: any, excludeComponentId?: string): number;
317
+ setRoomState(roomId: string, updates: any, excludeComponentId?: string): void;
318
+ getRoomState<TState = any>(roomId: string): TState;
319
+ isInRoom(componentId: string, roomId: string): boolean;
320
+ getComponentRooms(componentId: string): string[];
321
+ getMemberCount?(roomId: string): number;
322
+ getRoomInstance?(roomId: string): LiveRoom<any, any, any> | undefined;
323
+ getStats(): any;
324
+ }
325
+ interface LiveComponentContext {
326
+ roomEvents: RoomEventBus;
327
+ roomManager: LiveRoomManagerInterface;
328
+ }
329
+ /**
330
+ * Set the global Live Component context.
331
+ * Called once by LiveServer.start() before any components are mounted.
332
+ */
333
+ declare function setLiveComponentContext(ctx: LiveComponentContext): void;
334
+ /**
335
+ * Get the global Live Component context.
336
+ * Throws if LiveServer.start() hasn't been called yet.
337
+ */
338
+ declare function getLiveComponentContext(): LiveComponentContext;
339
+
340
+ declare const BINARY_ROOM_EVENT = 2;
341
+ declare const BINARY_ROOM_STATE = 3;
342
+ interface RoomCodec {
343
+ encode(data: unknown): Uint8Array;
344
+ decode(buf: Uint8Array): unknown;
345
+ }
346
+ declare const msgpackCodec: RoomCodec;
347
+ declare const jsonCodec: RoomCodec;
348
+ type RoomCodecOption = 'msgpack' | 'json' | RoomCodec;
349
+ declare function resolveCodec(option?: RoomCodecOption): RoomCodec;
350
+ /**
351
+ * Build a binary room frame.
352
+ * Format: [frameType:u8][compIdLen:u8][compId:utf8][roomIdLen:u8][roomId:utf8][eventLen:u16BE][event:utf8][payload]
353
+ */
354
+ declare function buildRoomFrame(frameType: number, componentId: string, roomId: string, event: string, payload: Uint8Array): Uint8Array;
355
+ /**
356
+ * Build frame tail (roomId + event + payload) that is shared across all members.
357
+ * Per-member: prepend [frameType:u8][compIdLen:u8][compId:utf8].
358
+ */
359
+ declare function buildRoomFrameTail(roomId: string, event: string, payload: Uint8Array): Uint8Array;
360
+ /**
361
+ * Prepend per-member header to a shared tail.
362
+ * Header: [frameType:u8][compIdLen:u8][compId:utf8]
363
+ */
364
+ declare function prependMemberHeader(frameType: number, componentId: string, tail: Uint8Array): Uint8Array;
365
+ /**
366
+ * Parse a binary room frame header (client-side).
367
+ * Returns parsed fields and the payload offset.
368
+ */
369
+ declare function parseRoomFrame(buf: Uint8Array): {
370
+ frameType: number;
371
+ componentId: string;
372
+ roomId: string;
373
+ event: string;
374
+ payload: Uint8Array;
375
+ } | null;
376
+
377
+ interface RoomJoinContext {
378
+ componentId: string;
379
+ userId?: string;
380
+ payload?: any;
381
+ }
382
+ interface RoomLeaveContext {
383
+ componentId: string;
384
+ userId?: string;
385
+ reason: 'leave' | 'disconnect' | 'cleanup';
386
+ }
387
+ interface RoomEventContext {
388
+ componentId: string;
389
+ userId?: string;
390
+ }
391
+ interface LiveRoomOptions {
392
+ /** Enable deep diff for room state. Default: true */
393
+ deepDiff?: boolean;
394
+ /** Max recursion depth for deep diff. Default: 3 */
395
+ deepDiffDepth?: number;
396
+ /** Max number of members allowed. Undefined = unlimited */
397
+ maxMembers?: number;
398
+ /**
399
+ * Wire codec for room messages. Default: 'msgpack' (binary).
400
+ * - 'msgpack' — Built-in MessagePack encoder (zero deps, ~30% smaller, ~2-3x faster)
401
+ * - 'json' — Standard JSON (text-based, larger but human-readable)
402
+ * - Custom RoomCodec object with encode/decode methods
403
+ */
404
+ codec?: RoomCodecOption;
405
+ }
406
+ /**
407
+ * Base class for typed rooms with lifecycle hooks and public/private state.
408
+ *
409
+ * @typeParam TState - Public state synced to all connected clients
410
+ * @typeParam TMeta - Private server-only metadata (never broadcasted)
411
+ * @typeParam TEvents - Event map for typed emit/on
412
+ */
413
+ declare abstract class LiveRoom<TState extends Record<string, any> = Record<string, any>, TMeta extends Record<string, any> = Record<string, any>, TEvents extends Record<string, any> = Record<string, any>> {
414
+ /** Unique room type name. Used as prefix in compound room IDs (e.g. "chat:lobby"). */
415
+ static roomName: string;
416
+ /** Initial public state template. Cloned per room instance. */
417
+ static defaultState: Record<string, any>;
418
+ /** Initial private metadata template. Cloned per room instance. */
419
+ static defaultMeta: Record<string, any>;
420
+ /** Room-level options */
421
+ static $options?: LiveRoomOptions;
422
+ /** The unique room instance identifier (e.g. "chat:lobby") */
423
+ readonly id: string;
424
+ /** Public state — synced to all connected clients via setState(). */
425
+ state: TState;
426
+ /** Private metadata — NEVER leaves the server. Mutate directly. */
427
+ meta: TMeta;
428
+ /** @internal Type brand for client-side event inference.
429
+ * No runtime value. Usage: `$room<CounterRoom>('id').on(...)` */
430
+ readonly $events: TEvents;
431
+ /** @internal Reference to the room manager for broadcasting */
432
+ protected readonly _manager: LiveRoomManagerInterface;
433
+ constructor(id: string, manager: LiveRoomManagerInterface);
434
+ /**
435
+ * Update public state and broadcast changes to all room members.
436
+ * Uses deep diff by default — only changed fields are sent over the wire.
437
+ */
438
+ setState(updates: Partial<TState>): void;
439
+ /**
440
+ * Emit a typed event to all members in this room.
441
+ * @returns Number of members notified
442
+ */
443
+ emit<K extends keyof TEvents & string>(event: K, data: TEvents[K]): number;
444
+ /** Get current member count */
445
+ get memberCount(): number;
446
+ /**
447
+ * Called when a component attempts to join this room.
448
+ * Return false to reject the join.
449
+ */
450
+ onJoin(_ctx: RoomJoinContext): void | false | Promise<void | false>;
451
+ /**
452
+ * Called after a component leaves this room.
453
+ */
454
+ onLeave(_ctx: RoomLeaveContext): void | Promise<void>;
455
+ /**
456
+ * Called when an event is emitted to this room.
457
+ * Can intercept/validate events before broadcasting.
458
+ */
459
+ onEvent(_event: string, _data: any, _ctx: RoomEventContext): void | Promise<void>;
460
+ /**
461
+ * Called once when the room is first created (first member joins).
462
+ */
463
+ onCreate(): void | Promise<void>;
464
+ /**
465
+ * Called when the last member leaves and the room is about to be destroyed.
466
+ * Return false to keep the room alive (e.g., persist state).
467
+ */
468
+ onDestroy(): void | false | Promise<void | false>;
469
+ }
470
+ /** Extract the public state type from a LiveRoom subclass */
471
+ type InferRoomState<R> = R extends LiveRoom<infer S, any, any> ? S : Record<string, any>;
472
+ /** Extract the private meta type from a LiveRoom subclass */
473
+ type InferRoomMeta<R> = R extends LiveRoom<any, infer M, any> ? M : Record<string, any>;
474
+ /** Extract the events type from a LiveRoom subclass */
475
+ type InferRoomEvents<R> = R extends LiveRoom<any, any, infer E> ? E : Record<string, any>;
476
+ /** LiveRoom class constructor type */
477
+ type LiveRoomClass<R extends LiveRoom = LiveRoom> = {
478
+ new (id: string, manager: LiveRoomManagerInterface): R;
479
+ roomName: string;
480
+ defaultState: Record<string, any>;
481
+ defaultMeta: Record<string, any>;
482
+ $options?: LiveRoomOptions;
483
+ };
484
+
485
+ declare class RoomRegistry {
486
+ private rooms;
487
+ /**
488
+ * Register a LiveRoom subclass.
489
+ * @throws If the class doesn't define a static roomName
490
+ */
491
+ register(roomClass: LiveRoomClass): void;
492
+ /**
493
+ * Get a registered room class by name.
494
+ */
495
+ get(name: string): LiveRoomClass | undefined;
496
+ /**
497
+ * Check if a room class is registered.
498
+ */
499
+ has(name: string): boolean;
500
+ /**
501
+ * Resolve a compound room ID (e.g. "chat:lobby") to its registered class.
502
+ * Returns undefined if the prefix doesn't match any registered room.
503
+ */
504
+ resolveFromId(roomId: string): LiveRoomClass | undefined;
505
+ /**
506
+ * Get all registered room names.
507
+ */
508
+ getRegisteredNames(): string[];
509
+ /**
510
+ * Check if a value is a LiveRoom subclass.
511
+ */
512
+ static isLiveRoomClass(cls: unknown): cls is LiveRoomClass;
513
+ }
514
+
249
515
  declare class LiveRoomManager {
250
516
  private roomEvents;
517
+ private pubsub?;
251
518
  private rooms;
252
519
  private componentRooms;
253
- constructor(roomEvents: RoomEventBus);
520
+ /** Room registry for LiveRoom class lookup. Set by LiveServer. */
521
+ roomRegistry?: RoomRegistry;
522
+ /**
523
+ * @param roomEvents - Local server-side event bus
524
+ * @param pubsub - Optional cross-instance pub/sub adapter (e.g. Redis).
525
+ * When provided, room events/state/membership are propagated
526
+ * to other server instances in the background.
527
+ */
528
+ constructor(roomEvents: RoomEventBus, pubsub?: IRoomPubSubAdapter | undefined);
254
529
  /**
255
- * Component joins a room
530
+ * Component joins a room.
531
+ * @param options.deepDiff - Enable/disable deep diff for this room's state. Default: true
532
+ * @param joinContext - Optional context for LiveRoom lifecycle hooks (userId, payload)
256
533
  */
257
- joinRoom<TState = any>(componentId: string, roomId: string, ws: GenericWebSocket, initialState?: TState): {
534
+ joinRoom<TState = any>(componentId: string, roomId: string, ws: GenericWebSocket, initialState?: TState, options?: {
535
+ deepDiff?: boolean;
536
+ deepDiffDepth?: number;
537
+ serverOnlyState?: boolean;
538
+ }, joinContext?: {
539
+ userId?: string;
540
+ payload?: any;
541
+ }): {
258
542
  state: TState;
543
+ rejected?: false;
544
+ } | {
545
+ rejected: true;
546
+ reason: string;
259
547
  };
260
548
  /**
261
549
  * Component leaves a room
550
+ * @param leaveReason - Why the component is leaving. Default: 'leave'
262
551
  */
263
- leaveRoom(componentId: string, roomId: string): void;
552
+ leaveRoom(componentId: string, roomId: string, leaveReason?: 'leave' | 'disconnect' | 'cleanup'): void;
264
553
  /**
265
- * Component disconnects - leave all rooms
554
+ * Component disconnects - leave all rooms.
555
+ * Batches removals: calls onLeave hooks, removes member from all rooms,
556
+ * then sends leave notifications in bulk.
266
557
  */
267
558
  cleanupComponent(componentId: string): void;
268
559
  /**
269
- * Emit event to all members in a room
560
+ * Emit event to all members in a room.
561
+ * For LiveRoom-backed rooms, calls onEvent() hook before broadcasting.
270
562
  */
271
563
  emitToRoom(roomId: string, event: string, data: any, excludeComponentId?: string): number;
272
564
  /**
273
- * Update room state
565
+ * Update room state.
566
+ * When deepDiff is enabled (default), deep-diffs plain objects to send only changed fields.
567
+ * When disabled, uses shallow diff (reference equality) like classic behavior.
274
568
  */
275
569
  setRoomState(roomId: string, updates: any, excludeComponentId?: string): void;
276
570
  /**
@@ -278,17 +572,36 @@ declare class LiveRoomManager {
278
572
  */
279
573
  getRoomState<TState = any>(roomId: string): TState;
280
574
  /**
281
- * Broadcast to all members in a room
575
+ * Broadcast to all members in a room.
576
+ *
577
+ * When the room has a binary codec (LiveRoom-backed), builds a binary frame
578
+ * once (encode payload + frame tail), then prepends per-member componentId header.
579
+ *
580
+ * When no codec (legacy rooms), uses JSON with serialize-once optimization:
581
+ * builds the JSON string template once, then inserts each member's componentId.
282
582
  */
283
583
  private broadcastToRoom;
284
584
  /**
285
585
  * Check if component is in a room
286
586
  */
287
587
  isInRoom(componentId: string, roomId: string): boolean;
588
+ /**
589
+ * Check if room state is server-only (no client writes)
590
+ */
591
+ isServerOnlyState(roomId: string): boolean;
288
592
  /**
289
593
  * Get rooms for a component
290
594
  */
291
595
  getComponentRooms(componentId: string): string[];
596
+ /**
597
+ * Get member count for a room
598
+ */
599
+ getMemberCount(roomId: string): number;
600
+ /**
601
+ * Get the LiveRoom instance for a room (if backed by a typed room class).
602
+ * Used by ComponentRoomProxy to expose custom methods.
603
+ */
604
+ getRoomInstance(roomId: string): LiveRoom<any, any, any> | undefined;
292
605
  /**
293
606
  * Get statistics
294
607
  */
@@ -302,80 +615,6 @@ declare class LiveRoomManager {
302
615
  };
303
616
  }
304
617
 
305
- type DebugEventType = 'COMPONENT_MOUNT' | 'COMPONENT_UNMOUNT' | 'COMPONENT_REHYDRATE' | 'STATE_CHANGE' | 'ACTION_CALL' | 'ACTION_RESULT' | 'ACTION_ERROR' | 'ROOM_JOIN' | 'ROOM_LEAVE' | 'ROOM_EMIT' | 'ROOM_EVENT_RECEIVED' | 'WS_CONNECT' | 'WS_DISCONNECT' | 'ERROR' | 'LOG';
306
- interface DebugEvent {
307
- id: string;
308
- timestamp: number;
309
- type: DebugEventType;
310
- componentId: string | null;
311
- componentName: string | null;
312
- data: Record<string, unknown>;
313
- }
314
- interface ComponentSnapshot {
315
- componentId: string;
316
- componentName: string;
317
- /** Developer-defined label for easier identification in the debugger */
318
- debugLabel?: string;
319
- state: Record<string, unknown>;
320
- rooms: string[];
321
- mountedAt: number;
322
- lastActivity: number;
323
- actionCount: number;
324
- stateChangeCount: number;
325
- errorCount: number;
326
- }
327
- interface DebugSnapshot {
328
- components: ComponentSnapshot[];
329
- connections: number;
330
- uptime: number;
331
- totalEvents: number;
332
- }
333
- interface DebugWsMessage {
334
- type: 'DEBUG_EVENT' | 'DEBUG_SNAPSHOT' | 'DEBUG_WELCOME' | 'DEBUG_DISABLED';
335
- event?: DebugEvent;
336
- snapshot?: DebugSnapshot;
337
- enabled?: boolean;
338
- timestamp: number;
339
- }
340
- declare class LiveDebugger {
341
- private events;
342
- private componentSnapshots;
343
- private debugClients;
344
- private _enabled;
345
- private startTime;
346
- private eventCounter;
347
- constructor(enabled?: boolean);
348
- get enabled(): boolean;
349
- set enabled(value: boolean);
350
- emit(type: DebugEventType | string, componentId: string | null, componentName: string | null, data?: Record<string, unknown>): void;
351
- trackComponentMount(componentId: string, componentName: string, initialState: Record<string, unknown>, room?: string, debugLabel?: string): void;
352
- trackComponentUnmount(componentId: string): void;
353
- trackStateChange(componentId: string, delta: Record<string, unknown>, fullState: Record<string, unknown>, source?: 'proxy' | 'setState' | 'rehydrate'): void;
354
- trackActionCall(componentId: string, action: string, payload: unknown): void;
355
- trackActionResult(componentId: string, action: string, result: unknown, duration: number): void;
356
- trackActionError(componentId: string, action: string, error: string, duration: number): void;
357
- trackRoomJoin(componentId: string, roomId: string): void;
358
- trackRoomLeave(componentId: string, roomId: string): void;
359
- trackRoomEmit(componentId: string, roomId: string, event: string, data: unknown): void;
360
- trackConnection(connectionId: string): void;
361
- trackDisconnection(connectionId: string, componentCount: number): void;
362
- trackError(componentId: string | null, error: string, context?: Record<string, unknown>): void;
363
- registerDebugClient(ws: GenericWebSocket): void;
364
- unregisterDebugClient(ws: GenericWebSocket): void;
365
- getSnapshot(): DebugSnapshot;
366
- getComponentState(componentId: string): ComponentSnapshot | null;
367
- getEvents(filter?: {
368
- componentId?: string;
369
- type?: DebugEventType;
370
- limit?: number;
371
- }): DebugEvent[];
372
- clearEvents(): void;
373
- private broadcastEvent;
374
- private sanitizeData;
375
- private sanitizeState;
376
- private updateSnapshot;
377
- }
378
-
379
618
  declare class LiveAuthManager {
380
619
  private providers;
381
620
  private defaultProviderName?;
@@ -446,33 +685,49 @@ interface StateSignatureConfig {
446
685
  compressionEnabled?: boolean;
447
686
  /** Enable encryption */
448
687
  encryptionEnabled?: boolean;
449
- /** Enable anti-replay nonces */
688
+ /** Enable anti-replay nonces (hybrid: stateless HMAC + replay detection) */
450
689
  nonceEnabled?: boolean;
451
- /** Maximum state age in ms */
690
+ /** Maximum state age in ms. Default: 1800000 (30 minutes) */
452
691
  maxStateAge?: number;
453
692
  /** Enable state backups */
454
693
  backupEnabled?: boolean;
455
694
  /** Max state backups to keep */
456
695
  maxBackups?: number;
696
+ /** Nonce TTL in ms. Nonces older than this are rejected. Default: 10000 (10 seconds) */
697
+ nonceTTL?: number;
457
698
  }
458
699
  declare class StateSignatureManager {
459
700
  private secret;
460
701
  private previousSecrets;
461
702
  private rotationTimer?;
462
- private usedNonces;
463
- private nonceCleanupTimer?;
464
703
  private stateBackups;
465
704
  private config;
705
+ private encryptionSalt;
706
+ private cachedEncryptionKey;
707
+ /** Replay detection: nonce → timestamp when it was first seen. Cleaned every 60s. */
708
+ private usedNonces;
709
+ private nonceCleanupTimer?;
466
710
  constructor(config?: StateSignatureConfig);
711
+ /**
712
+ * Generate a hybrid nonce: `timestamp:random:HMAC(timestamp:random, secret)`
713
+ * Self-validating via HMAC, unique via random bytes, replay-tracked via Map.
714
+ */
715
+ private generateNonce;
716
+ /**
717
+ * Validate a hybrid nonce: check format, HMAC, and TTL.
718
+ */
719
+ private validateNonce;
467
720
  signState(componentId: string, state: Record<string, unknown>, version: number, options?: {
468
721
  compress?: boolean;
469
722
  backup?: boolean;
470
- }): Promise<SignedState>;
471
- validateState(signedState: SignedState): Promise<{
723
+ }): SignedState;
724
+ validateState(signedState: SignedState, options?: {
725
+ skipNonce?: boolean;
726
+ }): {
472
727
  valid: boolean;
473
728
  error?: string;
474
- }>;
475
- extractData(signedState: SignedState): Promise<Record<string, unknown>>;
729
+ };
730
+ extractData(signedState: SignedState): Record<string, unknown>;
476
731
  getBackups(componentId: string): SignedState[];
477
732
  getLatestBackup(componentId: string): SignedState | null;
478
733
  private backupState;
@@ -481,6 +736,7 @@ declare class StateSignatureManager {
481
736
  private timingSafeEqual;
482
737
  private deriveEncryptionKey;
483
738
  private setupKeyRotation;
739
+ /** Remove nonces older than nonceTTL + 10s from the replay detection map. */
484
740
  private cleanupNonces;
485
741
  shutdown(): void;
486
742
  }
@@ -847,6 +1103,8 @@ declare class WebSocketConnectionManager extends EventEmitter {
847
1103
  private connections;
848
1104
  private connectionMetrics;
849
1105
  private connectionPools;
1106
+ /** Reverse index: connectionId -> Set of poolIds for O(1) cleanup */
1107
+ private connectionPoolIndex;
850
1108
  private messageQueues;
851
1109
  private healthCheckTimer?;
852
1110
  private heartbeatTimer?;
@@ -873,45 +1131,19 @@ declare class WebSocketConnectionManager extends EventEmitter {
873
1131
  shutdown(): void;
874
1132
  }
875
1133
 
876
- interface LiveRoomManagerInterface {
877
- joinRoom<TState = any>(componentId: string, roomId: string, ws: any, initialState?: TState): {
878
- state: TState;
879
- };
880
- leaveRoom(componentId: string, roomId: string): void;
881
- cleanupComponent(componentId: string): void;
882
- emitToRoom(roomId: string, event: string, data: any, excludeComponentId?: string): number;
883
- setRoomState(roomId: string, updates: any, excludeComponentId?: string): void;
884
- getRoomState<TState = any>(roomId: string): TState;
885
- isInRoom(componentId: string, roomId: string): boolean;
886
- getComponentRooms(componentId: string): string[];
887
- getStats(): any;
888
- }
889
- interface LiveDebuggerInterface {
890
- enabled: boolean;
891
- trackStateChange(componentId: string, delta: Record<string, unknown>, fullState: Record<string, unknown>, source?: string): void;
892
- trackActionCall(componentId: string, action: string, payload: unknown): void;
893
- trackActionResult(componentId: string, action: string, result: unknown, duration: number): void;
894
- trackActionError(componentId: string, action: string, error: string, duration: number): void;
895
- trackRoomEmit(componentId: string, roomId: string, event: string, data: unknown): void;
896
- }
897
- interface LiveComponentContext {
898
- roomEvents: RoomEventBus;
899
- roomManager: LiveRoomManagerInterface;
900
- debugger?: LiveDebuggerInterface;
901
- }
902
- /**
903
- * Set the global Live Component context.
904
- * Called once by LiveServer.start() before any components are mounted.
905
- */
906
- declare function setLiveComponentContext(ctx: LiveComponentContext): void;
907
- /**
908
- * Get the global Live Component context.
909
- * Throws if LiveServer.start() hasn't been called yet.
910
- */
911
- declare function getLiveComponentContext(): LiveComponentContext;
912
-
913
- /** @internal Symbol key for singleton emit override */
1134
+ /** Symbol key for singleton emit override */
914
1135
  declare const EMIT_OVERRIDE_KEY: unique symbol;
1136
+
1137
+ interface ComponentOptions {
1138
+ /** Enable deep diff for plain objects in setState(). Default: false */
1139
+ deepDiff?: boolean;
1140
+ /** Enable deep diff for room state updates. Default: true */
1141
+ roomDeepDiff?: boolean;
1142
+ /** Max recursion depth for deep diff (component + room). Default: 3 */
1143
+ deepDiffDepth?: number;
1144
+ /** When true, room state can only be set from server-side code. Client ROOM_STATE_SET is rejected. Default: false */
1145
+ serverOnlyRoomState?: boolean;
1146
+ }
915
1147
  declare abstract class LiveComponent<TState = ComponentState, TPrivate extends Record<string, any> = Record<string, any>> {
916
1148
  /** Component name for registry lookup - must be defined in subclasses */
917
1149
  static componentName: string;
@@ -933,6 +1165,35 @@ declare abstract class LiveComponent<TState = ComponentState, TPrivate extends R
933
1165
  * Per-action auth configuration.
934
1166
  */
935
1167
  static actionAuth?: LiveActionAuthMap;
1168
+ /**
1169
+ * Zod schemas for action payload validation.
1170
+ * When defined, payloads are validated before the action method is called.
1171
+ *
1172
+ * @example
1173
+ * static actionSchemas = {
1174
+ * sendMessage: z.object({ text: z.string().max(500) }),
1175
+ * updatePosition: z.object({ x: z.number(), y: z.number() }),
1176
+ * }
1177
+ */
1178
+ static actionSchemas?: Record<string, {
1179
+ safeParse: (data: unknown) => {
1180
+ success: boolean;
1181
+ error?: any;
1182
+ data?: any;
1183
+ };
1184
+ }>;
1185
+ /**
1186
+ * Rate limit for action execution.
1187
+ * Prevents clients from spamming expensive operations.
1188
+ *
1189
+ * @example
1190
+ * static actionRateLimit = { maxCalls: 10, windowMs: 1000, perAction: true }
1191
+ */
1192
+ static actionRateLimit?: {
1193
+ maxCalls: number;
1194
+ windowMs: number;
1195
+ perAction?: boolean;
1196
+ };
936
1197
  /**
937
1198
  * Data that survives HMR reloads.
938
1199
  */
@@ -942,8 +1203,14 @@ declare abstract class LiveComponent<TState = ComponentState, TPrivate extends R
942
1203
  * All clients share the same state.
943
1204
  */
944
1205
  static singleton?: boolean;
1206
+ /**
1207
+ * Component behavior options.
1208
+ *
1209
+ * @example
1210
+ * static $options = { deepDiff: true }
1211
+ */
1212
+ static $options?: ComponentOptions;
945
1213
  readonly id: string;
946
- private _state;
947
1214
  state: TState;
948
1215
  protected ws: GenericWebSocket;
949
1216
  room?: string;
@@ -951,27 +1218,53 @@ declare abstract class LiveComponent<TState = ComponentState, TPrivate extends R
951
1218
  broadcastToRoom: (message: BroadcastMessage) => void;
952
1219
  private _privateState;
953
1220
  private _authContext;
954
- private roomEventUnsubscribers;
955
- private joinedRooms;
1221
+ private _authContextSet;
956
1222
  protected roomType: string;
957
- private roomHandles;
958
- private _inStateChange;
959
1223
  [EMIT_OVERRIDE_KEY]: ((type: string, payload: any) => void) | null;
1224
+ private _stateManager;
1225
+ private _messaging;
1226
+ private _actionSecurity;
1227
+ private _roomProxyManager;
1228
+ static publicActions?: readonly string[];
960
1229
  constructor(initialState: Partial<TState>, ws: GenericWebSocket, options?: {
961
1230
  room?: string;
962
1231
  userId?: string;
963
1232
  });
964
- private createDirectStateAccessors;
965
- private createStateProxy;
966
1233
  get $private(): TPrivate;
967
- get $room(): ServerRoomProxy;
968
1234
  /**
969
- * List of room IDs this component is participating in
1235
+ * Unified room accessor.
1236
+ *
1237
+ * Usage:
1238
+ * - `this.$room` — default room handle (legacy)
1239
+ * - `this.$room('roomId')` — untyped room handle (legacy)
1240
+ * - `this.$room(ChatRoom, 'lobby')` — typed handle with custom methods
1241
+ */
1242
+ get $room(): ServerRoomProxy & {
1243
+ <R extends LiveRoom<any, any, any>>(roomClass: LiveRoomClass<R>, instanceId: string): R & {
1244
+ readonly id: string;
1245
+ join: (payload?: any) => {
1246
+ rejected?: false;
1247
+ } | {
1248
+ rejected: true;
1249
+ reason: string;
1250
+ };
1251
+ leave: () => void;
1252
+ emit: R['emit'];
1253
+ on: <K extends string>(event: K, handler: (data: any) => void) => () => void;
1254
+ setState: (updates: Partial<R['state']>) => void;
1255
+ readonly memberCount: number;
1256
+ };
1257
+ };
1258
+ /**
1259
+ * List of room IDs this component is participating in.
1260
+ * Cached — invalidated on join/leave.
970
1261
  */
971
1262
  get $rooms(): string[];
972
1263
  get $auth(): LiveAuthContext;
973
- /** @internal */
1264
+ /** @internal - Immutable after first set to prevent privilege escalation */
974
1265
  setAuthContext(context: LiveAuthContext): void;
1266
+ /** @internal - Reset auth context (for registry use in reconnection) */
1267
+ _resetAuthContext(): void;
975
1268
  get $persistent(): Record<string, any>;
976
1269
  protected onConnect(): void;
977
1270
  protected onMount(): void | Promise<void>;
@@ -985,29 +1278,117 @@ declare abstract class LiveComponent<TState = ComponentState, TPrivate extends R
985
1278
  protected onClientJoin(connectionId: string, connectionCount: number): void;
986
1279
  protected onClientLeave(connectionId: string, connectionCount: number): void;
987
1280
  setState(updates: Partial<TState> | ((prev: TState) => Partial<TState>)): void;
1281
+ /**
1282
+ * Send a binary-encoded state delta directly over WebSocket.
1283
+ * Updates internal state (same as setState) then sends the encoder's output
1284
+ * as a binary frame: [0x01][idLen:u8][id_bytes:utf8][payload_bytes].
1285
+ * Bypasses the JSON batcher — ideal for high-frequency updates.
1286
+ */
1287
+ sendBinaryDelta(delta: Partial<TState>, encoder: (delta: Partial<TState>) => Uint8Array): void;
988
1288
  setValue<K extends keyof TState>(payload: {
989
1289
  key: K;
990
1290
  value: TState[K];
991
- }): Promise<{
1291
+ }): {
992
1292
  success: true;
993
1293
  key: K;
994
1294
  value: TState[K];
995
- }>;
996
- static publicActions?: readonly string[];
997
- private static readonly BLOCKED_ACTIONS;
1295
+ };
998
1296
  executeAction(action: string, payload: any): Promise<any>;
999
1297
  protected emit(type: string, payload: any): void;
1000
1298
  protected broadcast(type: string, payload: any, excludeCurrentUser?: boolean): void;
1001
1299
  protected emitRoomEvent(event: string, data: any, notifySelf?: boolean): number;
1002
1300
  protected onRoomEvent<T = any>(event: string, handler: (data: T) => void): void;
1003
1301
  protected emitRoomEventWithState(event: string, data: any, stateUpdates: Partial<TState>): number;
1004
- protected subscribeToRoom(roomId: string): Promise<void>;
1005
- protected unsubscribeFromRoom(): Promise<void>;
1302
+ protected subscribeToRoom(roomId: string): void;
1303
+ protected unsubscribeFromRoom(): void;
1006
1304
  private generateId;
1007
1305
  destroy(): void;
1008
1306
  getSerializableState(): TState;
1009
1307
  }
1010
1308
 
1309
+ /**
1310
+ * Adapter for cross-instance component synchronization.
1311
+ *
1312
+ * In single-instance mode, no cluster adapter is needed.
1313
+ * For horizontal scaling, provide a RedisClusterAdapter (or custom implementation).
1314
+ */
1315
+ interface IClusterAdapter {
1316
+ /** Unique identifier for this server instance. */
1317
+ readonly instanceId: string;
1318
+ /** Save component state to the shared store. */
1319
+ saveState(componentId: string, componentName: string, state: any): Promise<void>;
1320
+ /** Load component state from the shared store. */
1321
+ loadState(componentId: string): Promise<ClusterComponentState | null>;
1322
+ /** Remove component state from the shared store. */
1323
+ deleteState(componentId: string): Promise<void>;
1324
+ /** Publish a state delta to all server instances. */
1325
+ publishDelta(componentId: string, componentName: string, delta: any): Promise<void>;
1326
+ /** Register handler for incoming state deltas from other instances. */
1327
+ onDelta(handler: ClusterDeltaHandler): void;
1328
+ /** Attempt to claim ownership of a singleton (atomic).
1329
+ * Returns { claimed: true, recoveredState? } on success, { claimed: false } otherwise.
1330
+ * When claiming after a failover, recoveredState contains the previous owner's last state. */
1331
+ claimSingleton(componentName: string, componentId: string): Promise<ClusterSingletonClaim>;
1332
+ /** Get the current owner of a singleton. Returns null if not claimed. */
1333
+ getSingletonOwner(componentName: string): Promise<ClusterSingletonOwner | null>;
1334
+ /** Release ownership of a singleton (when last client disconnects). */
1335
+ releaseSingleton(componentName: string): Promise<void>;
1336
+ /** Verify this instance still owns a singleton (split-brain protection). */
1337
+ verifySingletonOwnership(componentName: string): Promise<boolean>;
1338
+ /** Register callback for when this instance loses ownership of a singleton (detected during heartbeat). */
1339
+ onOwnershipLost(handler: (componentName: string) => void): void;
1340
+ /** Save singleton state keyed by componentName (survives owner crash + claim expiry). */
1341
+ saveSingletonState(componentName: string, state: any): Promise<void>;
1342
+ /** Load the last known singleton state by componentName (for failover recovery). */
1343
+ loadSingletonState(componentName: string): Promise<any | null>;
1344
+ /** Forward an action to the owner server instance. Returns the action result. */
1345
+ forwardAction(request: ClusterActionRequest): Promise<ClusterActionResponse>;
1346
+ /** Register handler for incoming forwarded actions from other instances. */
1347
+ onActionForward(handler: (req: ClusterActionRequest) => Promise<ClusterActionResponse>): void;
1348
+ /** Start the adapter (subscribe to channels, start heartbeats, etc.). */
1349
+ start(): Promise<void>;
1350
+ /** Graceful shutdown (unsubscribe, clear intervals, disconnect). */
1351
+ shutdown(): Promise<void>;
1352
+ }
1353
+ /** State stored in the shared store for a component. */
1354
+ interface ClusterComponentState {
1355
+ componentName: string;
1356
+ state: any;
1357
+ instanceId: string;
1358
+ updatedAt: number;
1359
+ }
1360
+ /** Information about the owner of a singleton. */
1361
+ interface ClusterSingletonOwner {
1362
+ instanceId: string;
1363
+ componentId: string;
1364
+ }
1365
+ /** Request to forward an action to another server instance. */
1366
+ interface ClusterActionRequest {
1367
+ sourceInstanceId: string;
1368
+ targetInstanceId: string;
1369
+ componentId: string;
1370
+ componentName: string;
1371
+ action: string;
1372
+ payload: any;
1373
+ requestId: string;
1374
+ }
1375
+ /** Result of a singleton claim attempt. */
1376
+ interface ClusterSingletonClaim {
1377
+ /** Whether the claim was successful. */
1378
+ claimed: boolean;
1379
+ /** If claimed and previous state exists (failover recovery), the recovered state. */
1380
+ recoveredState?: any;
1381
+ }
1382
+ /** Response from a forwarded action. */
1383
+ interface ClusterActionResponse {
1384
+ success: boolean;
1385
+ result?: any;
1386
+ error?: string;
1387
+ requestId: string;
1388
+ }
1389
+ /** Handler for incoming state deltas from other instances. */
1390
+ type ClusterDeltaHandler = (componentId: string, componentName: string, delta: any, sourceInstanceId: string) => void;
1391
+
1011
1392
  interface ComponentMetadata {
1012
1393
  id: string;
1013
1394
  name: string;
@@ -1038,9 +1419,9 @@ interface StateMigration {
1038
1419
  }
1039
1420
  interface ComponentRegistryDeps {
1040
1421
  authManager: LiveAuthManager;
1041
- debugger: LiveDebugger;
1042
1422
  stateSignature: StateSignatureManager;
1043
1423
  performanceMonitor: PerformanceMonitor;
1424
+ cluster?: IClusterAdapter;
1044
1425
  }
1045
1426
  declare class ComponentRegistry {
1046
1427
  private components;
@@ -1051,11 +1432,14 @@ declare class ComponentRegistry {
1051
1432
  private autoDiscoveredComponents;
1052
1433
  private healthCheckInterval?;
1053
1434
  private singletons;
1435
+ private remoteSingletons;
1436
+ private cluster?;
1054
1437
  private authManager;
1055
- private debugger;
1056
1438
  private stateSignature;
1057
1439
  private performanceMonitor;
1058
1440
  constructor(deps: ComponentRegistryDeps);
1441
+ /** Set up handlers for incoming cluster messages (deltas, forwarded actions). */
1442
+ private setupClusterHandlers;
1059
1443
  private setupHealthMonitoring;
1060
1444
  registerComponent<TState>(definition: ComponentDefinition<TState>): void;
1061
1445
  registerComponentClass(name: string, componentClass: new (initialState: any, ws: GenericWebSocket, options?: {
@@ -1085,8 +1469,10 @@ declare class ComponentRegistry {
1085
1469
  private ensureWsData;
1086
1470
  private isSingletonComponent;
1087
1471
  private removeSingletonConnection;
1088
- unmountComponent(componentId: string, ws?: GenericWebSocket): Promise<void>;
1472
+ unmountComponent(componentId: string, ws?: GenericWebSocket): void;
1089
1473
  private getSingletonName;
1474
+ /** Find a remote singleton entry by componentId. */
1475
+ private findRemoteSingleton;
1090
1476
  executeAction(componentId: string, action: string, payload: any): Promise<any>;
1091
1477
  updateProperty(componentId: string, property: string, value: any): void;
1092
1478
  subscribeToRoom(componentId: string, roomId: string): void;
@@ -1110,6 +1496,13 @@ declare class ComponentRegistry {
1110
1496
  connections: number;
1111
1497
  };
1112
1498
  };
1499
+ remoteSingletons: {
1500
+ [k: string]: {
1501
+ componentId: string;
1502
+ ownerInstanceId: string;
1503
+ connections: number;
1504
+ };
1505
+ };
1113
1506
  roomDetails: {
1114
1507
  [k: string]: number;
1115
1508
  };
@@ -1176,11 +1569,25 @@ interface LiveServerOptions {
1176
1569
  componentsPath?: string;
1177
1570
  /** HTTP monitoring routes prefix. Set to false to disable. Defaults to '/api/live' */
1178
1571
  httpPrefix?: string | false;
1572
+ /** Allowed origins for WebSocket connections (CSRF protection).
1573
+ * When set, connections from unlisted origins are rejected.
1574
+ * Example: ['https://myapp.com', 'http://localhost:3000'] */
1575
+ allowedOrigins?: string[];
1576
+ /** Optional cross-instance pub/sub adapter for horizontal scaling (e.g. Redis).
1577
+ * When provided, room events, state changes, and membership are propagated
1578
+ * across server instances. Without this, rooms are local to the current instance. */
1579
+ roomPubSub?: IRoomPubSubAdapter;
1580
+ /** Optional cluster adapter for cross-instance component synchronization.
1581
+ * When provided, singleton components are coordinated across instances,
1582
+ * component state is mirrored to a shared store (Redis), and actions on
1583
+ * remote singletons are forwarded to the owner instance. */
1584
+ cluster?: IClusterAdapter;
1585
+ /** LiveRoom classes to register. These define typed rooms with lifecycle hooks. */
1586
+ rooms?: LiveRoomClass[];
1179
1587
  }
1180
1588
  declare class LiveServer {
1181
1589
  readonly roomEvents: RoomEventBus;
1182
1590
  readonly roomManager: LiveRoomManager;
1183
- readonly debugger: LiveDebugger;
1184
1591
  readonly authManager: LiveAuthManager;
1185
1592
  readonly stateSignature: StateSignatureManager;
1186
1593
  readonly performanceMonitor: PerformanceMonitor;
@@ -1188,6 +1595,7 @@ declare class LiveServer {
1188
1595
  readonly connectionManager: WebSocketConnectionManager;
1189
1596
  readonly registry: ComponentRegistry;
1190
1597
  readonly rateLimiter: RateLimiterRegistry;
1598
+ readonly roomRegistry: RoomRegistry;
1191
1599
  private transport;
1192
1600
  private options;
1193
1601
  constructor(options: LiveServerOptions);
@@ -1195,6 +1603,11 @@ declare class LiveServer {
1195
1603
  * Register an auth provider.
1196
1604
  */
1197
1605
  useAuth(provider: LiveAuthProvider): this;
1606
+ /**
1607
+ * Register a LiveRoom class.
1608
+ * Can be called before start() to register room types dynamically.
1609
+ */
1610
+ useRoom(roomClass: LiveRoomClass): this;
1198
1611
  /**
1199
1612
  * Start the LiveServer: register WS + HTTP handlers on the transport.
1200
1613
  */
@@ -1211,6 +1624,32 @@ declare class LiveServer {
1211
1624
  private buildHttpRoutes;
1212
1625
  }
1213
1626
 
1627
+ interface PendingMessage {
1628
+ type: string;
1629
+ componentId: string;
1630
+ payload: any;
1631
+ timestamp: number;
1632
+ userId?: string;
1633
+ room?: string;
1634
+ [key: string]: any;
1635
+ }
1636
+ /**
1637
+ * Queue a message to be sent on the next microtask flush.
1638
+ * Messages are batched per-WS and sent as a JSON array.
1639
+ */
1640
+ declare function queueWsMessage(ws: GenericWebSocket, message: PendingMessage): void;
1641
+ /**
1642
+ * Send a binary message immediately (bypass batching).
1643
+ * Binary frames are never batched — they are self-framing.
1644
+ */
1645
+ declare function sendBinaryImmediate(ws: GenericWebSocket, data: Uint8Array): void;
1646
+ /**
1647
+ * Send a message immediately (bypass batching).
1648
+ * Used for ACTION_RESPONSE and other request-response patterns
1649
+ * where the client is awaiting an immediate response.
1650
+ */
1651
+ declare function sendImmediate(ws: GenericWebSocket, data: string): void;
1652
+
1214
1653
  /**
1215
1654
  * Encode a binary chunk message for transmission.
1216
1655
  * @param header - JSON metadata about the chunk
@@ -1314,6 +1753,26 @@ declare class RoomStateManager {
1314
1753
  };
1315
1754
  }
1316
1755
 
1756
+ declare class InMemoryRoomAdapter implements IRoomStorageAdapter, IRoomPubSubAdapter {
1757
+ private rooms;
1758
+ getOrCreateRoom(roomId: string, initialState?: any): Promise<{
1759
+ state: any;
1760
+ created: boolean;
1761
+ }>;
1762
+ getState(roomId: string): Promise<any>;
1763
+ updateState(roomId: string, updates: any): Promise<void>;
1764
+ hasRoom(roomId: string): Promise<boolean>;
1765
+ deleteRoom(roomId: string): Promise<boolean>;
1766
+ getStats(): Promise<{
1767
+ totalRooms: number;
1768
+ rooms: Record<string, any>;
1769
+ }>;
1770
+ publish(_roomId: string, _event: string, _data: any): Promise<void>;
1771
+ subscribe(_roomId: string, _handler: (event: string, data: any) => void): Promise<() => void>;
1772
+ publishMembership(_roomId: string, _action: 'join' | 'leave', _componentId: string): Promise<void>;
1773
+ publishStateChange(_roomId: string, _updates: any): Promise<void>;
1774
+ }
1775
+
1317
1776
  type LiveLogCategory = 'lifecycle' | 'messages' | 'state' | 'performance' | 'rooms' | 'websocket';
1318
1777
  type LiveLogConfig = boolean | readonly LiveLogCategory[];
1319
1778
  /**
@@ -1326,12 +1785,10 @@ declare function registerComponentLogging(componentId: string, config: LiveLogCo
1326
1785
  declare function unregisterComponentLogging(componentId: string): void;
1327
1786
  /**
1328
1787
  * Log a message gated by the component's logging config.
1329
- * Always forwarded to the Live Debugger when active.
1330
1788
  */
1331
1789
  declare function liveLog(category: LiveLogCategory, componentId: string | null, message: string, ...args: unknown[]): void;
1332
1790
  /**
1333
1791
  * Warn-level log gated by config.
1334
- * Always forwarded to the Live Debugger when active.
1335
1792
  */
1336
1793
  declare function liveWarn(category: LiveLogCategory, componentId: string | null, message: string, ...args: unknown[]): void;
1337
1794
 
@@ -1397,4 +1854,4 @@ interface UseTypedLiveComponentReturn<T extends LiveComponent<any>> {
1397
1854
  };
1398
1855
  }
1399
1856
 
1400
- export { ANONYMOUS_CONTEXT, type ActionNames, type ActionPayload, type ActionReturn, type ActiveUpload, AnonymousContext, AuthenticatedContext, type BinaryChunkHeader, type BroadcastMessage, type ComponentDefinition, type ComponentMetadata, type ComponentMetrics, type ComponentPerformanceMetrics, ComponentRegistry, type ComponentSnapshot, type ComponentState, type ConnectionConfig, type ConnectionHealth, type ConnectionMetrics, ConnectionRateLimiter, DEFAULT_CHUNK_SIZE, DEFAULT_WS_PATH, type DebugEvent, type DebugEventType, type DebugSnapshot, type DebugWsMessage, type EventHandler, type ExtractActions, type FileChunkData, type FileUploadChunkMessage, type FileUploadCompleteMessage, type FileUploadCompleteResponse, type FileUploadConfig, FileUploadManager, type FileUploadProgressResponse, type FileUploadStartMessage, type FluxStackWSData, type FluxStackWebSocket, type GenericWebSocket, type HttpRequest, type HttpResponse, type HttpRouteDefinition, type HybridComponentOptions, type HybridState, type InferComponentState, type InferPrivateState, type LiveActionAuth, type LiveActionAuthMap, type LiveAuthContext, type LiveAuthCredentials, LiveAuthManager, type LiveAuthProvider, type LiveAuthResult, type LiveAuthUser, LiveComponent, type LiveComponentAuth, type LiveComponentContext, type LiveComponentInstance, LiveDebugger, type LiveLogCategory, type LiveLogConfig, type LiveMessage, LiveRoomManager, LiveServer, type LiveServerOptions, type LiveTransport, type LiveWSData, PROTOCOL_VERSION, type PerformanceAlert, type PerformanceConfig, PerformanceMonitor, RateLimiterRegistry, RoomEventBus, type RoomInfo, type RoomMessage, type RoomStateData, RoomStateManager, type RoomSubscription, type ServerRoomHandle, type ServerRoomProxy, type SignedState, type StateMigration, type StateSignatureConfig, StateSignatureManager, type TypedCall, type TypedCallAndWait, type TypedSetValue, type UseTypedLiveComponentReturn, type WebSocketConfig, WebSocketConnectionManager, type WebSocketMessage, type WebSocketResponse, createTypedRoomEventBus, createTypedRoomState, decodeBinaryChunk, encodeBinaryChunk, getLiveComponentContext, liveLog, liveWarn, registerComponentLogging, setLiveComponentContext, unregisterComponentLogging };
1857
+ export { ANONYMOUS_CONTEXT, type ActionNames, type ActionPayload, type ActionReturn, type ActiveUpload, AnonymousContext, AuthenticatedContext, BINARY_ROOM_EVENT, BINARY_ROOM_STATE, type BinaryChunkHeader, type BroadcastMessage, type ClusterActionRequest, type ClusterActionResponse, type ClusterComponentState, type ClusterDeltaHandler, type ClusterSingletonClaim, type ClusterSingletonOwner, type ComponentDefinition, type ComponentMetadata, type ComponentMetrics, type ComponentPerformanceMetrics, ComponentRegistry, type ComponentState, type ConnectionConfig, type ConnectionHealth, type ConnectionMetrics, ConnectionRateLimiter, DEFAULT_CHUNK_SIZE, DEFAULT_WS_PATH, EMIT_OVERRIDE_KEY, type EventHandler, type ExtractActions, type FileChunkData, type FileUploadChunkMessage, type FileUploadCompleteMessage, type FileUploadCompleteResponse, type FileUploadConfig, FileUploadManager, type FileUploadProgressResponse, type FileUploadStartMessage, type FluxStackWSData, type FluxStackWebSocket, type GenericWebSocket, type HttpRequest, type HttpResponse, type HttpRouteDefinition, type HybridComponentOptions, type HybridState, type IClusterAdapter, type IRoomPubSubAdapter, type IRoomStorageAdapter, InMemoryRoomAdapter, type InferComponentState, type InferPrivateState, type InferRoomEvents, type InferRoomMeta, type InferRoomState, type LiveActionAuth, type LiveActionAuthMap, type LiveAuthContext, type LiveAuthCredentials, LiveAuthManager, type LiveAuthProvider, type LiveAuthResult, type LiveAuthUser, LiveComponent, type LiveComponentAuth, type LiveComponentContext, type LiveComponentInstance, type LiveLogCategory, type LiveLogConfig, type LiveMessage, LiveRoom, type LiveRoomClass, LiveRoomManager, type LiveRoomManagerInterface, type LiveRoomOptions, LiveServer, type LiveServerOptions, type LiveTransport, type LiveWSData, PROTOCOL_VERSION, type PerformanceAlert, type PerformanceConfig, PerformanceMonitor, RateLimiterRegistry, type RoomCodec, type RoomCodecOption, RoomEventBus, type RoomEventContext, type RoomInfo, type RoomJoinContext, type RoomLeaveContext, type RoomMessage, RoomRegistry, type RoomStateData, RoomStateManager, type RoomSubscription, type ServerRoomHandle, type ServerRoomProxy, type SignedState, type StateMigration, type StateSignatureConfig, StateSignatureManager, type TypedCall, type TypedCallAndWait, type TypedSetValue, type UseTypedLiveComponentReturn, type WebSocketConfig, WebSocketConnectionManager, type WebSocketMessage, type WebSocketResponse, buildRoomFrame, buildRoomFrameTail, createTypedRoomEventBus, createTypedRoomState, decodeBinaryChunk, encodeBinaryChunk, getLiveComponentContext, jsonCodec, liveLog, liveWarn, msgpackCodec, parseRoomFrame, prependMemberHeader, queueWsMessage, registerComponentLogging, resolveCodec, sendBinaryImmediate, sendImmediate, setLiveComponentContext, unregisterComponentLogging };