oph 0.1.0

OpenHealth CLI - Universal development tool for the OpenHealth team
Documentation
use crate::config::project_root;
use crate::ui;
use anyhow::{Context, Result};
use clap::Subcommand;
use std::process::{Command, Stdio};

#[derive(Subcommand)]
pub enum RunCommand {
    /// Start development server (bun run dev)
    Dev,
    /// Run all tests (bun run test)
    Test,
    /// Run unit tests only (bun run test:unit)
    #[command(name = "test:unit")]
    TestUnit,
    /// Run integration tests only (bun run test:integration)
    #[command(name = "test:integration")]
    TestIntegration,
    /// Run linter (bun run lint)
    Lint,
    /// Run TypeScript type checking (bun run typecheck)
    Typecheck,
    /// Run any script from package.json
    Script {
        /// Script name and arguments
        #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
        args: Vec<String>,
    },
}

pub fn run(cmd: RunCommand) -> Result<()> {
    check_bun()?;

    match cmd {
        RunCommand::Dev => bun_run(&["dev"])?,
        RunCommand::Test => bun_run(&["test"])?,
        RunCommand::TestUnit => bun_run(&["test:unit"])?,
        RunCommand::TestIntegration => bun_run(&["test:integration"])?,
        RunCommand::Lint => bun_run(&["lint"])?,
        RunCommand::Typecheck => bun_run(&["typecheck"])?,
        RunCommand::Script { args } => {
            if args.is_empty() {
                anyhow::bail!("Please specify a script to run");
            }
            let args_str: Vec<&str> = args.iter().map(String::as_str).collect();
            bun_run(&args_str)?;
        }
    }

    Ok(())
}

fn check_bun() -> Result<()> {
    which::which("bun").context("Bun is not installed or not in PATH")?;
    Ok(())
}

fn bun_run(args: &[&str]) -> Result<()> {
    let root = project_root()?;

    ui::show_command(&format!("bun run {}", args.join(" ")));

    let status = Command::new("bun")
        .arg("run")
        .args(args)
        .current_dir(&root)
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .status()
        .context("Failed to execute bun")?;

    if !status.success() {
        std::process::exit(status.code().unwrap_or(1));
    }

    Ok(())
}