use jacquard_common::{
Data,
types::{cid::Cid, nsid::Nsid},
};
use smol_str::SmolStr;
use super::*;
#[derive(Deserialize)]
pub struct ListRecords {
pub collection: Nsid,
pub cursor: Option<SmolStr>,
pub limit: Option<i64>,
pub repo: AtIdentifier,
pub reverse: Option<bool>,
}
#[derive(Serialize)]
pub struct RepoRecord {
pub uri: AtUri,
pub cid: Cid,
pub value: Data,
}
#[derive(Serialize)]
pub struct ListRecordsOutput {
#[serde(skip_serializing_if = "Option::is_none")]
pub cursor: Option<SmolStr>,
pub records: Vec<RepoRecord>,
}
pub async fn handle(
State(hydrant): State<Hydrant>,
ExtractXrpc(req): ExtractXrpc<ListRecords>,
) -> XrpcResult<Json<ListRecordsOutput>> {
let limit = req.limit.unwrap_or(50).min(100) as usize;
let reverse = req.reverse.unwrap_or(false);
let cursor = req.cursor.as_deref();
let repo = hydrant
.repos
.resolve(&req.repo)
.await
.map_err(internal_error)?;
// the lexicon names no errors, so this is the InvalidRequest a pds answers for a repo it
// won't serve
if let Some(reason) = unavailable(&repo).await.map_err(internal_error)? {
return Err(bad_request(reason));
}
let list = repo
.list_records(req.collection.as_str(), limit, reverse, cursor)
.await
.map_err(bad_request)?;
let records = list
.records
.into_iter()
.filter_map(|r| {
let uri = AtUri::from_parts_owned(
repo.did.as_str(),
req.collection.as_str(),
r.rkey.as_str(),
)
.ok()?;
Some(RepoRecord {
uri,
cid: r.cid,
value: r.value,
})
})
.collect();
Ok(Json(ListRecordsOutput {
cursor: list.cursor.map(|r| r.to_smolstr()),
records,
}))
}