resolveHandle
uses node:dns/promises
A handle's DID: from its DNS (_atproto.<handle>), else its HTTPS well-known (or the directory, if one is set).
import { directory, getJson, guardedFetch, HOSTNAME, isDid, Refused } from "#codebase/tcmts/atproto"; import dns from "node:dns/promises"; export async function resolveHandle(handle: string): Promise<string> { const h = handle.trim().replace(/^@/, "").toLowerCase(); if (!HOSTNAME.test(h)) throw new Refused(`${h} isn't a handle: a domain name, like alice.example.com`); const dir = directory(); if (dir) return ( await getJson<{ did: string }>( `${dir}/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(h)}`, ) ).did; const txt = await dns.resolveTxt(`_atproto.${h}`).catch(() => [] as string[][]); const fromDns = txt.map((t) => t.join("")).find((t) => t.startsWith("did=")); if (fromDns && isDid(fromDns.slice(4))) return fromDns.slice(4); // (a server the handle names: asked as any is that someone else names) const res = await guardedFetch(`https://${h}/.well-known/atproto-did`, `${h}'s server`).catch( () => undefined, ); const did = res?.ok ? (await res.text()).trim() : ""; if (isDid(did)) return did; throw new Refused(`no AT Protocol account has the handle ${h}`); }
uses
- tcmts.atproto.HOSTNAME
- tcmts.atproto.Refused
- tcmts.atproto.directory
- tcmts.atproto.getJson
- tcmts.atproto.guardedFetch
- tcmts.atproto.isDid