knowledge 0.12.1

The launcher and updater for Knowledge.Dev Workbench
Documentation
use crate::USER_AGENT;
use crate::app_info::{WORKBENCH_DOWNLOADS_URL, WORKBENCH_LATEST_URL};
use crate::built_info;
use crate::download::download_binary;
use anyhow::{Context, Result};
use reqwest::Client;
use semver::Version;
use serde::Deserialize;
use std::path::Path;

pub struct WorkbenchApi {
    client: Client,
}

impl WorkbenchApi {
    pub fn new() -> Self {
        Self {
            client: Client::new(),
        }
    }

    async fn latest_manifest(&mut self) -> Result<LatestManifest> {
        let manifest = self
            .client
            .get(WORKBENCH_LATEST_URL)
            .header(reqwest::header::USER_AGENT, USER_AGENT)
            .send()
            .await?
            .error_for_status()?
            .text()
            .await?;

        toml::from_str(&manifest).context("Failed to parse workbench latest manifest")
    }

    pub async fn latest_release(&mut self) -> Result<Release> {
        let manifest = self.latest_manifest().await?;
        Ok(Release {
            version: manifest.version,
        })
    }

    pub async fn download_binary(&mut self, url: &str, dest: &Path) -> Result<()> {
        download_binary(&self.client, url, dest).await
    }
}

#[derive(Debug, Deserialize)]
struct LatestManifest {
    pub version: Version,
}

#[derive(Debug)]
pub struct Release {
    pub version: Version,
}

impl Release {
    pub fn get_asset_url(&self) -> String {
        let asset_name = asset_name();
        format!("{WORKBENCH_DOWNLOADS_URL}/{}/{}", self.version, asset_name)
    }
}

fn asset_name() -> String {
    let os = built_info::CFG_OS;
    let arch = built_info::CFG_TARGET_ARCH;
    let suffix = match (os, arch) {
        ("macos", "aarch64") => "macos-arm",
        ("macos", "x86_64") => "macos-intel",
        ("windows", "x86_64") => "windows-x64.exe",
        ("linux", "x86_64") => "linux-x64",
        _ => "linux-x64",
    };
    format!("workbench-{suffix}")
}