···11+import { atom } from 'jotai';
22+import { atomFamily } from 'jotai/utils';
33+import type { EsavDocument, QueryState, LogEntry } from './types';
44+const MAX_LOG_SIZE = 500;
55+66+/**
77+ * Manages the WebSocket instance itself.
88+ * Should only be written to by the provider.
99+ */
1010+export const websocketAtom = atom<WebSocket | null>(null);
1111+1212+/**
1313+ * Tracks the current status of the WebSocket connection.
1414+ */
1515+export const websocketStatusAtom = atom<'connecting' | 'open' | 'closed'>('closed');
1616+1717+/**
1818+ * A global, normalized cache for all documents received from the server.
1919+ * Maps a document URI (at://...) to its full data.
2020+ * This prevents data duplication across multiple queries.
2121+ */
2222+export const documentsAtom = atom<Record<string, EsavDocument>>({});
2323+2424+/**
2525+ * A family of atoms to hold the state for each individual query.
2626+ * You get the state for a query by providing its unique queryId.
2727+ */
2828+export const queryStateFamily = atomFamily((_queryId: string) =>
2929+ atom<QueryState | null>(null)
3030+);
3131+3232+/**
3333+ * Tracks active subscriptions and their component usage count.
3434+ * This is an internal atom used by our hooks to know when to
3535+ * send `subscribe` and `unsubscribe` messages.
3636+ */
3737+export const activeSubscriptionsAtom = atom<
3838+ Record<string, { count: number; esQuery: Record<string, any> }>
3939+>({});
4040+4141+4242+/**
4343+ * Holds the array of log entries for display.
4444+ */
4545+export const logEntriesAtom = atom<LogEntry[]>([]);
4646+4747+let logIdCounter = 0;
4848+4949+/**
5050+ * A "write-only" atom to add a new entry to the log.
5151+ * This encapsulates the logic for creating a new entry with an ID and timestamp.
5252+ * Any component can call this to add a log without needing to know the implementation details.
5353+ */
5454+export const addLogEntryAtom = atom(
5555+ null,
5656+ (get, set, newEntry: Omit<LogEntry, 'id' | 'timestamp'>) => {
5757+ const entry: LogEntry = {
5858+ id: logIdCounter++,
5959+ timestamp: new Date(),
6060+ ...newEntry,
6161+ };
6262+ const currentLog = get(logEntriesAtom);
6363+ const newLog = [entry, ...currentLog];
6464+ if (newLog.length > MAX_LOG_SIZE) {
6565+ newLog.length = MAX_LOG_SIZE;
6666+ }
6767+ set(logEntriesAtom, newLog);
6868+ }
6969+);