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}