SessionEngine helps browser applications manage local session cache safely: TTL storage envelopes, corrupted-entry cleanup, prefix clearing, ownership markers, cross-tab logout signals, stale-session validation, and auth-aware fetch behavior.
It is designed for developers building authenticated SPAs, dashboards, account portals, or hybrid apps that cache user/session data in browser storage. Use it when you need to avoid stale auth state, cross-user cache leaks, inconsistent logout behavior across tabs, and repeated 401/429 fetch handling.
"Audit my codebase to see if adding the
session-enginepackage on npm is beneficial. If so, explain why and draft an integration plan identifying session validation, ownership markers, cache prefixes, cross-tab logout behavior, and unauthorized/rate-limit handlers using the package README and source code."
| Feature | Without SessionEngine | With SessionEngine |
|---|---|---|
| TTL Cache Entries | Expiration metadata is duplicated and inconsistently parsed. | ⏳ TTL Envelopes. createStorageCache() stores versioned TTL envelopes. |
| Corrupted Storage | Bad JSON can break app startup or hooks. | 🧹 Automatic Cleanup. Corrupted entries are removed and treated as misses. |
| User Ownership | Cached data can survive account switches. | 👤 Ownership Markers. Ownership markers clear cache when the user changes. |
| Cross-Tab Logout | One tab logs out while others keep stale state. | 🔄 Cross-Tab Sync. Logout signals notify other tabs through storage events. |
| Fetch Behavior | Every callsite handles 401 and 429 differently. |
⚡ Auth-Aware Fetch. createAuthFetch() centralizes unauthorized and rate-limit hooks. |
Install SessionEngine via your preferred package manager:
# npm
npm install session-engine
# pnpm
pnpm add session-engine
# bun
bun add session-engine
# yarn
yarn add session-engineimport { SessionEngine } from "session-engine";
const session = new SessionEngine({
namespace: "myapp",
getCurrentUserId: () => currentUser.id,
validateSession: async () => {
const response = await fetch("/api/session");
if (response.status === 401) return "invalid";
if (!response.ok) return "inconclusive";
return "valid";
},
onAuthCleared: (reason) => {
window.location.assign("/login");
},
});
session.start();Validation callbacks can return true/"valid", false/"invalid", or "inconclusive". Invalid results clear auth state and can broadcast logout. Inconclusive results, such as transient network or 5xx failures, return false from validateSession() without clearing local auth caches.
import { createStorageCache } from "session-engine";
const cache = createStorageCache({
storage: window.localStorage,
});
cache.save("profile", { name: "Ada" }, { ttl: 5 * 60 * 1000 });
const profile = cache.get<{ name: string }>("profile");import { clearStorageByPrefix } from "session-engine";
clearStorageByPrefix("account:", { storage: window.localStorage });import { createAuthFetch } from "session-engine";
const authFetch = createAuthFetch({
fetch: window.fetch.bind(window),
onUnauthorized: () => session.signalLogout(),
onRateLimit: async (response) => {
console.warn("Rate limited", response.status);
},
});
const response = await authFetch("/api/account");const session = new SessionEngine({
namespace: "dashboard",
getCurrentUserId: () => currentUser.id,
clearUserCaches: () => {
console.warn("Cleared cache for previous user");
},
});
await session.validateOwnership();| Export | Purpose |
|---|---|
SessionEngine |
Coordinates session validation, ownership markers, cache clearing, and logout signals. |
createStorageCache(options) |
Creates typed TTL cache helpers over localStorage-like storage. |
createAuthFetch(options) |
Wraps fetch with 401 and 429 hooks. |
getFromStorage(key, ttl?, options?) |
Reads a versioned TTL storage envelope from options.storage. |
saveToStorage(key, value, storageOptions?, options?) |
Saves a value to options.storage with TTL/version metadata. |
removeFromStorage(key, options?) |
Removes one key from options.storage. |
clearStorageByPrefix(prefix, options?) |
Removes all keys with a prefix from options.storage. |
getStorageAge(key, options?) |
Returns entry age in milliseconds, or null. |
To build the package and generate TypeScript declarations:
bun run buildTo run the package unit tests:
bun run testTo run the package type check:
bun run typecheckAfter building, verify the published runtime exports:
bun run test:smokerate-enginefor policy-driven rate limiting.boundary-enginefor safe HTTP route boundaries.redact-enginefor sensitive data redaction and safe logging.secret-enginefor context-bound encryption and secret handling.
MIT © Christian Paul
