forked from Vero-protocol/vero-guardian-dashboard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprofileClient.ts
More file actions
73 lines (64 loc) · 2.22 KB
/
Copy pathprofileClient.ts
File metadata and controls
73 lines (64 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const CACHE_KEY = 'contrib_profiles_v1';
const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
export type ContributorProfile = {
displayName?: string;
avatarUrl?: string;
};
type CacheRecord = {
fetchedAt: number;
data: Record<string, ContributorProfile>;
};
function readCache(): CacheRecord | null {
try {
const raw = localStorage.getItem(CACHE_KEY);
if (!raw) return null;
const parsed = JSON.parse(raw) as CacheRecord;
if (!parsed || typeof parsed.fetchedAt !== 'number' || typeof parsed.data !== 'object') return null;
if (Date.now() - parsed.fetchedAt > CACHE_TTL_MS) {
localStorage.removeItem(CACHE_KEY);
return null;
}
return parsed;
} catch {
return null;
}
}
function writeCache(data: Record<string, ContributorProfile>): void {
try {
const record: CacheRecord = { fetchedAt: Date.now(), data };
localStorage.setItem(CACHE_KEY, JSON.stringify(record));
} catch {
// ignore
}
}
/**
* Fetch contributor profiles from a configurable service.
* The service base URL should be set in `NEXT_PUBLIC_PROFILE_SERVICE_URL`.
* Expected optional endpoint: `${base}/profiles?ids=id1,id2` returning
* `{ [id]: { displayName?: string, avatarUrl?: string } }`.
* If no service is configured, resolves to empty results.
*/
export async function fetchContributorProfiles(ids: string[]): Promise<Record<string, ContributorProfile>> {
if (ids.length === 0) return {};
const cached = readCache();
const result: Record<string, ContributorProfile> = { ...(cached?.data ?? {}) };
const missing = ids.filter((id) => !(id in result));
const base = typeof process !== 'undefined' ? (process.env.NEXT_PUBLIC_PROFILE_SERVICE_URL as string | undefined) : undefined;
if (!base || missing.length === 0) {
return result;
}
try {
const url = new URL('/profiles', base);
url.searchParams.set('ids', missing.join(','));
const resp = await fetch(url.toString());
if (!resp.ok) return result;
const body = (await resp.json()) as Record<string, ContributorProfile>;
for (const id of Object.keys(body)) {
result[id] = body[id] ?? {};
}
writeCache(result);
} catch {
// ignore network failures and return whatever we have
}
return result;
}