UNPKG

wxt-zustand

Version:

High-performance Zustand state management for WXT web extensions with seamless cross-tab synchronization and sub-10ms React re-renders

100 lines 3.92 kB
import { mergeStatePreservingFunctions } from '../utils/stateTransforms'; import { connectAndFetchInitialState as _connectAndFetchInitialState } from './connect'; import { setupBidirectionalSync as _setupBidirectionalSync } from './sync'; /** * WeakMap registry to track per-store readiness promises. * Uses WXT-optimized approach for extension context management. * Map key: Zustand StoreApi instance (WeakMap avoids memory leaks) * Map value: Record of storeName -> readiness Promise<void> */ const readinessRegistry = new WeakMap(); function getRecord(store) { const existing = readinessRegistry.get(store); if (existing) return existing; const created = {}; readinessRegistry.set(store, created); return created; } /** * Returns the cached readiness promise for a given store and name, if any. */ export function getStoreReadiness(storeName, store) { const record = readinessRegistry.get(store); return record?.[storeName]; } /** * Caches a readiness promise for a given store and name. */ export function setStoreReadiness(storeName, store, readiness) { const record = getRecord(store); record[storeName] = readiness; } /** * Cleanup cached readiness data. * - When storeName is provided, remove only that entry. * - Otherwise, remove the entire record for the StoreApi. */ export function cleanupStoreReadiness(store, storeName) { if (storeName) { const record = readinessRegistry.get(store); if (!record) return; delete record[storeName]; // If record becomes empty, drop the WeakMap entry if (Object.keys(record).length === 0) { readinessRegistry.delete(store); } } else { readinessRegistry.delete(store); } } /** * For diagnostics/tests only: expose internal state length. */ export function __readinessSizeFor(store) { const record = readinessRegistry.get(store); return record ? Object.keys(record).length : 0; } // Internal indirection for testability (avoid global mock.module collisions) let connectAndFetchInitialState = _connectAndFetchInitialState; let setupBidirectionalSync = _setupBidirectionalSync; export function __setReadyImplementations(impl) { if (impl.connectAndFetchInitialState) connectAndFetchInitialState = impl.connectAndFetchInitialState; if (impl.setupBidirectionalSync) setupBidirectionalSync = impl.setupBidirectionalSync; } export function __resetReadyImplementations() { connectAndFetchInitialState = _connectAndFetchInitialState; setupBidirectionalSync = _setupBidirectionalSync; } /** * Orchestrate frontend readiness for a WXT Zustand store. * - Uses WXT-native primitives for optimal performance and compatibility. * - Ensures single initialization per (store instance + name) via readiness cache. * - Applies initial state, then sets up bidirectional sync. */ export async function wxtZustandStoreReady(storeName, store, config = {}) { // If we already kicked off readiness for this store+name, just await it. const existing = getStoreReadiness(storeName, store); if (existing) { await existing; return store; } // Create a single readiness promise that both fetches initial state and // attaches sync. Cache it immediately to prevent duplicate work. const readiness = (async () => { const { initialState } = await connectAndFetchInitialState(storeName); // Replace entire state but preserve any function props (e.g., actions) const merged = mergeStatePreservingFunctions(store.getState(), initialState); store.setState(merged, true); // After initial state is in place, wire up bidirectional sync. setupBidirectionalSync(storeName, store, config); })(); setStoreReadiness(storeName, store, readiness); await readiness; return store; } //# sourceMappingURL=ready.js.map