Skip to main content

saya_cli/
app.rs

1use crate::{
2    cli::{Cli, Command, ConfigCommand, ConnectionCommand},
3    commands, config, interactive,
4};
5use std::{io::IsTerminal, path::Path};
6
7pub fn run(cli: Cli) -> i32 {
8    match dispatch(cli) {
9        Ok(code) => code,
10        Err(error) => {
11            eprintln!("Error: {error}");
12            2
13        }
14    }
15}
16
17fn dispatch(cli: Cli) -> Result<i32, Box<dyn std::error::Error>> {
18    let Some(command) = cli.command.clone() else {
19        if cli.options.non_interactive {
20            return Err("non-interactive mode requires a subcommand".into());
21        }
22        return interactive::run(cli);
23    };
24    if matches!(
25        &command,
26        Command::Config {
27            command: ConfigCommand::Init
28        }
29    ) {
30        return commands::run_config_init(cli.options.format.into());
31    }
32    let options = command_options(&cli.options, &command);
33    let runtime = config::runtime::load(&options, Path::new("."))?;
34    let approval = config::runtime::approval_mode(&options)?;
35    let format = config::runtime::format_name(&options, &runtime.resolved);
36    let can_prompt = !options.non_interactive && std::io::stdin().is_terminal();
37    tokio::runtime::Builder::new_current_thread()
38        .enable_all()
39        .build()?
40        .block_on(commands::run(
41            command,
42            &runtime,
43            format,
44            approval,
45            can_prompt,
46            options.include_profiles.clone(),
47        ))
48}
49
50fn command_options(
51    options: &crate::cli::GlobalOptions,
52    command: &Command,
53) -> crate::cli::GlobalOptions {
54    let mut options = options.clone();
55    if options.profile.is_none() {
56        let profile = match command {
57            Command::Connection {
58                command:
59                    ConnectionCommand::Test { profile_name }
60                    | ConnectionCommand::Schema { profile_name, .. },
61            } => Some(profile_name.clone()),
62            _ => None,
63        };
64        options.profile = profile;
65    }
66    options
67}