Skip to main content

actr_cli/
error.rs

1//! Unified CLI error type system
2//!
3//! Design principles:
4//! 1. Clear semantics: each error type has a well-defined use case
5//! 2. No duplication: eliminate semantically overlapping error types
6//! 3. Layered: distinguish system errors vs. business errors
7//! 4. Easy to debug: provide sufficient context information
8
9use thiserror::Error;
10
11#[derive(Error, Debug)]
12pub enum ActrCliError {
13    // === System-level errors ===
14    #[error("IO operation failed: {0}")]
15    Io(#[from] std::io::Error),
16
17    #[error("Network request failed: {0}")]
18    Network(#[from] reqwest::Error),
19
20    #[error("JSON serialization failed: {0}")]
21    Serialization(#[from] serde_json::Error),
22
23    #[error("Git operation failed: {0}")]
24    Git(#[from] git2::Error),
25
26    // === Configuration errors ===
27    #[error("Configuration error: {0}")]
28    Configuration(String),
29
30    #[error("Invalid project structure: {0}")]
31    InvalidProject(String),
32
33    #[error("Project already exists: {0}")]
34    ProjectExists(String),
35
36    // === Dependency and build errors ===
37    #[error("Dependency resolution failed: {0}")]
38    Dependency(String),
39
40    #[error("Build process failed: {0}")]
41    Build(String),
42
43    #[error("Code generation failed: {0}")]
44    CodeGeneration(String),
45
46    // === Template and initialization errors ===
47    #[error("Template rendering failed: {0}")]
48    Template(#[from] handlebars::RenderError),
49
50    #[error("Unsupported feature: {0}")]
51    Unsupported(String),
52
53    // === Command execution errors ===
54    #[error("Command execution failed: {0}")]
55    Command(String),
56
57    // === Wrapper for underlying library errors ===
58    #[error("Actor framework error: {0}")]
59    Actor(#[from] actr_protocol::ActrError),
60
61    #[error("URI parsing error: {0}")]
62    UriParsing(#[from] actr_protocol::uri::ActrUriError),
63
64    #[error("Configuration parsing error: {0}")]
65    ConfigParsing(#[from] actr_config::ConfigError),
66
67    // === Generic error wrapper ===
68    #[error("Internal error: {0}")]
69    Internal(#[from] anyhow::Error),
70}
71
72// Error type conversion helpers
73impl ActrCliError {
74    /// Convert a string into a configuration error
75    pub fn config_error(msg: impl Into<String>) -> Self {
76        Self::Configuration(msg.into())
77    }
78
79    /// Convert a string into a dependency error
80    pub fn dependency_error(msg: impl Into<String>) -> Self {
81        Self::Dependency(msg.into())
82    }
83
84    /// Convert a string into a build error
85    pub fn build_error(msg: impl Into<String>) -> Self {
86        Self::Build(msg.into())
87    }
88
89    /// Convert a string into a command execution error
90    pub fn command_error(msg: impl Into<String>) -> Self {
91        Self::Command(msg.into())
92    }
93
94    /// Check whether this is a configuration-related error
95    pub fn is_config_error(&self) -> bool {
96        matches!(
97            self,
98            Self::Configuration(_) | Self::ConfigParsing(_) | Self::InvalidProject(_)
99        )
100    }
101
102    /// Check whether this is a network-related error
103    pub fn is_network_error(&self) -> bool {
104        matches!(self, Self::Network(_))
105    }
106
107    /// Get a user-friendly hint for this error
108    pub fn user_hint(&self) -> Option<&str> {
109        match self {
110            Self::InvalidProject(_) => Some("💡 Use 'actr init' to initialize a new project"),
111            Self::ProjectExists(_) => Some("💡 Use --force to overwrite existing project"),
112            Self::Configuration(_) => Some("💡 Check your manifest.toml configuration file"),
113            Self::Dependency(_) => {
114                Some("💡 Try 'actr deps install --force' to refresh dependencies")
115            }
116            Self::Build(_) => Some("💡 Check proto files and dependencies"),
117            Self::Network(_) => Some("💡 Check your network connection and proxy settings"),
118            Self::Unsupported(_) => Some("💡 This feature is not implemented yet"),
119            _ => None,
120        }
121    }
122}
123
124/// CLI-specific Result type
125pub type Result<T> = std::result::Result<T, ActrCliError>;
126
127// === Error compatibility conversions ===
128// Ensure backward compatibility while guiding migration to new error types