| + |
use std::collections::BTreeMap;
|
| + |
|
| + |
use radicle::identity::Did;
|
| + |
use radicle::node::AliasStore;
|
| + |
use radicle_artifact::share::cid_utils;
|
| + |
use serde::Serialize;
|
| + |
use ts_rs::TS;
|
| + |
|
| + |
use crate::cobs;
|
| + |
|
| + |
#[derive(Clone, Serialize, TS, Debug)]
|
| + |
#[serde(rename_all = "camelCase")]
|
| + |
#[ts(export)]
|
| + |
#[ts(export_to = "cob/release/")]
|
| + |
pub struct Release {
|
| + |
#[ts(as = "String")]
|
| + |
pub id: radicle_artifact::ReleaseId,
|
| + |
#[ts(as = "String")]
|
| + |
pub oid: radicle::git::Oid,
|
| + |
#[ts(type = "number")]
|
| + |
pub timestamp: u64,
|
| + |
pub artifacts: Vec<Artifact>,
|
| + |
}
|
| + |
|
| + |
#[derive(Clone, Serialize, TS, Debug)]
|
| + |
#[serde(rename_all = "camelCase")]
|
| + |
#[ts(export)]
|
| + |
#[ts(export_to = "cob/release/")]
|
| + |
pub struct Artifact {
|
| + |
pub cid: String,
|
| + |
pub name: String,
|
| + |
pub kind: ArtifactKind,
|
| + |
pub author: cobs::Author,
|
| + |
pub locations: Vec<Location>,
|
| + |
pub attestations: Vec<cobs::Author>,
|
| + |
pub redactions: Vec<Redaction>,
|
| + |
/// True when at least one of the location URLs we (the local DID) wrote
|
| + |
/// to this artifact uses the `iroh://` scheme — i.e. we are advertising
|
| + |
/// ourselves as an iroh provider for it.
|
| + |
pub shared_by_us: bool,
|
| + |
}
|
| + |
|
| + |
#[derive(Clone, Serialize, TS, Debug)]
|
| + |
#[serde(rename_all = "camelCase")]
|
| + |
#[ts(export)]
|
| + |
#[ts(export_to = "cob/release/")]
|
| + |
pub enum ArtifactKind {
|
| + |
Blob,
|
| + |
Collection,
|
| + |
Unknown,
|
| + |
}
|
| + |
|
| + |
#[derive(Clone, Serialize, TS, Debug)]
|
| + |
#[serde(rename_all = "camelCase")]
|
| + |
#[ts(export)]
|
| + |
#[ts(export_to = "cob/release/")]
|
| + |
pub struct Location {
|
| + |
pub peer: cobs::Author,
|
| + |
pub urls: Vec<String>,
|
| + |
}
|
| + |
|
| + |
#[derive(Clone, Serialize, TS, Debug)]
|
| + |
#[serde(rename_all = "camelCase")]
|
| + |
#[ts(export)]
|
| + |
#[ts(export_to = "cob/release/")]
|
| + |
pub struct Redaction {
|
| + |
pub peer: cobs::Author,
|
| + |
pub reason: String,
|
| + |
}
|
| + |
|
| + |
impl Release {
|
| + |
pub fn new(
|
| + |
id: radicle_artifact::ReleaseId,
|
| + |
release: &radicle_artifact::Release,
|
| + |
our_did: &Did,
|
| + |
aliases: &impl AliasStore,
|
| + |
) -> Self {
|
| + |
let artifacts = release
|
| + |
.artifacts()
|
| + |
.iter()
|
| + |
.map(|(cid, artifact)| Artifact::new(cid, artifact, our_did, aliases))
|
| + |
.collect();
|
| + |
|
| + |
Self {
|
| + |
id,
|
| + |
oid: *release.oid(),
|
| + |
timestamp: release.timestamp(),
|
| + |
artifacts,
|
| + |
}
|
| + |
}
|
| + |
}
|
| + |
|
| + |
impl Artifact {
|
| + |
pub fn new(
|
| + |
cid: &cid::Cid,
|
| + |
artifact: &radicle_artifact::Artifact,
|
| + |
our_did: &Did,
|
| + |
aliases: &impl AliasStore,
|
| + |
) -> Self {
|
| + |
let kind = match cid_utils::artifact_kind(cid) {
|
| + |
Ok(cid_utils::ArtifactKind::Blob) => ArtifactKind::Blob,
|
| + |
Ok(cid_utils::ArtifactKind::Collection) => ArtifactKind::Collection,
|
| + |
Err(_) => ArtifactKind::Unknown,
|
| + |
};
|
| + |
|
| + |
let locations = artifact
|
| + |
.locations()
|
| + |
.iter()
|
| + |
.map(|(did, urls)| Location {
|
| + |
peer: cobs::Author::new(did, aliases),
|
| + |
urls: urls.iter().map(|u| u.to_string()).collect(),
|
| + |
})
|
| + |
.collect();
|
| + |
|
| + |
let attestations = artifact
|
| + |
.attestations()
|
| + |
.iter()
|
| + |
.map(|did| cobs::Author::new(did, aliases))
|
| + |
.collect();
|
| + |
|
| + |
let redactions = artifact
|
| + |
.redactions()
|
| + |
.iter()
|
| + |
.map(|(did, reason)| Redaction {
|
| + |
peer: cobs::Author::new(did, aliases),
|
| + |
reason: reason.clone(),
|
| + |
})
|
| + |
.collect();
|
| + |
|
| + |
let shared_by_us = artifact
|
| + |
.locations_of(our_did)
|
| + |
.is_some_and(|urls| urls.iter().any(|u| u.scheme() == "iroh"));
|
| + |
|
| + |
Self {
|
| + |
cid: cid.to_string(),
|
| + |
name: artifact.name().to_string(),
|
| + |
kind,
|
| + |
author: cobs::Author::new(artifact.author(), aliases),
|
| + |
locations,
|
| + |
attestations,
|
| + |
redactions,
|
| + |
shared_by_us,
|
| + |
}
|
| + |
}
|
| + |
}
|
| + |
|
| + |
// Quiet the dead-code warning: this map alias keeps the upstream type names
|
| + |
// aligned with the DTO at a glance, and may be used later by trait helpers.
|
| + |
#[allow(dead_code)]
|
| + |
pub(crate) type LocationMap = BTreeMap<Did, std::collections::BTreeSet<url::Url>>;
|