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 61 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 INVALID_HANDLE = "handle.invalid"; 11 12export const resolveMiniDoc = ( 13 ctx: BobbinContext, 14 identifier: string, 15 init?: XrpcRequestInit 16): Promise<MiniDoc> => 17 jsonGet<MiniDoc>(ctx, "com.bad-example.identity.resolveMiniDoc", { identifier }, init); 18 19// did/handle cache with in-flight de-dupe. 20export class IdentityCache { 21 readonly #ctx: BobbinContext; 22 readonly #byDid = new Map<string, MiniDoc>(); 23 readonly #byHandle = new Map<string, MiniDoc>(); 24 readonly #inflight = new Map<string, Promise<MiniDoc>>(); 25 26 constructor(ctx: BobbinContext) { 27 this.#ctx = ctx; 28 } 29 30 prime(doc: MiniDoc): void { 31 this.#byDid.set(doc.did, doc); 32 this.#byHandle.set(doc.handle, doc); 33 } 34 35 didFor(handle: string): string | undefined { 36 return this.#byHandle.get(handle)?.did; 37 } 38 39 handleFor(did: string): string | undefined { 40 return this.#byDid.get(did)?.handle; 41 } 42 43 resolve(identifier: string, init?: XrpcRequestInit): Promise<MiniDoc> { 44 const cached = identifier.startsWith("did:") 45 ? this.#byDid.get(identifier) 46 : this.#byHandle.get(identifier); 47 if (cached) return Promise.resolve(cached); 48 49 const existing = this.#inflight.get(identifier); 50 if (existing) return existing; 51 52 const pending = resolveMiniDoc(this.#ctx, identifier, init) 53 .then((doc) => { 54 this.prime(doc); 55 return doc; 56 }) 57 .finally(() => this.#inflight.delete(identifier)); 58 this.#inflight.set(identifier, pending); 59 return pending; 60 } 61}