Something went wrong. Try again.
tiny REST API that resolves AT Protocol Lexicon schemas from NSIDs lex.desertthunder.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081import type { ApiErrorCode, DnsJsonResponse, TxtRecord } from './types';
export class DnsLookupError extends Error { constructor(message: string) { super(message); this.name = 'DnsLookupError'; }}
function decodeTxtData(value: string): string { const parts = value.match(/"((?:\\"|[^"])*)"/g); if (parts === null) { return value; }
return parts.map((part) => part.slice(1, -1).replaceAll('\\"', '"')).join('');}
export async function lookupTxtRecords(endpoint: string, name: string): Promise<TxtRecord[]> { const url = new URL(endpoint); url.searchParams.set('name', name); url.searchParams.set('type', 'TXT');
const response = await fetch(url, { headers: { accept: 'application/dns-json' } });
if (!response.ok) { throw new DnsLookupError(`DNS lookup failed with ${response.status} ${response.statusText}`); }
const body = (await response.json()) as DnsJsonResponse; if (body.Status !== 0) { return []; }
return (body.Answer ?? []) .filter((answer) => answer.type === 16) .map((answer) => { const record: TxtRecord = { name: answer.name, data: decodeTxtData(answer.data) };
if (answer.TTL !== undefined) { record.ttl = answer.TTL; }
return record; });}
export function findLexiconDid(records: TxtRecord[]): string | null { for (const record of records) { const value = record.data.trim(); if (!value.startsWith('did=')) { continue; }
const did = value.slice('did='.length); if (/^did:[a-z0-9]+:[A-Za-z0-9._:%-]+$/.test(did)) { return did; } }
return null;}
export function jsonResponse(body: unknown, init: ResponseInit = {}): Response { const headers = new Headers(init.headers); headers.set('content-type', 'application/json; charset=utf-8');
return Response.json(body, { ...init, headers });}
export function htmlResponse(body: string, init: ResponseInit = {}): Response { const headers = new Headers(init.headers); headers.set('content-type', 'text/html; charset=utf-8');
return new Response(body, { ...init, headers });}
export function apiError(status: number, code: ApiErrorCode, message: string): Response { return jsonResponse({ error: { code, message } }, { status });}