···
import { Client, CredentialManager } from "@atcute/client";
+
import { DidDocument, getPdsEndpoint } from "@atcute/identity";
import { lexiconDoc } from "@atcute/lexicon-doc";
import { RecordValidator } from "@atcute/lexicon-doc/validations";
+
import { FailedLexiconResolutionError, ResolvedSchema } from "@atcute/lexicon-resolver";
import { ActorIdentifier, is, Nsid } from "@atcute/lexicons";
import { AtprotoDid, Did, isNsid } from "@atcute/lexicons/syntax";
import { verifyRecord } from "@atcute/repo";
···
import { pds } from "../components/navbar.jsx";
import { addNotification, removeNotification } from "../components/notification.jsx";
import Tooltip from "../components/tooltip.jsx";
+
resolveLexiconAuthority,
+
} from "../utils/api.js";
import { AtUri, uriTemplates } from "../utils/templates.js";
import { lexicons } from "../utils/types/lexicons.js";
+
const authorityCache = new Map<string, Promise<AtprotoDid>>();
+
const documentCache = new Map<string, Promise<DidDocument>>();
+
const schemaCache = new Map<string, Promise<unknown>>();
+
const getAuthoritySegment = (nsid: string): string => {
+
const segments = nsid.split(".");
+
return segments.slice(0, -1).join(".");
+
const resolveSchema = async (authority: AtprotoDid, nsid: Nsid): Promise<unknown> => {
+
const cacheKey = `${authority}:${nsid}`;
+
let cachedSchema = schemaCache.get(cacheKey);
+
const schemaPromise = (async () => {
+
let didDocPromise = documentCache.get(authority);
+
didDocPromise = didDocumentResolver.resolve(authority);
+
documentCache.set(authority, didDocPromise);
+
const didDocument = await didDocPromise;
+
const pdsEndpoint = getPdsEndpoint(didDocument);
+
throw new FailedLexiconResolutionError(nsid, {
+
cause: new TypeError(`no pds service in did document; did=${authority}`),
+
const rpc = new Client({ handler: new CredentialManager({ service: pdsEndpoint }) });
+
const response = await rpc.get("com.atproto.repo.getRecord", {
+
collection: "com.atproto.lexicon.schema",
+
throw new Error(`got http ${response.status}`);
+
return response.data.value;
+
schemaCache.set(cacheKey, schemaPromise);
+
return await schemaPromise;
+
schemaCache.delete(cacheKey);
const extractRefs = (obj: any): Nsid[] => {
const refs: Set<string> = new Set();
···
const fetchPromise = (async () => {
+
let authority: AtprotoDid | undefined;
+
const authoritySegment = getAuthoritySegment(nsid);
+
let authorityPromise = authorityCache.get(authoritySegment);
+
if (!authorityPromise) {
+
authorityPromise = resolveLexiconAuthority(nsid);
+
authorityCache.set(authoritySegment, authorityPromise);
+
authority = await authorityPromise;
+
const schema = await resolveSchema(authority, nsid);
+
resolved.set(nsid, schema);
+
const refs = extractRefs(schema);
···
console.error(`Failed to resolve lexicon ${nsid}:`, err);
+
authorityCache.delete(authoritySegment);
+
documentCache.delete(authority);
···
const lexiconDocs = Object.fromEntries(resolved);
+
console.log(lexiconDocs);
const validator = new RecordValidator(lexiconDocs, params.collection as Nsid);