1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
pub mod config;

mod types;
mod util;

use clap::Parser;
use cmd::CliCommand;

mod cmd;

pub fn run() -> Result<(), anyhow::Error> {
    let args = Args::parse();
    args.cmd.run()
}

#[derive(clap::Parser, Debug)]
struct Args {
    #[clap(subcommand)]
    cmd: cmd::SubCmd,
}

#[derive(clap::Parser, Debug, Clone)]
pub struct ApiOpts {
    #[clap(long, env = "WASMER_TOKEN")]
    pub token: Option<String>,
    #[clap(long)]
    pub registry: Option<url::Url>,
}

impl ApiOpts {
    const DEV_REGISTRY: &'static str = "https://registry.wapm.dev/graphql";

    fn user_token_from_config(registry: &str) -> Result<Option<String>, anyhow::Error> {
        let wasmer_dir = wasmer_registry::WasmerConfig::get_wasmer_dir()
            .map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?;
        let config = wasmer_registry::WasmerConfig::from_file(&wasmer_dir)
            .map_err(|e| anyhow::anyhow!("could not load config {e}"))?;
        let token_opt = config
            .registry
            .tokens
            .iter()
            .find(|t| t.registry == registry)
            .map(|x| x.token.clone());
        Ok(token_opt)
    }

    fn token(&self) -> Result<Option<String>, anyhow::Error> {
        if let Some(token) = &self.token {
            Ok(Some(token.clone()))
        } else {
            let registry = self
                .registry
                .as_ref()
                .map(|x| x.as_str())
                .unwrap_or(Self::DEV_REGISTRY);
            Self::user_token_from_config(registry)
        }
    }

    fn client(&self) -> Result<wasmer_api::backend::BackendClient, anyhow::Error> {
        let client = wasmer_api::backend::BackendClient::new(Self::DEV_REGISTRY.parse().unwrap());

        let client = if let Some(token) = self.token()? {
            client.with_auth_token(token)
        } else {
            client
        };

        Ok(client)
    }
}

/// Formatting options for a single item.
#[derive(clap::Parser, Debug)]
pub struct ItemFormatOpts {
    /// Output format. (json, text)
    #[clap(short = 'f', long, default_value = "yaml")]
    pub format: util::render::ItemFormat,
}

/// Formatting options for a list of items.
#[derive(clap::Parser, Debug)]
pub struct ListFormatOpts {
    /// Output format. (json, text)
    #[clap(short = 'f', long, default_value = "table")]
    pub format: util::render::ListFormat,
}