ytptube/ui/app/utils/cache.ts
2026-02-20 22:46:30 +03:00

66 lines
1.6 KiB
TypeScript

type CacheEngine = 'session' | 'local';
interface CachedItem<T = any> {
value: T;
ttl: number | null;
time: number;
}
class Cache {
private storage: Storage;
private supportedEngines: CacheEngine[] = ['session', 'local'];
constructor(engine: CacheEngine = 'session') {
if (!this.supportedEngines.includes(engine)) {
throw new Error(`Engine '${engine}' not supported.`);
}
this.storage = 'session' === engine ? window.sessionStorage : window.localStorage;
}
set<T = any>(key: string, value: T, ttl: number | null = null): void {
const item: CachedItem<T> = { value, ttl, time: Date.now() };
this.storage.setItem(key, JSON.stringify(item));
}
get<T = any>(key: string): T | null {
const item = this.storage.getItem(key);
if (null === item) {
return null;
}
try {
const parsed: CachedItem<T> = JSON.parse(item);
if (null !== parsed.ttl && Date.now() - parsed.time > parsed.ttl) {
this.remove(key);
return null;
}
return parsed.value;
} catch {
return item as unknown as T;
}
}
remove(key: string): void {
this.storage.removeItem(key);
}
clear(filter: ((key: string) => boolean) | null = null): void {
if (null !== filter) {
Object.keys(this.storage)
.filter(filter)
.forEach((k) => this.storage.removeItem(k));
return;
}
this.storage.clear();
}
has(key: string): boolean {
return null !== this.get(key);
}
}
const useLocalCache = (): Cache => new Cache('local');
const useSessionCache = (): Cache => new Cache('session');
export { useSessionCache, useLocalCache, Cache };