esmeril 0.2.0

Scaffold, validate, format, audit and build Roblox Luau projects from the terminal
use std::path::Path;

use colored::Colorize;
use serde::Serialize;

use crate::cli::BuildArgs;

#[derive(Serialize)]
pub struct BuildReport {
    pub path: String,
    pub grade: char,
    pub score: u8,
    pub output: String,
    pub ok: bool,
    pub summary: String,
}

impl BuildReport {
    pub fn fail(&self) -> bool {
        !self.ok
    }
}

pub fn run(args: &BuildArgs, json: bool) -> anyhow::Result<BuildReport> {
    let root = Path::new(&args.path);
    let check = crate::check::inspect(root);
    if check.fail() {
        crate::check::print_report(&check);
        anyhow::bail!("check failed - fix the project before building");
    }
    if !crate::check::on_path("rojo") {
        anyhow::bail!("rojo is not installed - install with: aftman add rojo-rbx/rojo");
    }

    let default_out = if crate::fix::is_lib(root) {
        "lib.rbxm"
    } else {
        "game.rbxl"
    };
    let output = args
        .output
        .clone()
        .unwrap_or_else(|| default_out.to_string());
    let out = crate::tool::run("rojo", &["build", "-o", &output], root)?;
    let report = BuildReport {
        path: root.display().to_string(),
        grade: check.grade,
        score: check.score,
        output,
        ok: out.code == 0,
        summary: crate::tool::summary(&out),
    };
    if json {
        println!("{}", serde_json::to_string_pretty(&report)?);
    } else {
        print_report(&report);
    }
    Ok(report)
}

fn print_report(r: &BuildReport) {
    println!("  {}  {}", "esmeril build".bold().cyan(), r.path);
    println!();
    println!("  check  {}", crate::check::colored_grade(r.grade, r.score));
    let mark = if r.ok { "".green() } else { "".red() };
    let summary = if r.summary.is_empty() {
        if r.ok {
            "ok".to_string()
        } else {
            "build failed".to_string()
        }
    } else {
        r.summary.clone()
    };
    let line = format!("  {} rojo  {}", mark, summary);
    if r.ok {
        println!("{}  ({})", line, r.output.dimmed());
    } else {
        println!("{}", line.red());
    }
    println!();
    if r.ok {
        println!("  {}", format!("wrote {}", r.output).green());
    } else {
        println!("  {}", "build failed".red().bold());
    }
}