import { ok } from '@atcute/client'; import type { Did, Nsid, ResourceUri } from '@atcute/lexicons/syntax'; import { appviewBulkRecords, appviewFallback, type AppviewRecordView, } from './appview'; import { getRpc } from './client'; import { type BacklinkRecordRef, type HydratedRecord, parseAtUri, } from './records'; import { resolveActor, resolveActorForDisplay } from './identity'; export const appviewRecordToHydrated = async (record: AppviewRecordView): Promise> => { const parsed = parseAtUri(record.uri); const author = await resolveActorForDisplay(parsed.did); return { author, collection: parsed.collection, rkey: parsed.rkey, uri: record.uri, cid: record.cid ?? undefined, value: record.value, }; }; export const hydrateRecord = async ( ref: BacklinkRecordRef | { did: Did; collection: Nsid; rkey: string }, ): Promise> => { const actor = await resolveActor(ref.did); const record = await ok( getRpc(actor.pds).get('com.atproto.repo.getRecord', { params: { repo: ref.did, collection: ref.collection, rkey: ref.rkey, }, }), ); return { author: actor, collection: ref.collection, rkey: ref.rkey, uri: record.uri, cid: record.cid, value: record.value as T, }; }; export const fetchRecordValue = async ( ref: BacklinkRecordRef | { did: Did; collection: Nsid; rkey: string }, ): Promise => { const actor = await resolveActor(ref.did); const record = await ok( getRpc(actor.pds).get('com.atproto.repo.getRecord', { params: { repo: ref.did, collection: ref.collection, rkey: ref.rkey, }, }), ); return record.value as T; }; export const hydrateBacklinks = async (refs: BacklinkRecordRef[]): Promise>> => Promise.all(refs.map((ref) => hydrateRecord(ref))); const backlinkRefToUri = (ref: BacklinkRecordRef): ResourceUri => `at://${ref.did}/${ref.collection}/${ref.rkey}` as ResourceUri; export const hydrateBacklinksFromAppview = async ( refs: BacklinkRecordRef[], nsid: string, paramName: string, ): Promise>> => appviewFallback( async () => { const records = await appviewBulkRecords( nsid, paramName, refs.map(backlinkRefToUri), ); return Promise.all(records.map((record) => appviewRecordToHydrated(record))); }, () => hydrateBacklinks(refs), );