use super::{IndexError, PackageIndex, PackageMeta, VersionMeta};
pub struct Clojars;
impl Clojars {
const API_BASE: &'static str = "https://clojars.org/api";
}
impl PackageIndex for Clojars {
fn ecosystem(&self) -> &'static str {
"clojars"
}
fn display_name(&self) -> &'static str {
"Clojars (Clojure)"
}
fn fetch(&self, name: &str) -> Result<PackageMeta, IndexError> {
let url = format!("{}/artifacts/{}", Self::API_BASE, name);
let response: serde_json::Value = ureq::get(&url)
.call()
.map_err(|_| IndexError::NotFound(name.to_string()))?
.into_json()?;
let license = response["licenses"]
.as_array()
.and_then(|arr| arr.first())
.and_then(|l| l["name"].as_str())
.map(String::from);
let maintainers: Vec<String> = response["user"]
.as_str()
.map(|u| vec![u.to_string()])
.unwrap_or_default();
Ok(PackageMeta {
name: format!(
"{}/{}",
response["group_name"].as_str().unwrap_or(""),
response["jar_name"].as_str().unwrap_or(name)
),
version: response["latest_version"]
.as_str()
.unwrap_or("unknown")
.to_string(),
description: response["description"].as_str().map(String::from),
homepage: response["homepage"].as_str().map(String::from),
repository: response["scm"]
.get("url")
.and_then(|u| u.as_str())
.map(String::from),
license,
binaries: Vec::new(),
keywords: Vec::new(),
maintainers,
published: None,
downloads: response["downloads"].as_u64(),
archive_url: None,
checksum: None,
extra: Default::default(),
})
}
fn fetch_versions(&self, name: &str) -> Result<Vec<VersionMeta>, IndexError> {
let url = format!("{}/artifacts/{}", Self::API_BASE, name);
let response: serde_json::Value = ureq::get(&url)
.call()
.map_err(|_| IndexError::NotFound(name.to_string()))?
.into_json()?;
let versions = response["recent_versions"]
.as_array()
.ok_or_else(|| IndexError::NotFound(name.to_string()))?;
Ok(versions
.iter()
.filter_map(|v| {
Some(VersionMeta {
version: v["version"].as_str()?.to_string(),
released: None,
yanked: false,
})
})
.collect())
}
fn search(&self, query: &str) -> Result<Vec<PackageMeta>, IndexError> {
let url = format!("https://clojars.org/search?q={}&format=json", query);
let response: serde_json::Value = ureq::get(&url).call()?.into_json()?;
let results = response["results"]
.as_array()
.ok_or_else(|| IndexError::Parse("Invalid search response".into()))?;
Ok(results
.iter()
.filter_map(|pkg| {
Some(PackageMeta {
name: format!(
"{}/{}",
pkg["group_name"].as_str()?,
pkg["jar_name"].as_str()?
),
version: pkg["version"].as_str().unwrap_or("unknown").to_string(),
description: pkg["description"].as_str().map(String::from),
homepage: None,
repository: None,
license: None,
binaries: Vec::new(),
keywords: Vec::new(),
maintainers: Vec::new(),
published: None,
downloads: None,
archive_url: None,
checksum: None,
extra: Default::default(),
})
})
.collect())
}
}