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 {}