1use crate::RI_USER_AGENT;
2use anyhow::Error;
3use reqwest::{header::USER_AGENT, Client};
4use semver::Version;
5use serde::Deserialize;
6
7const BASE: &str = "https://crates.io/api/v1/crates/knowledge";
8
9pub struct CratesApi {
10 client: Client,
11}
12
13impl CratesApi {
14 pub fn new() -> Self {
15 Self {
16 client: Client::new(),
17 }
18 }
19
20 pub async fn fetch_info(&mut self) -> Result<CratesInfo, Error> {
21 let url = format!("{BASE}");
22 let info = self
23 .client
24 .get(&url)
25 .header(USER_AGENT, RI_USER_AGENT)
26 .send()
27 .await?
28 .json()
29 .await?;
30 Ok(info)
31 }
32
33 pub async fn latest_version(&mut self) -> Result<Version, Error> {
34 self.fetch_info()
35 .await?
36 .versions
37 .into_iter()
38 .next()
39 .map(|remote| remote.num)
40 .ok_or_else(|| Error::msg("No versions avaialble"))
41 }
42}
43
44#[derive(Debug, Deserialize)]
45pub struct CratesInfo {
46 pub versions: Vec<CratesVersion>,
47}
48
49#[derive(Debug, Deserialize)]
50pub struct CratesVersion {
51 pub num: Version,
52}