a a vibe-coded abomination experiment of a fragrance review platform built on the atmosphere.
drydown.social
1interface CacheEntry<T> {
2 value: T
3 expiresAt: number
4}
5
6class SimpleCache {
7 private store = new Map<string, CacheEntry<unknown>>()
8
9 get<T>(key: string): T | null {
10 const entry = this.store.get(key)
11 if (!entry) return null
12 if (Date.now() > entry.expiresAt) {
13 this.store.delete(key)
14 return null
15 }
16 return entry.value as T
17 }
18
19 set<T>(key: string, value: T, ttlMs: number): void {
20 this.store.set(key, { value, expiresAt: Date.now() + ttlMs })
21 }
22
23 delete(key: string): void {
24 this.store.delete(key)
25 }
26
27 clear(): void {
28 this.store.clear()
29 }
30
31 async getOrFetch<T>(key: string, ttlMs: number, fetcher: () => Promise<T>): Promise<T> {
32 const cached = this.get<T>(key)
33 if (cached !== null) return cached
34 const value = await fetcher()
35 this.set(key, value, ttlMs)
36 return value
37 }
38}
39
40export const cache = new SimpleCache()
41
42// TTL constants (ms)
43export const TTL = {
44 DID: 60 * 60 * 1000, // 1 hour
45 PDS: 60 * 60 * 1000, // 1 hour
46 PROFILE: 5 * 60 * 1000, // 5 minutes
47 FRAGRANCE: 30 * 60 * 1000, // 30 minutes
48 HOUSE: 30 * 60 * 1000, // 30 minutes
49 REVIEWS: 2 * 60 * 1000, // 2 minutes
50 SETTINGS: 30 * 60 * 1000, // 30 minutes
51}