/** * RealtimeRoom — presence + broadcast over a {@link RealtimeTransport}. * * const room = RealtimeRoom.join({ * transport: new BroadcastChannelTransport({ id, channel: 'demo' }), * initialPresence: { name: 'Ada', color: '#6d5bfa' }, * }); * * room.onPresence((peers) => renderAvatars(peers)); * room.setPresence({ cursor: { x, y } }); * room.on('chat', (e) => appendMessage(e.payload)); * room.broadcast('chat', 'message', { text: 'hi' }); * * Presence is heartbeat-based: peers re-announce on an interval and are pruned * after a timeout. Transports with explicit teardown (MemoryHub) also emit an * immediate `bye` on {@link RealtimeRoom.leave}. */ import { Signal } from '../client/reactive.js'; import type { BroadcastEvent, PresencePeer, PresenceState, RealtimeMessage, RealtimeTransport } from './types.js'; export interface RealtimeRoomOptions
{ transport: RealtimeTransport; /** Initial presence for the local peer. */ initialPresence?: P; /** Heartbeat interval (ms). Default 2000. Set 0 to disable timers. */ heartbeatMs?: number; /** Peer expiry after no heartbeat (ms). Default 6000. */ timeoutMs?: number; /** Injectable clock for tests. Default `Date.now`. */ now?: () => number; } type BroadcastHandler = (event: BroadcastEvent) => void; export declare class RealtimeRoom
{ readonly id: string; private transport; private myState; private peers; /** Sender timestamps from presence messages (not local lastSeen). */ private presenceTsByPeer; private channelHandlers; private _presence; private now; private heartbeatMs; private timeoutMs; private heartbeatTimer?; private unsubscribe; private closed; private pendingReplay; /** Ids of broadcasts already delivered — keeps replay idempotent (G-Set). */ private seenMsgIds; private constructor(); /** Join a room and announce presence. */ static join
(opts: RealtimeRoomOptions
): RealtimeRoom
; /** The local peer id. */ get selfId(): string; /** Current local presence state. */ getSelfState(): P; /** Merge a partial update into local presence and broadcast it. */ setPresence(partial: Partial
): void; /** Replace local presence wholesale and broadcast it. */ replacePresence(state: P): void; /** All peers including self (self first). */ getPresence(): PresencePeer
[]; /** Peers excluding self. */ getOthers(): PresencePeer
[]; /** Subscribe to presence changes. Called immediately with current peers. */ onPresence(cb: (peers: PresencePeer
[]) => void): () => void;
/** Reactive presence signal (for framework adapters). */
get presenceSignal(): Signal