Cache
One cache API, swappable drivers. Pick a backend at boot — localStorage, sessionStorage, in-memory map, opt-in IndexedDB, or any of those with encryption layered on — then call cache.set / cache.get / cache.remove / cache.clear everywhere else. Every storage-touching method is async. TTL, key prefixing, and default-fallbacks built in. Pairs cleanly with @mongez/atom’s persist slot.
Highlighted features
One async API, seven drivers
Plain + encrypted variants for localStorage / sessionStorage / IndexedDB, plus a runtime in-memory driver. Configure once; swap drivers without touching call sites.
Per-entry TTL
await cache.set(“token”, value, 60 * 15) — entries expire on read after their TTL. Or set a default for every key via configuration.
Encryption-at-rest
EncryptedLocalStorageDriver / EncryptedSessionStorageDriver / EncryptedIndexedDBDriver run values through your encrypt/decrypt pair before writing. Sensitive cache values stay opaque on disk.
Opt-in IndexedDB
IndexedDBDriver / EncryptedIndexedDBDriver for structured values and quotas beyond ~5MB. Never wired up by default — construct one explicitly.
Key prefixing
prefix: “shop-” namespaces every key so multiple apps on the same domain can’t collide. Set once at config time.
Pairs with @mongez/atom
Any driver satisfies the async PersistAdapter shape — drop it into an atom’s persist slot and the atom hydrates from cache + writes through on update.
Install
npm install @mongez/cacheyarn add @mongez/cachepnpm add @mongez/cacheRequires Node >=20. @mongez/encryption (^2.0.0) is an optional peer — install only when using the Encrypted* drivers.
Quick peek
import cache, { PlainLocalStorageDriver, setCacheConfigurations } from "@mongez/cache";
setCacheConfigurations({ driver: new PlainLocalStorageDriver(), prefix: "shop-", // namespace every key expiresAfter: 60 * 60, // optional default TTL: 1 hour});
await cache.set("user", { id: 1, name: "Hasan" });await cache.set("token", "abc123", 60 * 15); // override the default TTLawait cache.get("user"); // { id: 1, name: "Hasan" }Pick a backend at boot, then use the same async API everywhere.
Available drivers
| Driver | Persistence | Notes |
|---|---|---|
PlainLocalStorageDriver | Cross-session | JSON-serialised; supports TTL envelope |
PlainSessionStorageDriver | Tab-lifetime | Same contract as local-storage variant |
EncryptedLocalStorageDriver | Cross-session | Encrypt/decrypt before writing |
EncryptedSessionStorageDriver | Tab-lifetime | Encrypted sessionStorage variant |
RunTimeDriver | In-memory (lost on reload) | SSR-safe; no Web Storage dependency |
IndexedDBDriver (opt-in) | Cross-session | Structured clone (no JSON pass); larger quota |
EncryptedIndexedDBDriver (opt-in) | Cross-session | IndexedDB + encrypted envelope |
All drivers implement the same async CacheDriverInterface — set / get / has / remove / clear / keys / getAll.
Key pitfalls
setCacheConfigurationsmust be called before first use. The singleton’s driver isundefineduntil you call it;cache.set(...)before configuring throws.- Every storage-touching method returns a
Promise. Even the synchronous-under-the-hood drivers (Web Storage,RunTimeDriver) resolve immediately rather than returning the value directly —awaitis required as of 2.0.0. - Web Storage drivers throw on the server (no
localStoragein Node). Gate driver selection withtypeof window === "undefined"and fall back toRunTimeDriverfor SSR paths. RunTimeDriverinstances are not shared. Two instances have independent stores; no global in-memory registry.- IndexedDB is never the default. Nothing constructs
IndexedDBDriverfor you — opt in explicitly viasetCacheConfigurations({ driver: new IndexedDBDriver() }).
Where to go next
- Basic usage —
cache.set/get/remove/clear, TTL semantics - Manager —
CacheManager, custom singletons, multi-cache apps,keys()/getAll() - Drivers, Local storage, Session storage, Runtime, IndexedDB — driver internals
- Custom drivers — implementing
CacheDriverInterface - Encryption, Encrypted cache — opaque-at-rest values
- Recipes — common patterns