/** * Client-side Event Store * * Maintains a circular buffer of events captured from WebSocket interception * with persistence, export/import, and time-travel capabilities */ import type { DevToolsEvent, ActiveSubscription, PerformanceMetrics } from "../types.js"; export type EventListener = (event: DevToolsEvent) => void; export type BatchListener = (events: DevToolsEvent[]) => void; export type FocusListener = (eventId: string | null) => void; export type SettingsListener = (settings: DevToolsSettings) => void; /** * Per-function aggregate statistics for the performance panel. */ export interface FunctionStats { udfPath: string; type: "query" | "mutation" | "action"; calls: number; errors: number; /** Percentage in [0, 100]. */ errorRate: number; avgDuration: number; p50Duration: number; p95Duration: number; maxDuration: number; lastInvoked: number; } export interface DevToolsSettings { persistEvents: boolean; maxEvents: number; captureLogLines: boolean; autoPauseOnError: boolean; wsLatencyMs: number; wsJitterMs: number; } export interface StoreSnapshot { timestamp: number; events: DevToolsEvent[]; subscriptions: Array<[number, ActiveSubscription]>; } export interface ExportedSession { version: string; exportedAt: number; events: DevToolsEvent[]; subscriptions: Array<[number, ActiveSubscription]>; metadata: { userAgent: string; url: string; }; } export interface EventStoreOptions { maxEvents?: number; storageScope?: string; enablePersistence?: boolean; } export declare class EventStore { private events; private maxEvents; private listeners; private batchListeners; private pendingBatch; private batchTimer; private eventsSnapshot; private focusListeners; private settingsListeners; private subscriptions; private snapshots; private maxSnapshots; private isPaused; private focusedEventId; private readonly storageKey; private readonly settingsKey; private readonly persistenceEnabled; private recentEventIds; private persistTimer; private settings; private static readonly MIN_EVENTS; private static readonly MAX_EVENTS; private static readonly MAX_SIMULATED_LATENCY_MS; constructor(options?: number | EventStoreOptions, legacyStorageScope?: string); /** * Add an event to the store */ addEvent(event: DevToolsEvent): void; /** * Notify per-event listeners immediately and enqueue for batched listeners. */ private emit; private flushBatch; /** * Subscribe to new events */ subscribe(listener: EventListener): () => void; /** * Subscribe to events in coalesced batches (at most one delivery per * ~80ms window). Prefer this for UI rendering: per-event subscriptions * re-render once per event, which is too often for chatty apps. */ subscribeBatched(listener: BatchListener): () => void; /** * Subscribe to focus/navigation changes across panels */ subscribeFocus(listener: FocusListener): () => void; /** * Subscribe to settings changes */ subscribeSettings(listener: SettingsListener): () => void; /** * Set the currently focused event (for cross-panel navigation) */ setFocusedEventId(eventId: string | null): void; /** * Get focused event id */ getFocusedEventId(): string | null; /** * Get all events. The returned array is cached until the store changes, * so repeated calls between updates are free and referentially stable * (safe for React dependency comparisons). */ getAllEvents(): DevToolsEvent[]; /** * Get events by type */ getEventsByType(type: T["type"]): T[]; /** * Get recent events */ getRecentEvents(count: number): DevToolsEvent[]; /** * Get events for a specific function */ getEventsByFunction(udfPath: string): DevToolsEvent[]; /** * Get active subscriptions */ getActiveSubscriptions(): ActiveSubscription[]; /** * Get subscription by query ID */ getSubscription(queryId: number): ActiveSubscription | undefined; /** * Calculate performance metrics */ getPerformanceMetrics(): PerformanceMetrics; /** * Per-function aggregates over the recorded events, sorted by call count. * Pending operations are excluded; errors count toward calls and errorRate * but not toward duration percentiles (no meaningful duration). */ getFunctionStats(): FunctionStats[]; /** * Clear all events */ clear(): void; /** * Pause event capture */ pause(): void; /** * Resume event capture */ resume(): void; /** * Check if paused */ isPausedState(): boolean; /** * Create a snapshot of current state (for time-travel) */ createSnapshot(): void; /** * Restore from a snapshot */ restoreSnapshot(timestamp: number): boolean; /** * Get all snapshots */ getSnapshots(): StoreSnapshot[]; /** * Export session data */ exportSession(): ExportedSession; /** * Import session data */ importSession(session: ExportedSession): boolean; /** * Save settings */ saveSettings(settings: Partial): void; /** * Get settings */ getSettings(): typeof this.settings; /** * Whether this store supports local persistence */ isPersistenceEnabled(): boolean; /** * Load settings from localStorage */ private loadSettings; /** * Push latency settings to the shared window config object * that the WebSocket interceptors read on every send/receive. */ private syncLatencyConfig; private notifySettingsChanged; /** * Persist events to localStorage */ private persistEvents; /** * Load persisted events from localStorage */ private loadPersistedEvents; /** * Update subscription tracking */ private updateSubscription; private clearPendingQueryEvents; private sanitizeEvents; private isEventLike; private normalizeMaxEvents; private normalizeLatencySettings; private isOperationEvent; private isTerminalOperationEvent; private isMatchingPendingOperation; private reconcilePendingOperation; } export declare function getGlobalEventStore(): EventStore;