mecha10-cli 0.8.0

Mecha10 CLI tool
Documentation
//! Building node binaries before spawning nodes in dev mode

use crate::context::CliContext;
use crate::paths;
use crate::types::ProjectConfig;
use anyhow::Result;

/// Build all nodes
///
/// Framework nodes need no local build - they're resolved on demand by `BinaryManager`. This
/// also pre-builds local project nodes so the node-runner doesn't need to build them at spawn time.
pub fn build_nodes(_ctx: &mut CliContext) -> Result<()> {
    println!("⚡ Nodes resolved on demand (no build required)");
    println!();

    build_local_project_nodes()?;

    Ok(())
}

/// Pre-build all local project nodes from the nodes/ directory, so the binary already exists
/// when node-runner spawns it and no compilation is needed at that point.
fn build_local_project_nodes() -> Result<()> {
    use crate::types::NodeSource;
    use std::process::Command;

    let config_path = std::path::Path::new(paths::PROJECT_CONFIG);
    if !config_path.exists() {
        return Ok(());
    }

    let config_content = std::fs::read_to_string(config_path)?;
    let config: ProjectConfig = serde_json::from_str(&config_content)?;

    let local_nodes: Vec<_> = config
        .nodes
        .get_node_specs()
        .into_iter()
        .filter(|spec| spec.source == NodeSource::Project)
        .collect();

    if local_nodes.is_empty() {
        return Ok(());
    }

    println!("🔨 Pre-building local project nodes...");

    for node_spec in &local_nodes {
        let node_name = &node_spec.name;

        let node_dir = std::path::Path::new("nodes").join(node_name);
        if !node_dir.exists() {
            tracing::warn!("Local node directory not found: nodes/{}", node_name);
            continue;
        }

        println!("  Building {}...", node_name);

        let output = Command::new("cargo")
            .args(["build", "-p", node_name])
            .output()
            .map_err(|e| anyhow::anyhow!("Failed to run cargo build for {}: {}", node_name, e))?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(anyhow::anyhow!(
                "Failed to build local node '{}': {}",
                node_name,
                stderr
            ));
        }
    }

    println!("✅ Local nodes built");
    println!();

    Ok(())
}