wasmer_cli/commands/namespace/
create.rs1use std::io::IsTerminal as _;
2
3use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ItemFormatOpts};
4use dialoguer::theme::ColorfulTheme;
5
6#[derive(clap::Parser, Debug)]
8pub struct CmdNamespaceCreate {
9 #[clap(flatten)]
10 fmt: ItemFormatOpts,
11
12 #[clap(flatten)]
13 env: WasmerEnv,
14
15 #[clap(long, default_value_t = !std::io::stdin().is_terminal())]
17 non_interactive: bool,
18
19 #[clap(long)]
21 display_name: Option<String>,
22
23 #[clap(long)]
25 description: Option<String>,
26
27 name: Option<String>,
29}
30
31impl CmdNamespaceCreate {
32 fn can_prompt(&self) -> bool {
33 !self.non_interactive && std::io::stdin().is_terminal()
34 }
35
36 fn normalize_optional_value(value: Option<&str>) -> Option<String> {
37 value.and_then(|value| {
38 let value = value.trim();
39 (!value.is_empty()).then(|| value.to_string())
40 })
41 }
42
43 fn prompt_optional_value(
44 &self,
45 message: &str,
46 default: Option<&str>,
47 ) -> anyhow::Result<Option<String>> {
48 let theme = ColorfulTheme::default();
49 let value = dialoguer::Input::<String>::with_theme(&theme)
50 .with_prompt(message)
51 .with_initial_text(default.unwrap_or_default())
52 .interact_text()?;
53
54 Ok(Self::normalize_optional_value(Some(&value)))
55 }
56
57 fn get_name(&self) -> anyhow::Result<String> {
58 if let Some(name) = Self::normalize_optional_value(self.name.as_deref()) {
59 return Ok(name);
60 }
61
62 if !self.can_prompt() {
63 anyhow::bail!("No namespace name given. Provide one as a positional argument.")
64 }
65
66 crate::utils::prompts::prompt_for_ident("Enter the namespace name", None)
67 }
68
69 fn get_display_name(&self) -> anyhow::Result<Option<String>> {
70 if self.display_name.is_some() || !self.can_prompt() {
71 return Ok(Self::normalize_optional_value(self.display_name.as_deref()));
72 }
73
74 self.prompt_optional_value("Enter the namespace display name", None)
75 }
76
77 fn get_description(&self) -> anyhow::Result<Option<String>> {
78 if self.description.is_some() || !self.can_prompt() {
79 return Ok(Self::normalize_optional_value(self.description.as_deref()));
80 }
81
82 self.prompt_optional_value("Enter the namespace description", None)
83 }
84}
85
86#[async_trait::async_trait]
87impl AsyncCliCommand for CmdNamespaceCreate {
88 type Output = ();
89
90 async fn run_async(self) -> Result<(), anyhow::Error> {
91 let client = self.env.client()?;
92
93 let vars = wasmer_backend_api::types::CreateNamespaceVars {
94 input: wasmer_backend_api::types::CreateNamespaceInput {
95 name: self.get_name()?,
96 display_name: self.get_display_name()?,
97 description: self.get_description()?,
98 avatar: None,
99 client_mutation_id: None,
100 },
101 };
102 let namespace = wasmer_backend_api::query::create_namespace(&client, vars).await?;
103
104 println!("{}", self.fmt.get().render(&namespace));
105
106 Ok(())
107 }
108}