use serde::Deserialize;
use std::collections::HashMap;
use super::Tag;
use crate::sources::data::NpmSource;
use crate::{Error, Result};
#[derive(Debug, Clone, Deserialize)]
struct Response {
versions: HashMap<String, serde_json::Value>,
time: HashMap<String, chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Entry {
pub version: String,
pub created: chrono::DateTime<chrono::Utc>,
}
pub async fn fetch_entries(index: &str) -> Result<Vec<Entry>> {
let res = crate::util::http::client()?.get(index).send().await?;
let data: Response = serde_json::from_str(&crate::util::http::body(res).await?)?;
let entries = data
.versions
.keys()
.filter_map(|version| Some((version, data.time.get(version)?)))
.map(|(version, date)| Entry {
version: version.clone(),
created: *date,
})
.collect();
Ok(entries)
}
pub async fn list_tags(source: &NpmSource) -> Result<Vec<Tag>> {
let repo_url = if let Some(url) = source.url().as_str().strip_prefix("npm+") {
url.to_string()
} else if let Some(package_name) = source.url().host_str() {
format!("https://registry.npmjs.org/{package_name}")
} else {
return Err(Error::NpmRegistryURL(source.url().to_string()));
};
let entries = fetch_entries(&repo_url).await?;
Ok(entries
.into_iter()
.map(|entry| Tag::new(entry.version, entry.created))
.collect())
}