| 1 | /** |
| 2 | * Names and faces for member keys (`user:<id>`, `agent:<id>`): comment |
| 3 | * authors and history. Asked of the site once per key per tab. |
| 4 | */ |
| 5 | import type { Result } from "@g1t/contracts"; |
| 6 | |
| 7 | /** Someone by member key, as the site names them. */ |
| 8 | export type Who = { key: string; kind: "user" | "agent"; id: string; name: string; display_name: string; avatar: string | null; avatar_seed: string | null }; |
| 9 | |
| 10 | const known = new Map<string, Who>(); |
| 11 | |
| 12 | /** Names and faces for member keys (`user:<id>`, `agent:<id>`), asked of the site once each. */ |
| 13 | export async function whoAre(slug: string, keys: string[]): Promise<Map<string, Who>> { |
| 14 | const wanted = [...new Set(keys)].filter((k) => !known.has(k) && /^(user|agent):/.test(k)); |
| 15 | if (wanted.length) { |
| 16 | try { |
| 17 | const r = await fetch(`/${slug}/-/docs/api?who=${encodeURIComponent(wanted.join(","))}`, { headers: { accept: "application/json" } }); |
| 18 | const result = (await r.json()) as Result<Who[]>; |
| 19 | if (result.ok) for (const w of result.value) known.set(w.key, w); |
| 20 | } catch { |
| 21 | // Shown as "Someone" until asked again. |
| 22 | } |
| 23 | } |
| 24 | return new Map(keys.map((k) => [k, known.get(k)!]).filter(([, w]) => !!w) as [string, Who][]); |
| 25 | } |
| 26 |