auric 0.1.1

CLI for the `auric` MVC SPA framework
use clap::Parser;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::process::Command;

const DOT_GITIGNORE: &[u8] = include_bytes!("../../assets/.gitignore");
const INDEX_HTML: &[u8] = include_bytes!("../../assets/index.html");
const BUILD_RS: &[u8] = include_bytes!("../../assets/build.rs");
const SRC_MAIN_RS: &[u8] = include_bytes!("../../assets/src/main.rs");
const TEMPLATES_APPLICATION_HBS: &[u8] = include_bytes!("../../assets/templates/application.hbs");

#[derive(Debug, Parser)]
pub struct Opts {
    /// App Name
    #[arg(long = "name")]
    pub name: Option<String>,
}

pub async fn run(path: Option<&Path>, _name: Option<String>) -> anyhow::Result<()> {
    // cargo init <path>
    let path = path.unwrap_or(Path::new(".")).canonicalize()?;
    let path = path.as_path();
    eprintln!("==> cargo init {}", path.display());
    let output = Command::new("cargo").arg("init").current_dir(path).output()?;
    for line in output.stderr.split(|&c| c == b'\n') {
        let line = String::from_utf8(line.to_vec())?;
        eprintln!("{line}");
    }

    // Add dependencies required by trunk
    for dependency in ["anyhow@1.0", "auric-runtime"] {
        eprintln!("==> cargo add {dependency}");
        let output = Command::new("cargo")
            .arg("add")
            .args(dependency.split_ascii_whitespace())
            .current_dir(path)
            .output()?;
        for line in output.stderr.split(|&c| c == b'\n') {
            let line = String::from_utf8(line.to_vec())?;
            eprintln!("{line}");
        }
    }

    // Add build dependencies
    for dependency in ["anyhow@1.0", "auric-build"] {
        eprintln!("==> cargo add --build {dependency}");
        let output = Command::new("cargo")
            .arg("add")
            .arg("--build")
            .args(dependency.split_ascii_whitespace())
            .current_dir(path)
            .output()?;
        for line in output.stderr.split(|&c| c == b'\n') {
            let line = String::from_utf8(line.to_vec())?;
            eprintln!("{line}");
        }
    }

    // Deploy a .gitignore file
    let mut file = File::create(path.join(".gitignore"))?;
    file.write_all(DOT_GITIGNORE)?;

    // Deploy an index.html file
    let mut file = File::create(path.join("index.html"))?;
    file.write_all(INDEX_HTML)?;

    // Deploy a build.rs file
    let mut file = File::create(path.join("build.rs"))?;
    file.write_all(BUILD_RS)?;

    // Deploy an empty src/styles/app.scss file
    let styles_dir = path.join("src").join("styles");
    fs::create_dir_all(&styles_dir)?;
    let mut file = File::create(styles_dir.join("app.scss"))?;
    file.write_all("".as_bytes())?;

    // Deploy a src/main.rs file
    let mut file = File::create(path.join("src").join("main.rs"))?;
    file.write_all(SRC_MAIN_RS)?;

    // Deploy a src/templates/application.hbs file
    let templates_dir = path.join("src").join("templates");
    fs::create_dir_all(&templates_dir)?;
    let mut file = File::create(templates_dir.join("application.hbs"))?;
    file.write_all(TEMPLATES_APPLICATION_HBS)?;

    // Deploy an empty src/routes/mod.rs file
    let routes_dir = path.join("src").join("routes");
    fs::create_dir_all(&routes_dir)?;
    let mut file = File::create(routes_dir.join("mod.rs"))?;
    file.write_all("".as_bytes())?;

    // trunk build
    eprintln!("==> trunk build");
    let output = Command::new("trunk").arg("build").current_dir(path).output()?;
    for line in output.stderr.split(|&c| c == b'\n') {
        let line = String::from_utf8(line.to_vec())?;
        eprintln!("{line}");
    }

    Ok(())
}