kit_rs/
error.rs

1//! Framework-wide error types
2//!
3//! Provides a unified error type that can be used throughout the framework
4//! and automatically converts to appropriate HTTP responses.
5
6use std::fmt;
7
8/// Framework-wide error type
9///
10/// This enum represents all possible errors that can occur in the framework.
11/// It implements `From<FrameworkError> for Response` so errors can be propagated
12/// using the `?` operator in controller handlers.
13///
14/// # Example
15///
16/// ```rust,ignore
17/// use kit::{App, FrameworkError, Response};
18///
19/// pub async fn index(_req: Request) -> Response {
20///     let service = App::resolve::<MyService>()?;  // Returns FrameworkError on failure
21///     // ...
22/// }
23/// ```
24#[derive(Debug, Clone)]
25pub enum FrameworkError {
26    /// Service not found in the dependency injection container
27    ServiceNotFound {
28        /// The type name of the service that was not found
29        type_name: &'static str,
30    },
31
32    /// Parameter extraction failed (missing or invalid parameter)
33    ParamError {
34        /// The name of the parameter that failed extraction
35        param_name: String,
36    },
37
38    /// Validation error
39    ValidationError {
40        /// The field that failed validation
41        field: String,
42        /// The validation error message
43        message: String,
44    },
45
46    /// Database error
47    DatabaseError {
48        /// The error message
49        message: String,
50    },
51
52    /// Generic internal server error
53    Internal {
54        /// The error message
55        message: String,
56    },
57}
58
59impl FrameworkError {
60    /// Create a ServiceNotFound error for a given type
61    pub fn service_not_found<T: ?Sized>() -> Self {
62        Self::ServiceNotFound {
63            type_name: std::any::type_name::<T>(),
64        }
65    }
66
67    /// Create a ParamError for a missing parameter
68    pub fn param(name: impl Into<String>) -> Self {
69        Self::ParamError {
70            param_name: name.into(),
71        }
72    }
73
74    /// Create a ValidationError
75    pub fn validation(field: impl Into<String>, message: impl Into<String>) -> Self {
76        Self::ValidationError {
77            field: field.into(),
78            message: message.into(),
79        }
80    }
81
82    /// Create a DatabaseError
83    pub fn database(message: impl Into<String>) -> Self {
84        Self::DatabaseError {
85            message: message.into(),
86        }
87    }
88
89    /// Create an Internal error
90    pub fn internal(message: impl Into<String>) -> Self {
91        Self::Internal {
92            message: message.into(),
93        }
94    }
95
96    /// Get the HTTP status code for this error
97    pub fn status_code(&self) -> u16 {
98        match self {
99            Self::ServiceNotFound { .. } => 500,
100            Self::ParamError { .. } => 400,
101            Self::ValidationError { .. } => 422,
102            Self::DatabaseError { .. } => 500,
103            Self::Internal { .. } => 500,
104        }
105    }
106}
107
108impl fmt::Display for FrameworkError {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        match self {
111            Self::ServiceNotFound { type_name } => {
112                write!(f, "Service '{}' not registered in container", type_name)
113            }
114            Self::ParamError { param_name } => {
115                write!(f, "Missing required parameter: {}", param_name)
116            }
117            Self::ValidationError { field, message } => {
118                write!(f, "Validation error for '{}': {}", field, message)
119            }
120            Self::DatabaseError { message } => {
121                write!(f, "Database error: {}", message)
122            }
123            Self::Internal { message } => {
124                write!(f, "Internal server error: {}", message)
125            }
126        }
127    }
128}
129
130impl std::error::Error for FrameworkError {}