npm install rune-syncimport { lsSync } from 'rune-sync/localstorage'; let settings = lsSync('settings', { theme: 'dark', lang: 'en' }); settings.theme = 'light'; // Persisted automaticallyNote: State must always be an object — primitives are not supported as root values.
import { lsSync } from 'rune-sync/localstorage'; let state = lsSync('key', { count: 0 });Cross-tab sync via the native storage event. No extra dependencies.
npm install localforageimport { lfSync } from 'rune-sync/localforage'; let state = lfSync('key', { count: 0 });Cross-tab sync via BroadcastChannel. Requires localforage as a peer dependency.
import { ckSync } from 'rune-sync/cookie'; // Default options (path: '/', sameSite: 'lax') let state = ckSync('key', { count: 0 });With custom cookie settings:
import { createCookieSync } from 'rune-sync/cookie'; const cookieSync = createCookieSync({ path: '/', maxAge: 86400, sameSite: 'strict', secure: true }); let state = cookieSync('key', { count: 0 });Cross-tab sync via BroadcastChannel. Keep in mind the ~4KB cookie size limit.
CookieOptions:
| Option | Type | Default |
|---|---|---|
path | string | '/' |
domain | string | — |
maxAge | number (seconds) | — |
expires | Date | — |
sameSite | 'strict' | 'lax' | 'none' | 'lax' |
secure | boolean | — |
All drivers accept an optional third argument:
let state = lsSync('key', { value: 0 }, { debounce: 500, // Wait 500ms after last change before writing throttle: 1000, // Write at most once per 1000ms doNotSubscribe: true // Disable cross-tab sync });| Option | Type | Description |
|---|---|---|
debounce | number | Delay writes by N ms after the last change |
throttle | number | Write at most once per N ms (with trailing) |
doNotSubscribe | boolean | Disable cross-tab synchronization |
Implement the StateSynchronizer interface to use any storage backend:
import { createSyncState } from 'rune-sync'; import type { StateSynchronizer } from 'rune-sync'; const mySynchronizer: StateSynchronizer = { read: async (key) => { const data = await myStorage.get(key); return data ?? null; }, write: async (key, value) => { await myStorage.set(key, value); }, // Optional: enable real-time updates subscribe: (key, write) => { const unsubscribe = myRealtimeService.on(key, (data) => { write(data); }); return unsubscribe; } }; const mySync = createSyncState(mySynchronizer); let state = mySync('app-state', { counter: 0 });interface StateSynchronizer { read<T>(key: string): Promise<T | null> | T | null; write<T>(key: string, value: T): Promise<void> | void; subscribe?<T>(key: string, write: (newValue: T) => void): () => void; }MIT License - see LICENSE for details.