waterui-cli 0.3.0

Cross-platform tooling for WaterUI applications
Documentation
//! CLI command implementations.

use std::path::PathBuf;

use crate::shell::Shell;
use crate::{note, warn};
use waterui_cli::{
    toolchain::{Host, sccache::Sccache},
    utils::sccache_install_hint,
};

/// Whether the host environment permits routing builds through `sccache`.
fn sccache_allowed(host: &Host) -> bool {
    if let Some(value) = host.env("WATERUI_DISABLE_SCCACHE") {
        let value = value.to_string_lossy().trim().to_ascii_lowercase();
        if matches!(value.as_str(), "1" | "true" | "yes" | "on") {
            return false;
        }
    }
    // Respect explicit wrapper from caller (e.g. passthrough wrapper in constrained envs).
    host.env("RUSTC_WRAPPER").is_none()
}

/// Locate `sccache` for compilation caching, noting on the shell when it is
/// skipped or missing.
async fn detect_sccache_path(shell: &Shell, host: &Host) -> Option<PathBuf> {
    if !sccache_allowed(host) {
        note!(
            shell,
            "Skipping sccache (explicit wrapper or WATERUI_DISABLE_SCCACHE is set)"
        );
        return None;
    }

    let sccache = Sccache;
    sccache.path(host).await.map_or_else(
        |_| {
            warn!(
                shell,
                "sccache not found. Build efficiency may be reduced. Install with: {}",
                sccache_install_hint()
            );
            None
        },
        Some,
    )
}

pub mod backend;
pub mod bench;
pub mod build;
pub mod channel;
pub mod clean;
pub mod create;
pub mod device;
pub mod devices;
pub mod doctor;
pub mod gc;
pub mod init;
pub mod inspector;
pub mod mcp;
pub mod package;
pub mod preview;
pub mod run;
pub mod web;

/// Parse a viewport size from a `WIDTHxHEIGHT` string into whole pixels.
fn parse_viewport(s: &str) -> eyre::Result<(u32, u32)> {
    let parts: Vec<&str> = s.split('x').collect();
    if parts.len() != 2 {
        eyre::bail!("Invalid viewport format: expected WIDTHxHEIGHT (e.g., 390x844)");
    }

    let width: u32 = parts[0]
        .parse()
        .map_err(|_| eyre::eyre!("Invalid viewport width"))?;
    let height: u32 = parts[1]
        .parse()
        .map_err(|_| eyre::eyre!("Invalid viewport height"))?;

    if width == 0 {
        eyre::bail!("Invalid viewport width: must be positive");
    }
    if height == 0 {
        eyre::bail!("Invalid viewport height: must be positive");
    }

    Ok((width, height))
}