Fork of atp.tools as a universal profile for people on the ATmosphere
1export interface CacheEntry {
2 data: any;
3 timestamp: number;
4}
5
6export interface UserCache {
7 get(key: string): CacheEntry | undefined;
8 set(key: string, value: CacheEntry): void;
9 delete(key: string): void;
10 clear(): void;
11 clean(): void;
12}
13
14export class PersistentUserCache implements UserCache {
15 private cache: Map<string, CacheEntry>;
16 private readonly CACHE_KEY = "bsky_user_cache";
17 private readonly CACHE_DURATION = 24 * 60 * 60 * 1000; // 1 day
18
19 constructor() {
20 this.cache = new Map();
21 this.loadFromStorage();
22 }
23
24 private loadFromStorage() {
25 try {
26 const stored = localStorage.getItem(this.CACHE_KEY);
27 if (stored) {
28 const parsed = JSON.parse(stored);
29 this.cache = new Map(Object.entries(parsed));
30 }
31 } catch (error) {
32 console.warn("Failed to load cache from storage:", error);
33 }
34 }
35
36 private saveToStorage() {
37 try {
38 const obj = Object.fromEntries(this.cache);
39 localStorage.setItem(this.CACHE_KEY, JSON.stringify(obj));
40 } catch (error) {
41 console.warn("Failed to save cache to storage:", error);
42 }
43 }
44
45 get(key: string): CacheEntry | undefined {
46 return this.cache.get(key);
47 }
48
49 set(key: string, value: CacheEntry) {
50 this.cache.set(key, value);
51 this.saveToStorage();
52 }
53
54 delete(key: string) {
55 this.cache.delete(key);
56 this.saveToStorage();
57 }
58
59 clear() {
60 this.cache.clear();
61 this.saveToStorage();
62 }
63
64 clean() {
65 const now = Date.now();
66 let hasChanges = false;
67
68 for (const [key, value] of this.cache.entries()) {
69 if (now - value.timestamp > this.CACHE_DURATION) {
70 this.cache.delete(key);
71 hasChanges = true;
72 }
73 }
74
75 if (hasChanges) {
76 this.saveToStorage();
77 }
78 }
79}