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}