MCPcopy Create free account
hub / github.com/VPSDance/ai-proxy-rules / FetchCache

Class FetchCache

scripts/sync/cache.ts:18–173  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

16const STALE_CACHE_DAYS = 30;
17
18export class FetchCache {
19 private warnings: CacheWarning[] = [];
20 private staleWarnings: StaleCacheWarning[] = [];
21 private indexCache: Record<string, string> | null = null;
22 private usedKeys = new Set<string>();
23
24 constructor(private cacheDir: string) {}
25
26 async fetch(url: string): Promise<string> {
27 return this.cached(url, async () => {
28 const response = await fetch(url);
29 if (!response.ok) {
30 throw new Error(`HTTP ${response.status} ${response.statusText}`);
31 }
32 return response.text();
33 });
34 }
35
36 async cached(key: string, fresh: () => Promise<string>): Promise<string> {
37 this.usedKeys.add(this.cacheKey(key));
38 try {
39 const text = await fresh();
40 await this.write(key, text);
41 return text;
42 } catch (error) {
43 const cachedEntry = await this.read(key);
44 if (cachedEntry !== null) {
45 this.warnings.push({
46 url: key,
47 reason: error instanceof Error ? error.message : String(error),
48 cachedAt: cachedEntry.cachedAt
49 });
50 if (cachedEntry.cachedAt) {
51 const ageDays = (Date.now() - new Date(cachedEntry.cachedAt).getTime()) / 86_400_000;
52 if (ageDays > STALE_CACHE_DAYS) {
53 this.staleWarnings.push({ url: key, ageDays: Math.floor(ageDays) });
54 }
55 }
56 return cachedEntry.text;
57 }
58 throw new Error(
59 `Failed to fetch ${key} and no cache available: ${
60 error instanceof Error ? error.message : String(error)
61 }`
62 );
63 }
64 }
65
66 async pruneOrphans(): Promise<string[]> {
67 const removed: string[] = [];
68 const index = await this.readIndex();
69 let indexChanged = false;
70
71 for (const key of Object.keys(index)) {
72 if (!this.usedKeys.has(key)) {
73 const file = path.join(this.cacheDir, `${key}.txt`);
74 await unlink(file).catch(() => undefined);
75 removed.push(index[key] ?? key);

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected