1pub mod app;
2pub mod cli;
3pub mod client;
4pub mod command_result;
5pub mod commands;
6pub mod config;
7pub mod credentials;
8pub mod error;
9pub mod exit_code;
10pub mod input;
11pub mod output;
12pub mod redaction;
13
14use std::{
15 env,
16 ffi::OsString,
17 io::{self, Write},
18 process::ExitCode,
19};
20
21use clap::{CommandFactory, Parser, error::ErrorKind};
22
23use crate::{
24 app::App,
25 cli::Cli,
26 config::ServerSelection,
27 error::AppError,
28 output::{OutputFormat, render_error, write_success},
29};
30
31pub fn run() -> impl std::future::Future<Output = ExitCode> {
34 Box::pin(run_command())
38}
39
40async fn run_command() -> ExitCode {
41 let args: Vec<OsString> = env::args_os().collect();
42 let cli = match Cli::try_parse_from(&args) {
43 Ok(cli) => cli,
44 Err(error)
45 if matches!(
46 error.kind(),
47 ErrorKind::DisplayHelp | ErrorKind::DisplayVersion
48 ) =>
49 {
50 let code = error.exit_code();
51 let _ = error.print();
52 return ExitCode::from(code as u8);
53 }
54 Err(error) => {
55 let requested_output = OutputFormat::detect_from_args(&args);
56 let app_error = AppError::invalid_input(error.to_string());
57 eprintln!("{}", render_error(requested_output, &app_error));
58 return app_error.exit_code().into();
59 }
60 };
61
62 let output_format = cli.output;
63 if let Err(error) = cli.command.validate_output(output_format) {
64 eprintln!("{}", render_error(output_format, &error));
65 return error.exit_code().into();
66 }
67 let app = App::production_with_confirmation_interactivity(
68 ServerSelection::new(cli.server, cli.profile_name, cli.allow_insecure_http),
69 output_format != OutputFormat::Json,
70 );
71
72 match app.execute(cli.command).await {
73 Ok(success) => {
74 let mut stdout = io::stdout().lock();
75 let mut stderr = io::stderr().lock();
76 match write_success(output_format, success, &mut stdout, &mut stderr).await {
77 Ok(exit_code) => exit_code,
78 Err(error) => {
79 let _ = writeln!(stderr, "{}", render_error(output_format, &error));
80 error.exit_code().into()
81 }
82 }
83 }
84 Err(error) => {
85 eprintln!("{}", render_error(output_format, &error));
86 error.exit_code().into()
87 }
88 }
89}
90
91pub fn command() -> clap::Command {
93 Cli::command()
94}