stackr 0.1.10

CLI to initialize, develop, and maintain your Stackr Micro-rollups
use std::fs;
use std::{error::Error, process::Command};

use crate::constants::MRU_TEMPLATE_REPO;

pub fn build_index_content() -> &'static str {
    r#"
  // Execution step
  // Read inputs from stdin
  const stfInputs = readInput();
  var newState = run(stfInputs.currentState, stfInputs.actions);
  // Write the result to stdout
  writeOutput(newState);
  
  // Read input from stdin
  function readInput() {
    const chunkSize = 1024;
    const inputChunks = [];
    let totalBytes = 0;
  
    // Read all the available bytes
    while (1) {
      const buffer = new Uint8Array(chunkSize);
      // Stdin file descriptor
      const fd = 0;
      const bytesRead = Javy.IO.readSync(fd, buffer);
  
      totalBytes += bytesRead;
      if (bytesRead === 0) {
        break;
      }
      inputChunks.push(buffer.subarray(0, bytesRead));
    }
  
    // Assemble input into a single Uint8Array
    const { finalBuffer } = inputChunks.reduce(
      (context, chunk) => {
        context.finalBuffer.set(chunk, context.bufferOffset);
        context.bufferOffset += chunk.length;
        return context;
      },
      { bufferOffset: 0, finalBuffer: new Uint8Array(totalBytes) },
    );
  
    return JSON.parse(new TextDecoder().decode(finalBuffer));
  }
  
  function writeOutput(output) {
    const encodedOutput = new TextEncoder().encode(JSON.stringify(output));
    const buffer = new Uint8Array(encodedOutput);
    // Stdout file descriptor
    const fd = 1;
    Javy.IO.writeSync(fd, buffer);
  }"#
}

pub async fn setup_project(project_name: &str) -> Result<(), Box<dyn Error>> {
    println!(
        r#"
        _             _                        _ _ 
    ___| |_ __ _  ___| | ___ __            ___| (_)
   / __| __/ _` |/ __| |/ / '__|  _____   / __| | |
   \__ \ || (_| | (__|   <| |    |_____| | (__| | |
   |___/\__\__,_|\___|_|\_\_|             \___|_|_|
                                                   
   "#
    );
    println!("🐜 Initializing Micro-rollup build");

    println!("🛠️ Generating Project Files {}", project_name);
    let _ = fs::create_dir(project_name);

    let mut clone_command = Command::new("git");
    clone_command
        .arg("clone")
        .arg(MRU_TEMPLATE_REPO)
        .arg(".")
        .current_dir(project_name);

    match clone_command.status() {
        Ok(status) => {
            if status.success() {
                println!("💻 Rollup Template Setup Complete");
            } else {
                eprintln!("Failed to clone repository: {:?}", status);
            }
        }
        Err(err) => {
            eprintln!("Failed to execute git clone: {:?}", err);
        }
    }

    let bun_install_status = Command::new("bun")
        .arg("install")
        .current_dir(project_name)
        .status();

    match bun_install_status {
        Ok(status) => {
            if status.success() {
                println!("📦 bun install Complete");
            } else {
                eprintln!("Failed to execute bun install: {:?}", status);
            }
        }
        Err(err) => {
            eprintln!("Failed to execute bun install: {:?}", err);
        }
    }

    let _ = fs::remove_dir_all(format!("{}/.git", project_name));

    let git_init_status = Command::new("git")
        .arg("init")
        .current_dir(project_name)
        .status();

    match git_init_status {
        Ok(status) => {
            if status.success() {
                println!("📦 setup git repository");
            } else {
                eprintln!("Failed to execute git init: {:?}", status);
            }
        }
        Err(err) => {
            eprintln!("Failed to execute git init: {:?}", err);
        }
    }

    // TODO : Consider creating a genesis state file for applications not using template
    // let _ = fs::write(
    //     format!("{}/genesis-state.json", project_name),
    //     "{ \"state\" : }",
    // )?;

    let _ = Command::new("git")
        .arg("add")
        .arg(".")
        .current_dir(project_name)
        .status();

    let _ = Command::new("git")
        .arg("commit")
        .arg("-m")
        .arg("Initial Project Setup")
        .current_dir(project_name)
        .status();

    // print a message to the user and ask them to cd into the project
    println!("🎉 Project Setup Complete");

    Ok(())
}