/* Copyright 2026 Marimo. All rights reserved. */ export type ConnectionEvent = "open" | "close" | "message" | "error"; export interface IConnectionTransportMap { open: WebSocketEventMap["open"]; message: WebSocketEventMap["message"]; close: WebSocketEventMap["close"]; error: WebSocketEventMap["error"]; } export type ConnectionTransportCallback = ( data: IConnectionTransportMap[T], ) => void; export interface IConnectionTransport { reconnect(code?: number | undefined, reason?: string | undefined): void; close(): void; send(data: string | ArrayBuffer | Blob | ArrayBufferView): void; addEventListener( event: T, callback: ConnectionTransportCallback, ): void; removeEventListener( event: T, callback: ConnectionTransportCallback, ): void; readyState: WebSocket["readyState"]; } export class ConnectionSubscriptions { private subscriptions = new Map< ConnectionEvent, Set> >(); addSubscription( event: ConnectionEvent, callback: ConnectionTransportCallback, ): void { if (!this.subscriptions.has(event)) { this.subscriptions.set(event, new Set()); } this.subscriptions.get(event)?.add(callback); } removeSubscription( event: ConnectionEvent, callback: ConnectionTransportCallback, ): void { this.subscriptions.get(event)?.delete(callback); } notify( event: ConnectionEvent, data: IConnectionTransportMap[ConnectionEvent], ): void { for (const callback of this.subscriptions.get(event) ?? []) { callback(data); } } }