Graphical PDS migrator for AT Protocol
1import { IdResolver } from "npm:@atproto/identity"; 2import { Did } from "npm:@atproto/api"; 3 4interface AtprotoData { 5 did: string; 6 signingKey: string; 7 handle: string; 8 pds: string; 9} 10 11const idResolver = createIdResolver(); 12export const resolver = createBidirectionalResolver(idResolver); 13 14export function createIdResolver() { 15 return new IdResolver(); 16} 17 18export interface BidirectionalResolver { 19 resolveDidToHandle(did: string): Promise<string>; 20 resolveDidsToHandles(dids: string[]): Promise<Record<string, string>>; 21 resolveDidToPdsUrl(did: string): Promise<string | undefined>; 22} 23 24export function createBidirectionalResolver(resolver: IdResolver) { 25 return { 26 async resolveDidToHandle(did: string): Promise<string> { 27 const didDoc = await resolver.did.resolveAtprotoData(did) as AtprotoData; 28 const resolvedHandle = await resolver.handle.resolve(didDoc.handle); 29 if (resolvedHandle === did) { 30 return didDoc.handle; 31 } 32 return did; 33 }, 34 35 async resolveHandleToDid(handle: string) { 36 return await resolver.handle.resolve(handle) as Did 37 }, 38 39 async resolveDidToPdsUrl(did: string): Promise<string | undefined> { 40 try { 41 const didDoc = await resolver.did.resolveAtprotoData( 42 did, 43 ) as AtprotoData; 44 return didDoc.pds; 45 } catch (err) { 46 console.error("Error resolving PDS URL:", err); 47 return undefined; 48 } 49 }, 50 51 async resolveDidsToHandles( 52 dids: string[], 53 ): Promise<Record<string, string>> { 54 const didHandleMap: Record<string, string> = {}; 55 const resolves = await Promise.all( 56 dids.map((did) => this.resolveDidToHandle(did).catch((_) => did)), 57 ); 58 for (let i = 0; i < dids.length; i++) { 59 didHandleMap[dids[i]] = resolves[i]; 60 } 61 return didHandleMap; 62 }, 63 }; 64}