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 <T>(record: AppviewRecordView<T>): Promise<HydratedRecord<T>> => {
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 <T>(
ref: BacklinkRecordRef | { did: Did; collection: Nsid; rkey: string },
): Promise<HydratedRecord<T>> => {
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 <T>(
ref: BacklinkRecordRef | { did: Did; collection: Nsid; rkey: string },
): Promise<T> => {
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 <T>(refs: BacklinkRecordRef[]): Promise<Array<HydratedRecord<T>>> =>
Promise.all(refs.map((ref) => hydrateRecord<T>(ref)));
const backlinkRefToUri = (ref: BacklinkRecordRef): ResourceUri =>
`at://${ref.did}/${ref.collection}/${ref.rkey}` as ResourceUri;
export const hydrateBacklinksFromAppview = async <T>(
refs: BacklinkRecordRef[],
nsid: string,
paramName: string,
): Promise<Array<HydratedRecord<T>>> =>
appviewFallback(
async () => {
const records = await appviewBulkRecords<T>(
nsid,
paramName,
refs.map(backlinkRefToUri),
);
return Promise.all(records.map((record) => appviewRecordToHydrated(record)));
},
() => hydrateBacklinks<T>(refs),
);