cyrce-forge-core 0.6.0

Motor principal de FORGE: DAG, ejecutor paralelo y cachΓ©
Documentation
// =============================================================================
// πŸ”₯ FORGE β€” Motor Core: Tipos de Error (v0.4.0)
// =============================================================================
// Manejo de errores centralizado con tipos descriptivos y sugerencias
// contextuales para resolver cada problema.
// PatrΓ³n moderno: thiserror para errores tipados + anyhow para propagaciΓ³n.
// =============================================================================

use std::path::PathBuf;

/// Errores especΓ­ficos del motor FORGE.
/// Cada variante describe un problema concreto con contexto ΓΊtil para el usuario.
#[derive(Debug, thiserror::Error)]
pub enum ForgeError {
    // ── ConfiguraciΓ³n ────────────────────────────────────────────────────
    #[error("No se encontrΓ³ 'forge.toml' en: {path}")]
    ConfigNotFound { path: PathBuf },

    #[error("Error al parsear 'forge.toml': {message}")]
    ConfigParseError { message: String },

    #[error("Campo requerido '{field}' no encontrado en forge.toml")]
    ConfigMissingField { field: String },

    #[error("Lenguaje no soportado: '{lang}'. Usa: java, kotlin, python")]
    UnsupportedLanguage { lang: String },

    // ── Grafo de Tareas (DAG) ────────────────────────────────────────────
    #[error("Dependencia circular detectada: {cycle}")]
    CyclicDependency { cycle: String },

    #[error("Tarea no encontrada: '{task_name}'")]
    TaskNotFound { task_name: String },

    // ── EjecuciΓ³n ────────────────────────────────────────────────────────
    #[error("La tarea '{task_name}' fallΓ³ con cΓ³digo de salida: {exit_code}")]
    TaskFailed { task_name: String, exit_code: i32 },

    #[error("Comando no encontrado: '{command}'. ΒΏEstΓ‘ instalado y en el PATH?")]
    CommandNotFound { command: String },

    #[error("Timeout al ejecutar la tarea '{task_name}' despuΓ©s de {seconds}s")]
    TaskTimeout { task_name: String, seconds: u64 },

    // ── Dependencias ─────────────────────────────────────────────────────
    #[error("No se pudo resolver la dependencia: '{dependency}'")]
    DependencyResolutionFailed { dependency: String },

    #[error("Error al descargar '{url}': {message}")]
    DownloadError { url: String, message: String },

    // ── Sistema de Archivos ──────────────────────────────────────────────
    #[error("Error de E/S en '{path}': {message}")]
    IoError { path: PathBuf, message: String },

    // ── CachΓ© ────────────────────────────────────────────────────────────
    #[error("CachΓ© corrupta en '{path}'. Ejecuta 'forge clean' para regenerar.")]
    CacheCorrupted { path: PathBuf },
}

impl ForgeError {
    /// Devuelve una sugerencia contextual de resoluciΓ³n para el error.
    pub fn suggestion(&self) -> &'static str {
        match self {
            Self::ConfigNotFound { .. } => {
                "πŸ’‘ Ejecuta 'forge init <lang>' para crear un forge.toml, o verifica que estΓ‘s en el directorio correcto."
            }
            Self::ConfigParseError { .. } => {
                "πŸ’‘ Verifica la sintaxis TOML de tu forge.toml. Usa un validador como https://www.toml-lint.com/"
            }
            Self::ConfigMissingField { field, .. } => {
                match field.as_str() {
                    "name" => "πŸ’‘ AΓ±ade 'name = \"mi-proyecto\"' en la secciΓ³n [project] de forge.toml",
                    "lang" => "πŸ’‘ AΓ±ade 'lang = \"java\"' (o kotlin/python) en la secciΓ³n [project] de forge.toml",
                    _ => "πŸ’‘ Revisa la documentaciΓ³n: https://github.com/enri312/forge#configuraciΓ³n",
                }
            }
            Self::UnsupportedLanguage { .. } => {
                "πŸ’‘ FORGE soporta: java, kotlin, python. Verifica el campo 'lang' en [project]"
            }
            Self::CyclicDependency { .. } => {
                "πŸ’‘ Revisa las secciones [tasks.*.depends-on] en tu forge.toml para romper el ciclo"
            }
            Self::TaskNotFound { .. } => {
                "πŸ’‘ Lista las tareas disponibles con 'forge info' o revisa la secciΓ³n [tasks] de forge.toml"
            }
            Self::TaskFailed { .. } => {
                "πŸ’‘ Revisa la salida del compilador arriba. Usa 'forge build --verbose' para mΓ‘s detalle"
            }
            Self::CommandNotFound { command, .. } => {
                match command.as_str() {
                    "javac" | "java" => "πŸ’‘ Instala JDK 17+: https://adoptium.net/ y asegΓΊrate que 'javac' estΓ‘ en PATH",
                    "kotlinc" => "πŸ’‘ Instala Kotlin: https://kotlinlang.org/docs/command-line.html",
                    "python" | "python3" | "pip" => "πŸ’‘ Instala Python 3.12+: https://www.python.org/downloads/",
                    "pytest" => "πŸ’‘ Instala pytest: pip install pytest",
                    _ => "πŸ’‘ Verifica que el comando estΓ‘ instalado y accesible en tu PATH del sistema",
                }
            }
            Self::TaskTimeout { .. } => {
                "πŸ’‘ Considera aumentar el timeout o dividir la tarea en sub-tareas mΓ‘s pequeΓ±as"
            }
            Self::DependencyResolutionFailed { .. } => {
                "πŸ’‘ Verifica el formato en [dependencies]: \"groupId:artifactId\" = \"versiΓ³n\". Ejemplo: \"com.google.gson:gson\" = \"2.11.0\""
            }
            Self::DownloadError { .. } => {
                "πŸ’‘ Verifica tu conexiΓ³n a internet y que la dependencia exista en Maven Central / PyPI"
            }
            Self::IoError { .. } => {
                "πŸ’‘ Verifica permisos de escritura en el directorio del proyecto y espacio disponible en disco"
            }
            Self::CacheCorrupted { .. } => {
                "πŸ’‘ Ejecuta 'forge clean' para eliminar la cachΓ© y reconstruir desde cero"
            }
        }
    }
}

/// Resultado tipado de FORGE usando anyhow para contexto flexible.
pub type ForgeResult<T> = anyhow::Result<T>;