Something went wrong. Try again.
Web frontend and supporting services for lance.blue
Something went wrong. Try again.
3.0 kB · 79 lines
TypeScript
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980/** * Finding the server that holds an account's data. * * A DID document says where a repository lives, and reading a record or a * blob out of that repository needs no account and no token — a PDS answers * both to anyone, with `access-control-allow-origin: *`. So anything this site * only reads, it reads straight from the source rather than through our API. * * The alternative, asking an appview, is one fewer request and worse: it only * knows accounts it has indexed, and its CDN sends no CORS header at all, so a * canvas that draws from it cannot be read back. */
/** * What a DID document says that anything here reads. * * `alsoKnownAs` is the account's own claim to a handle, and it is only a * claim: identity.ts is what checks the handle resolves back to this DID * before anyone is shown it. */export interface DidDocument { readonly alsoKnownAs?: unknown; readonly service?: { id?: string; serviceEndpoint?: unknown }[];}
const cache = new Map<string, Promise<DidDocument>>();
/** * A DID's document. Cached: it does not move often, and both the server it * names and the handle it claims are read off the one fetch. */export function didDocument(did: string): Promise<DidDocument> { const known = cache.get(did); if (known) return known; const pending = lookup(did).catch((error: unknown) => { // A failure must not be remembered, or one flaky lookup breaks the page // until it is reloaded. cache.delete(did); throw error; }); cache.set(did, pending); return pending;}
/** The PDS endpoint for a DID. */export async function resolvePds(did: string): Promise<string> { const doc = await didDocument(did); const endpoint = doc.service?.find((s) => s.id?.endsWith("#atproto_pds"), )?.serviceEndpoint; if (typeof endpoint !== "string") { throw new Error("Your account's identity names no server."); } return endpoint.replace(/\/+$/, "");}
async function lookup(did: string): Promise<DidDocument> { let docUrl: string; if (did.startsWith("did:plc:")) { docUrl = `https://plc.directory/${encodeURIComponent(did)}`; } else if (did.startsWith("did:web:")) { // did:web:example.com is the well-known path; extra colon-separated // segments are a path instead. A port arrives percent-encoded. const [host, ...path] = did.slice("did:web:".length).split(":"); const where = path.length ? `/${path.join("/")}` : "/.well-known"; docUrl = `https://${decodeURIComponent(host ?? "")}${where}/did.json`; } else { throw new Error("Your account's identity is not one we can read."); }
const response = await fetch(docUrl); if (!response.ok) throw new Error("Your account's identity did not resolve."); return (await response.json()) as DidDocument;}
/** The public URL of a blob in someone's repository. */export function blobUrl(pds: string, did: string, cid: string): string { return `${pds}/xrpc/com.atproto.sync.getBlob?did=${encodeURIComponent(did)}&cid=${encodeURIComponent(cid)}`;}