A generic observable key-value store for runtime toggles — feature flags, permission overrides, locale settings — that must be changeable without a deploy. Each store is isolated per domain, guarded by a build-context predicate, optionally persisted to localStorage, and reactive via useSyncExternalStore.
API
const store = createOverrideStore<boolean>({
guard: () => isDev, // writes no-op in prod
storageKey: "app:my-overrides", // opt-in persistence
name: "my-overrides", // opt-in DevTools registration
});
store.set(key, value) // write (checked by guard)
store.get(key) // V | undefined
store.getAll() // ReadonlyMap<string, V>
store.remove(key)
store.clear()
store.version() // monotonic int — snapshot for useSyncExternalStore
store.subscribe(cb) // returns unsubscribe
Implementation
function createOverrideStore<V>(opts?: {
guard?: () => boolean;
storageKey?: string;
}): OverrideStore<V> {
const map = new Map<string, V>();
const subscribers = new Set<() => void>();
let ver = 0;
// Hydrate synchronously so overrides exist before first render
if (opts?.storageKey) {
try {
const raw = localStorage.getItem(opts.storageKey);
if (raw) for (const [k, v] of JSON.parse(raw)) map.set(k, v);
} catch {}
}
const allowed = () => opts?.guard ? opts.guard() : true;
const notify = () => { for (const cb of subscribers) cb(); };
const persist = () => {
if (!opts?.storageKey) return;
map.size === 0
? localStorage.removeItem(opts.storageKey)
: localStorage.setItem(opts.storageKey, JSON.stringify([...map]));
};
return {
set(k, v) { if (!allowed()) return; map.set(k, v); ver++; persist(); notify(); },
remove(k) { if (!allowed()) return; if (map.delete(k)) { ver++; persist(); notify(); } },
clear() { if (!allowed()) return; if (map.size) { map.clear(); ver++; persist(); notify(); } },
get(k) { return map.get(k); },
getAll() { return map; },
version() { return ver; },
subscribe(cb) { subscribers.add(cb); return () => subscribers.delete(cb); },
};
}
Imperative usage
Check the override first — it wins unconditionally:
const permOverrides = createOverrideStore<boolean>({ guard: () => isDev });
function canEdit(userId: string): boolean {
const ov = permOverrides.get(`edit:${userId}`);
if (ov !== undefined) return ov;
return evaluateRealPermission(userId);
}
Reactive usage
version() is a monotonic counter — safe as a useSyncExternalStore snapshot:
function usePermission(key: string) {
const _ver = useSyncExternalStore(
(cb) => permOverrides.subscribe(cb),
() => permOverrides.version(),
);
return useMemo(() => {
const ov = permOverrides.get(key);
return ov !== undefined ? ov : evaluateRealPermission(key);
}, [key, _ver]);
}
Rules
- One store per domain area. Never mix permission and flag overrides.
- Always guard. A missing guard means prod users can write overrides.
- Override check comes first in every evaluator — override wins unconditionally.
version()as the snapshot, not entry count — a value update without a size change would skip the re-render.