import { Socket } from 'socket.io-client'; /** * Client operational lifecycle states. */ export type ClientState = 'idle' | 'electing' | 'follower' | 'leader' | 'disconnecting' | 'disposed'; /** * Coordination mode across browser tabs. */ export type CoordinationMode = 'shared' | 'independent'; /** * Standardized typed error codes for WebSocket and coordination failures. */ export type WebSocketErrorCode = 'invalid-argument' | 'connection-timeout' | 'timeout' | 'broadcast-failure' | 'leader-changed' | 'unauthenticated' | 'disconnected' | 'disposed' | 'ambiguous-outcome' | 'unavailable' | 'cancelled'; /** * Serialized error format passed across leader/follower boundaries and to consumers. */ export interface SerializedError { name: string; message: string; code: WebSocketErrorCode; retryable: boolean; source: 'client' | 'leader' | 'follower' | 'server'; isAmbiguous: boolean; details?: unknown; } /** * Production error class preserving structured metadata across tab boundaries. */ export declare class NexaWebSocketError extends Error implements SerializedError { readonly code: WebSocketErrorCode; readonly retryable: boolean; readonly source: 'client' | 'leader' | 'follower' | 'server'; readonly isAmbiguous: boolean; readonly details?: unknown; constructor(options: { message: string; code?: WebSocketErrorCode; retryable?: boolean; source?: 'client' | 'leader' | 'follower' | 'server'; isAmbiguous?: boolean; details?: unknown; cause?: unknown; }); toJSON(): SerializedError; static from(err: unknown, defaultSource?: 'client' | 'leader' | 'follower' | 'server'): NexaWebSocketError; } /** * Tri-state path extraction outcome to prevent invalid paths from becoming global events. */ export type PathExtractionResult = { status: 'none'; } | { status: 'valid'; path: string; } | { status: 'invalid'; raw: unknown; }; /** * Options for configuring WebSocketClient. */ export interface WebSocketClientOptions { sessionScope?: string; authPayload?: unknown; getAuthPayload?: () => Promise | unknown; defaultTimeoutMs?: number; coordinationMode?: CoordinationMode; followerTtlMs?: number; heartbeatIntervalMs?: number; pruneIntervalMs?: number; leaderLeaseIntervalMs?: number; socketFactory?: (url: string, opts: any) => Socket; broadcastChannelFactory?: (name: string) => BroadcastChannel; locks?: LockManager; } /** * Valid broadcast message types. */ export type BroadcastMessageType = 'follower_subscribe' | 'follower_unsubscribe' | 'follower_sync_request' | 'follower_announce' | 'follower_heartbeat' | 'follower_disconnect' | 'follower_send' | 'leader_elected' | 'leader_state' | 'leader_event' | 'leader_send_response'; export interface BaseBroadcastMessage { type: BroadcastMessageType; senderId: string; timestamp: number; } export interface FollowerSubscribeMessage extends BaseBroadcastMessage { type: 'follower_subscribe'; payload: { path: string; }; } export interface FollowerUnsubscribeMessage extends BaseBroadcastMessage { type: 'follower_unsubscribe'; payload: { path: string; }; } export interface FollowerSyncRequestMessage extends BaseBroadcastMessage { type: 'follower_sync_request'; payload?: Record; } export interface FollowerAnnounceMessage extends BaseBroadcastMessage { type: 'follower_announce'; payload: { paths: string[]; globalListenersCount: number; }; } export interface FollowerHeartbeatMessage extends BaseBroadcastMessage { type: 'follower_heartbeat'; payload: { globalListenersCount: number; paths?: string[]; }; } export interface FollowerDisconnectMessage extends BaseBroadcastMessage { type: 'follower_disconnect'; payload?: { tabId?: string; }; } export interface FollowerSendMessage extends BaseBroadcastMessage { type: 'follower_send'; payload: { requestId: string; expectedLeaderId: string; expectedElectionId: string; event: string; data: unknown; targetTabId: string; deadline: number; idempotencyKey?: string; }; } export interface LeaderElectedMessage extends BaseBroadcastMessage { type: 'leader_elected'; leaderId: string; electionId: string; termSeq: number; payload: { leaderId: string; electionId: string; isConnected: boolean; termSeq: number; }; } export interface LeaderStateMessage extends BaseBroadcastMessage { type: 'leader_state'; leaderId: string; electionId: string; termSeq: number; payload: { leaderId: string; electionId: string; isConnected: boolean; termSeq: number; }; } export interface LeaderEventMessage extends BaseBroadcastMessage { type: 'leader_event'; leaderId: string; electionId: string; payload: { event: string; data: unknown; targetTabIds?: string[]; }; } export interface LeaderSendResponseMessage extends BaseBroadcastMessage { type: 'leader_send_response'; leaderId: string; electionId: string; payload: { requestId: string; targetTabId: string; response?: unknown; error?: SerializedError; }; } export type BroadcastMessage = FollowerSubscribeMessage | FollowerUnsubscribeMessage | FollowerSyncRequestMessage | FollowerAnnounceMessage | FollowerHeartbeatMessage | FollowerDisconnectMessage | FollowerSendMessage | LeaderElectedMessage | LeaderStateMessage | LeaderEventMessage | LeaderSendResponseMessage; /** * Production-hardened WebSocketClient with distributed coordination, * term-fenced follower forwarding, BFCache/background resilience, and strict invariants. */ export declare class WebSocketClient { private readonly _projectId; private readonly _serverUrl; private readonly _sessionScope; private readonly _tabId; private readonly _options; private readonly _coordinationKey; private _coordinationMode; private _socket; private _isConnected; private _lastReportedConnected; private _state; private _isSuspended; private _authPayload; private _electionId; private _currentLeaderId; private _currentElectionId; private _currentTermSeq; private _isLeaderSocketConnected; private listeners; private localSubscribedPaths; private activeLocalSendsCount; private broadcastChannel; private lockAbortController; private resolveLeaderLock; private followerSubscriptions; private followerSubscriptionsByTab; private followerGlobalNeeds; private processedFollowerRequests; private pendingSendRequests; private activeLeaderSends; private readinessWaiters; private heartbeatTimer; private pruneTimer; private leaseTimer; private reconnectTimer; private pageLifecycleCleanup; private readonly followerTtlMs; private readonly heartbeatIntervalMs; private readonly pruneIntervalMs; private readonly leaderLeaseIntervalMs; private readonly defaultTimeoutMs; private static readonly DEFAULT_FOLLOWER_TTL; private static readonly DEFAULT_HEARTBEAT_INTERVAL; private static readonly DEFAULT_PRUNE_INTERVAL; private static readonly DEFAULT_LEADER_LEASE_INTERVAL; private static readonly DEFAULT_TIMEOUT_MS; private static readonly MAX_DEDUP_CACHE_SIZE; private static readonly DEDUP_CACHE_TTL_MS; private static readonly RESERVED_SEND_EVENTS; constructor(projectId: string, serverUrl: string, options?: WebSocketClientOptions); get projectId(): string; get serverUrl(): string; get tabId(): string; get isConnected(): boolean; get isLeader(): boolean; get state(): ClientState; get electionId(): string | null; get currentLeaderId(): string | null; get currentElectionId(): string | null; get isIndependent(): boolean; get coordinationMode(): CoordinationMode; get isSuspended(): boolean; /** * Unique ID generation with Web Crypto fallback. */ static generateId(): string; /** * Stable deterministic hashing function. */ static hashScope(scope: string): string; /** * Normalizes server URL and creates a unique coordination key. */ static deriveCoordinationKey(projectId: string, serverUrl: string, sessionScope: string | null): string; /** * Sanitizes, segments, and bounds path strings. */ static cleanAndValidatePath(path: unknown): string | null; static validatePathOrThrow(path: unknown): string; /** * Segment-aware path matcher: checks exact match or segment hierarchy. */ static isPathMatch(eventPath: string, subPath: string): boolean; /** * Tri-state path extraction distinguishing: none vs valid vs invalid. */ static extractPayloadPathTriState(payload: unknown): PathExtractionResult; /** * Backward-compatible extractor returning valid path or null. */ static extractPayloadPath(payload: unknown): string | null; /** * Dynamic authentication updater. */ updateAuth(authPayload: unknown): void; private getFreshAuthPayload; private transitionTo; /** * Atomically downgrades from shared coordination to independent socket mode. */ private switchToIndependentMode; /** * Safe non-throwing broadcast poster returning a delivery indicator boolean. */ private postBroadcast; /** * Strictly validates incoming broadcast payload schema, types, bounds, and string sizes. */ validateBroadcastMessage(raw: unknown): BroadcastMessage | null; private handleBroadcastMessage; private handleMessageAsLeader; private pruneDedupCache; private handleFollowerSendRequest; private handleMessageAsFollower; private updateFollowerConnectionState; private handleFollowerAnnounce; private announceNeedsToLeader; private announceGlobalListenersChange; private getGlobalListenersCount; private addFollowerPathSubscription; private removeFollowerPathSubscription; private pruneFollower; private startFollowerHeartbeat; private stopFollowerHeartbeat; private startLeaderPruneTimer; private stopLeaderPruneTimer; private startLeaderLeaseTimer; private stopLeaderLeaseTimer; /** * Subscribes an event listener callback with reference counting and connection management. */ addListener(event: string, callback: (data: any) => void): () => void; /** * Reference-counted path subscription. */ subscribe(path: string): void; /** * Decrements reference-counted path subscription. */ unsubscribe(path: string): void; private broadcastToFollowers; /** * Connects socket directly or coordinates election via Web Locks. */ ensureConnected(): void; private startSocketConnection; private isLocalSubscribedToPath; private handleSocketDataEvent; private executeSendAsLeader; private checkReadinessWaiters; private waitForReady; private static isMutatingEvent; /** * Production-hardened request execution with invariant counter handling in a single finally block. */ send(event: string, data: any, timeoutMs?: number): Promise; checkCloseConnection(): void; hasNetworkNeeds(): boolean; private hasLocalNeeds; hasListeners(): boolean; /** * Dispatches events using a defensive snapshot of listeners to avoid mutation hazards. */ dispatch(event: string, data: any): void; private releaseLeaderLock; private disconnectSocket; private setupPageLifecycleListeners; /** * Idempotent client teardown releasing locks, clearing queues, and sending best-effort disconnect notice. */ close(): void; }