atproto user agency toolkit for individuals and groups
8
fork

Configure Feed

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

at main 88 lines 2.0 kB view raw
1/** 2 * DID resolution for Node.js 3 */ 4 5import { 6 CompositeDidDocumentResolver, 7 PlcDidDocumentResolver, 8 WebDidDocumentResolver, 9} from "@atcute/identity-resolver"; 10import type { DidDocument } from "@atcute/identity"; 11import type { Did } from "@atcute/lexicons/syntax"; 12import type { DidCache } from "./did-cache.js"; 13 14const PLC_DIRECTORY = "https://plc.directory"; 15const TIMEOUT_MS = 3000; 16 17export interface DidResolverOpts { 18 plcUrl?: string; 19 timeout?: number; 20 didCache?: DidCache; 21} 22 23export type { DidDocument }; 24 25export class DidResolver { 26 private resolver: CompositeDidDocumentResolver<"plc" | "web">; 27 private timeout: number; 28 private cache?: DidCache; 29 30 constructor(opts: DidResolverOpts = {}) { 31 this.timeout = opts.timeout ?? TIMEOUT_MS; 32 this.cache = opts.didCache; 33 34 this.resolver = new CompositeDidDocumentResolver({ 35 methods: { 36 plc: new PlcDidDocumentResolver({ 37 apiUrl: opts.plcUrl ?? PLC_DIRECTORY, 38 }), 39 web: new WebDidDocumentResolver(), 40 }, 41 }); 42 } 43 44 async resolve(did: string): Promise<DidDocument | null> { 45 if (this.cache) { 46 const cached = await this.cache.checkCache(did); 47 if (cached && !cached.expired) { 48 if (cached.stale) { 49 this.cache.refreshCache( 50 did, 51 () => this.resolveNoCache(did), 52 cached, 53 ); 54 } 55 return cached.doc; 56 } 57 } 58 59 const doc = await this.resolveNoCache(did); 60 61 if (doc && this.cache) { 62 await this.cache.cacheDid(did, doc); 63 } else if (!doc && this.cache) { 64 await this.cache.clearEntry(did); 65 } 66 67 return doc; 68 } 69 70 private async resolveNoCache(did: string): Promise<DidDocument | null> { 71 const controller = new AbortController(); 72 const timeoutId = setTimeout(() => controller.abort(), this.timeout); 73 74 try { 75 const doc = await this.resolver.resolve(did as Did<"plc" | "web">, { 76 signal: controller.signal, 77 }); 78 if (doc.id !== did) { 79 return null; 80 } 81 return doc; 82 } catch { 83 return null; 84 } finally { 85 clearTimeout(timeoutId); 86 } 87 } 88}