import type { City, Country, State } from '../types' class LRUCache { private readonly map = new Map() constructor(private readonly maxSize: number) {} get(key: string): T | undefined { const value = this.map.get(key) if (value === undefined) return undefined this.map.delete(key) this.map.set(key, value) return value } set(key: string, value: T): void { if (this.map.has(key)) { this.map.delete(key) } else if (this.map.size >= this.maxSize) { const lruKey = this.map.keys().next().value if (lruKey !== undefined) this.map.delete(lruKey) } this.map.set(key, value) } has(key: string): boolean { return this.map.has(key) } } export const countriesCache = new LRUCache(1) export const statesCache = new LRUCache(20) export const citiesCache = new LRUCache(10) const pending = new Map>() export function cachedFetch( cache: LRUCache, key: string, fetcher: () => Promise ): Promise { const hit = cache.get(key) if (hit !== undefined) return Promise.resolve(hit) const inflight = pending.get(key) as Promise | undefined if (inflight !== undefined) return inflight const promise = fetcher() .then((data) => { cache.set(key, data) pending.delete(key) return data }) .catch((err: unknown) => { pending.delete(key) throw err }) pending.set(key, promise) return promise }