This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / api / identity.ts
1.6 kB 59 lines
1import type { BobbinContext, XrpcRequestInit } from "./client"; 2import { jsonGet } from "./_request"; 3 4export interface MiniDoc { 5 did: string; 6 handle: string; 7 pds?: string; 8} 9 10export const resolveMiniDoc = ( 11 ctx: BobbinContext, 12 identifier: string, 13 init?: XrpcRequestInit 14): Promise<MiniDoc> => 15 jsonGet<MiniDoc>(ctx, "com.bad-example.identity.resolveMiniDoc", { identifier }, init); 16 17// did/handle cache with in-flight de-dupe. 18export class IdentityCache { 19 readonly #ctx: BobbinContext; 20 readonly #byDid = new Map<string, MiniDoc>(); 21 readonly #byHandle = new Map<string, MiniDoc>(); 22 readonly #inflight = new Map<string, Promise<MiniDoc>>(); 23 24 constructor(ctx: BobbinContext) { 25 this.#ctx = ctx; 26 } 27 28 prime(doc: MiniDoc): void { 29 this.#byDid.set(doc.did, doc); 30 this.#byHandle.set(doc.handle, doc); 31 } 32 33 didFor(handle: string): string | undefined { 34 return this.#byHandle.get(handle)?.did; 35 } 36 37 handleFor(did: string): string | undefined { 38 return this.#byDid.get(did)?.handle; 39 } 40 41 resolve(identifier: string, init?: XrpcRequestInit): Promise<MiniDoc> { 42 const cached = identifier.startsWith("did:") 43 ? this.#byDid.get(identifier) 44 : this.#byHandle.get(identifier); 45 if (cached) return Promise.resolve(cached); 46 47 const existing = this.#inflight.get(identifier); 48 if (existing) return existing; 49 50 const pending = resolveMiniDoc(this.#ctx, identifier, init) 51 .then((doc) => { 52 this.prime(doc); 53 return doc; 54 }) 55 .finally(() => this.#inflight.delete(identifier)); 56 this.#inflight.set(identifier, pending); 57 return pending; 58 } 59}