chore: sync submodule state (parent ref update)
Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Fetch JSON from a URL with in-memory caching.
|
||||
* Used for TOKEN_LIST_JSON_URL, BRIDGE_LIST_JSON_URL, NETWORKS_JSON_URL (e.g. GitHub raw URLs).
|
||||
*/
|
||||
|
||||
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
interface CacheEntry {
|
||||
data: unknown;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
const cache = new Map<string, CacheEntry>();
|
||||
|
||||
export async function fetchRemoteJson(
|
||||
url: string,
|
||||
ttlMs: number = CACHE_TTL_MS
|
||||
): Promise<unknown> {
|
||||
const trimmed = url?.trim();
|
||||
if (!trimmed) {
|
||||
throw new Error('URL is required');
|
||||
}
|
||||
const entry = cache.get(trimmed);
|
||||
if (entry && entry.expiresAt > Date.now()) {
|
||||
return entry.data;
|
||||
}
|
||||
const res = await fetch(trimmed, {
|
||||
headers: { Accept: 'application/json' },
|
||||
signal: AbortSignal.timeout(15000),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
cache.set(trimmed, { data, expiresAt: Date.now() + ttlMs });
|
||||
return data;
|
||||
}
|
||||
|
||||
export function clearRemoteJsonCache(): void {
|
||||
cache.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user