coman/cli/
commands.rs

1use std::fmt;
2
3use clap::Subcommand;
4
5use crate::cli::{manager::ManagerCommands, request::RequestCommands};
6
7#[derive(Subcommand)]
8pub enum Commands {
9    #[command(about = "List APIs Collections")]
10    List {
11        #[clap(short = 'c', long = "col", default_value = "", required = false)]
12        col: String,
13
14        #[clap(short = 'e', long = "endpoint", default_value = "", required = false)]
15        endpoint: String,
16
17        #[clap(short = 'q', long = "quiet", default_value = "false")]
18        quiet: bool,
19
20        #[clap(short, long, default_value = "false")]
21        verbose: bool,
22    },
23
24    #[command(about = "Managing APIs")]
25    Man {
26        #[command(subcommand)]
27        command: ManagerCommands,
28    },
29
30    #[command(about = "Sending requests")]
31    Req {
32        #[command(subcommand)]
33        command: RequestCommands,
34
35        #[clap(short, long, default_value = "false")]
36        verbose: bool,
37
38        #[clap(short, long, required = false, default_value = "false")]
39        stream: bool,
40    },
41
42    #[command(about = "Running collections endpoints")]
43    Run {
44        collection: String,
45        endpoint: String,
46
47        #[clap(short, long, default_value = "false")]
48        verbose: bool,
49
50        #[clap(short, long, required = false, default_value = "false")]
51        stream: bool,
52    },
53
54    #[command(about = "Print request URL with headers and body")]
55    Url {
56        collection: String,
57        endpoint: String,
58    },
59
60    #[command(about = "Run tests")]
61    Test { collection: String },
62}
63
64impl fmt::Display for Commands {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            Commands::List {
68                col,
69                endpoint,
70                quiet,
71                verbose,
72            } => write!(
73                f,
74                "List Command: {} - {} - {} - {}",
75                col, endpoint, quiet, verbose
76            ),
77            Commands::Man { command } => write!(f, "Man Command: {}", command),
78            Commands::Req {
79                command,
80                verbose,
81                stream,
82            } => {
83                write!(
84                    f,
85                    "Req Command: {} (verbose: {}) (stream: {})",
86                    command, verbose, stream
87                )
88            }
89            Commands::Run {
90                collection,
91                endpoint,
92                verbose,
93                stream,
94            } => {
95                write!(
96                    f,
97                    "Run Command: collection: '{}', endpoint: '{}', verbose: {}, stream: {}",
98                    collection, endpoint, verbose, stream
99                )
100            }
101            Commands::Url {
102                collection,
103                endpoint,
104            } => {
105                write!(
106                    f,
107                    "Url Command: collection: '{}', endpoint: '{}'",
108                    collection, endpoint
109                )
110            }
111            Commands::Test { collection } => {
112                write!(f, "Test Command: collection: '{}'", collection)
113            }
114        }
115    }
116}
117
118impl Commands {
119    pub async fn run_url(
120        &self,
121        collection: &str,
122        endpoint: &str,
123    ) -> Result<(), Box<dyn std::error::Error>> {
124        let command = ManagerCommands::get_endpoint_command(collection, endpoint)
125            .await
126            .ok_or("Endpoint not found")?;
127
128        let data = command.get_data();
129
130        let headers_url = data
131            .headers
132            .iter()
133            .map(|(key, value)| format!("-H \"{}: {}\"", key, value))
134            .collect::<Vec<_>>()
135            .join(" ");
136
137        let body_flag = if !data.body.is_empty() {
138            format!("-b '{}'", data.body)
139        } else {
140            String::new()
141        };
142
143        let url = format!(
144            "{} '{}' {} {}",
145            command.to_string().to_lowercase(),
146            data.url,
147            headers_url,
148            body_flag
149        );
150        println!("coman req -v {}", url);
151
152        Ok(())
153    }
154
155    pub async fn run_request(
156        &self,
157        collection: &str,
158        endpoint: &str,
159        verbose: &bool,
160        stdin_input: &Vec<u8>,
161        stream: &bool,
162    ) -> Result<(), Box<dyn std::error::Error>> {
163        if *verbose {
164            println!(
165                "Running collection '{}' with endpoint '{}'",
166                collection, endpoint
167            );
168        }
169
170        let command = ManagerCommands::get_endpoint_command(collection, endpoint)
171            .await
172            .ok_or("Endpoint not found")?;
173
174        command.run(*verbose, stdin_input.to_owned(), *stream).await
175    }
176
177    pub async fn run(&self, stdin_input: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
178        match self {
179            Commands::List {
180                col,
181                endpoint,
182                quiet,
183                verbose,
184            } => {
185                ManagerCommands::List {
186                    col: col.to_owned(),
187                    endpoint: endpoint.to_owned(),
188                    verbose: *verbose,
189                    quiet: *quiet,
190                }
191                .run()
192                .await
193            }
194            Commands::Man { command } => command.run().await,
195            Commands::Req {
196                command,
197                verbose,
198                stream,
199            } => command.run(*verbose, stdin_input, *stream).await,
200            Commands::Run {
201                collection,
202                endpoint,
203                verbose,
204                stream,
205            } => {
206                self.run_request(collection, endpoint, verbose, &stdin_input, stream)
207                    .await
208            }
209            Commands::Url {
210                collection,
211                endpoint,
212            } => self.run_url(collection, endpoint).await,
213            Commands::Test { collection } => self.run_tests(collection).await,
214        }
215    }
216}