Static site hosting via tangled
1const PDS_SERVICE_ID = "#atproto_pds";
2
3async function getServiceEndpointFromDidDoc(didDoc) {
4 const service = didDoc.service.find((s) => s.id === PDS_SERVICE_ID);
5 if (!service) {
6 throw new Error(
7 `No PDS service found in DID doc ${JSON.stringify(didDoc)}`
8 );
9 }
10 return service.serviceEndpoint;
11}
12
13export async function resolveHandle(handle) {
14 const params = new URLSearchParams({
15 handle,
16 });
17 const res = await fetch(
18 "https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?" +
19 params.toString()
20 );
21 const data = await res.json();
22 return data.did;
23}
24
25async function resolveDid(did) {
26 if (did.startsWith("did:plc:")) {
27 const res = await fetch(`https://plc.directory/${encodeURIComponent(did)}`);
28 const didDoc = await res.json();
29 return didDoc;
30 } else if (did.startsWith("did:web:")) {
31 const website = did.split(":")[2];
32 const res = await fetch(`https://${website}/.well-known/did.json`);
33 const didDoc = await res.json();
34 return didDoc;
35 } else {
36 throw new Error(`Unsupported DID: ${did}`);
37 }
38}
39
40async function getServiceEndpointForDid(did) {
41 const didDoc = await resolveDid(did);
42 return getServiceEndpointFromDidDoc(didDoc);
43}
44
45export async function listRecords({ did, collection }) {
46 const serviceEndpoint = await getServiceEndpointForDid(did);
47 let cursor = "";
48 const records = [];
49 do {
50 const res = await fetch(
51 `${serviceEndpoint}/xrpc/com.atproto.repo.listRecords?repo=${did}&collection=${collection}&limit=100&cursor=${cursor}`
52 );
53 const data = await res.json();
54 const recordsWithAuthor = data.records.map((record) => {
55 return {
56 ...record,
57 author: did,
58 };
59 });
60 records.push(...recordsWithAuthor);
61 cursor = data.cursor;
62 } while (cursor);
63 return records;
64}