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 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 .ok_or_else(|| format!("Endpoint not found: {}/{}", collection, endpoint))?;
126
127 let data = command.get_data();
128
129 let headers_url = data
130 .headers
131 .iter()
132 .map(|(key, value)| format!("-H \"{}: {}\"", key, value))
133 .collect::<Vec<_>>()
134 .join(" ");
135
136 let body_flag = if !data.body.is_empty() {
137 format!("-b '{}'", data.body)
138 } else {
139 String::new()
140 };
141
142 let url = format!(
143 "{} '{}' {} {}",
144 command.to_string().to_lowercase(),
145 data.url,
146 headers_url,
147 body_flag
148 );
149 println!("coman req -v {}", url);
150
151 Ok(())
152 }
153
154 pub async fn run_request(
155 &self,
156 collection: &str,
157 endpoint: &str,
158 verbose: &bool,
159 stdin_input: &Vec<u8>,
160 stream: &bool,
161 ) -> Result<(), Box<dyn std::error::Error>> {
162 if *verbose {
163 println!(
164 "Running collection '{}' with endpoint '{}'",
165 collection, endpoint
166 );
167 }
168
169 let command = ManagerCommands::get_endpoint_command(collection, endpoint);
170
171 if let Some(cmd) = command {
172 cmd.run(*verbose, stdin_input.to_owned(), *stream).await
173 } else {
174 Err(format!("Endpoint not found: {} - {}", collection, endpoint).into())
175 }
176 }
177
178 pub async fn run(&self, stdin_input: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
179 match self {
180 Commands::List {
181 col,
182 endpoint,
183 quiet,
184 verbose,
185 } => ManagerCommands::List {
186 col: col.to_owned(),
187 endpoint: endpoint.to_owned(),
188 verbose: *verbose,
189 quiet: *quiet,
190 }
191 .run(),
192 Commands::Man { command } => command.run(),
193 Commands::Req {
194 command,
195 verbose,
196 stream,
197 } => command.run(*verbose, stdin_input, *stream).await,
198 Commands::Run {
199 collection,
200 endpoint,
201 verbose,
202 stream,
203 } => {
204 self.run_request(collection, endpoint, verbose, &stdin_input, stream)
205 .await
206 }
207 Commands::Url {
208 collection,
209 endpoint,
210 } => self.run_url(collection, endpoint),
211 Commands::Test { collection } => self.run_tests(collection).await,
212 }
213 }
214}