checkmate-cli 0.4.1

Checkmate - API Testing Framework CLI
//! Init command - initialize Checkmate in current directory

use std::io::{self, Write};

use crate::project::{CheckmateProject, ProjectError};

/// Options for the init command
pub struct InitOptions {
    pub url: Option<String>,
    pub stealth: bool,
}

/// Run the init command
pub fn run(options: InitOptions) -> Result<(), Box<dyn std::error::Error>> {
    let cwd = std::env::current_dir()?;

    // Check if already initialized
    if CheckmateProject::exists_at(&cwd) {
        eprintln!("Error: Checkmate already initialized in this directory.");
        eprintln!("Remove .checkmate/ to reinitialize.");
        std::process::exit(1);
    }

    // Get base URL
    let base_url = match options.url {
        Some(url) => url,
        None if atty::is(atty::Stream::Stdin) => {
            // Interactive mode - prompt user
            prompt_for_url()?
        }
        None => {
            // Non-interactive mode - error with instructions
            eprintln!("Error: Base URL required in non-interactive mode.");
            eprintln!();
            eprintln!("Run with --url flag:");
            eprintln!("  cm init --url http://localhost:8080");
            eprintln!();
            eprintln!("Or run interactively in a terminal.");
            std::process::exit(1);
        }
    };

    // Initialize project
    match CheckmateProject::init(&cwd, &base_url, options.stealth) {
        Ok(project) => {
            println!("✓ Initialized Checkmate in {}", project.root.display());
            println!();
            println!("Created:");
            println!("  .checkmate/config.toml  - Project configuration");
            println!("  .checkmate/tests/       - Test specifications");
            println!("  .checkmate/runs/        - Test run history");
            println!("  .checkmate/hooks/       - Custom hook scripts");
            println!();
            println!("Next steps:");
            println!("  1. Create test specs in .checkmate/tests/");
            println!("  2. Run tests with: cm test run");
            println!();
            println!("For help: cm docs");

            if options.stealth {
                println!();
                println!("Stealth mode: .checkmate/ added to .git/info/exclude");
            }

            Ok(())
        }
        Err(ProjectError::InvalidUrl(msg)) => {
            eprintln!("Error: {}", msg);
            std::process::exit(1);
        }
        Err(e) => Err(e.into()),
    }
}

/// Prompt user for base URL interactively
fn prompt_for_url() -> Result<String, io::Error> {
    print!("Base URL for API tests: ");
    io::stdout().flush()?;

    let mut input = String::new();
    io::stdin().read_line(&mut input)?;

    let url = input.trim().to_string();

    if url.is_empty() {
        eprintln!("Error: Base URL cannot be empty.");
        std::process::exit(1);
    }

    Ok(url)
}