diff --git a/Cargo.toml b/Cargo.toml index d96aa08..7175b7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ repository = "https://github.com/franklinblanco/err.git" [dependencies] serde = { version = "1.0", features = ["derive"] } thiserror = "1.0.48" -sqlx = { version = "0.7", features = ["json"] } +sqlx = { version = "0.8", features = ["json"] } stdext = "0.3.1" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index a2b5f31..b832db5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,7 @@ mod macros; -mod tests; use std::fmt::Display; -use serde::{Serialize, Deserialize, Serializer}; -use serde::ser::SerializeMap; -use thiserror::Error; +use serde::{Serialize, Deserialize}; pub use stdext::function_name; @@ -25,51 +22,6 @@ impl Trace { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Traces { pub traces: Vec } - -#[derive(Serialize, Debug, Error)] -#[error("MessageResource: {message_resource} ErrorType: {error_type} Trace: {trace:#?}")] -pub struct Error { - pub trace: Traces, - #[serde(rename = "messageResource")] - pub message_resource: MessageResource, - #[serde(rename = "errorType")] - pub error_type: ErrorType, -} - -impl Error { - pub fn new(trace: Trace) -> Self { - Self { - trace: Traces { traces: Vec::from([trace]) }, - message_resource: MessageResource::new("errors.backend.common.default", "We still don't have an error defined for this."), - error_type: ErrorType::Unspecified, - } - } - pub fn push_trace(mut self, trace: Trace) -> Self { - self.trace.traces.push(trace); - self - } - - pub fn push_error(mut self, error: Error) -> Self { - self.error_type = ErrorType::Nested { nested: Box::new(error) }; - self - } - pub fn key(mut self, key: Option) -> Self { - self.message_resource.key = match key { - None => None, - Some(key) => Some(key.to_string()), - }; - self - } - pub fn message(mut self, message: impl ToString) -> Self { - self.message_resource.message = message.to_string(); - self - } - pub fn error_type(mut self, error_type: ErrorType) -> Self { - self.error_type = error_type; - self - } -} - /// This is for sending errors back from requests conveniently. /// This struct contains an optional key just in /// case you want to deal with internationalization. @@ -110,83 +62,6 @@ impl Default for MessageResource{ Self { key: None, message: "".to_string() } } } -/// This is supposed to be used whenever you have an error in your code and want to be more specific about it. -/// Fits in with most CRUD web apps. What you send back to the client is a MessageResource, not the error itself! -#[derive(Serialize, Debug, Error)] -pub enum ErrorType { - #[error("Network Error")] - Network, - #[error("IO error")] - IO, - #[error("Privilege Error")] - Privilege, - #[error("Unexpected Status Code. Expected: {expected} Actual: {actual}")] - UnexpectedStatusCode { expected: u16, actual: u16 }, - #[error("Serde Error. Attempted to Serialize/Deserialize String: {text}")] - Serde { text: String }, - #[error("Parsing error.")] - Parser, - #[error("Service Error: {error}")] - Service { error: ServiceError }, - #[error("Unspecified Error")] - Unspecified, - #[error("Unexpected Error: {message}")] - Unexpected { message: String }, - #[error("Nested Error: {nested}")] - Nested { nested: Box }, -} - -#[derive(Error, Serialize, Debug)] -pub enum ServiceError { - /// Used to return a simple error from FromStr implementations. - #[error("Error parsing string into value")] - FromStrError, - /// Every error that is returned from a DAO operation. - #[error("Error from the Database: {error}")] - #[serde(serialize_with = "ser_with")] - DatabaseError { - #[from] - error: sqlx::Error - }, - /// A vec of ValidationErrors - #[error("Error Operation Not Allowed: {message}")] - NotAllowed { message: String }, - #[error("Validation Errors: {errors:?}")] - ValidationErrors { errors: Vec }, - /// Something already exists. That something should be {0} - /// Example: "User" "Credential" - #[error("Error {message} Already exists.")] - AlreadyExistsError { message: String }, - /// Example: "User with id X" - #[error("{message} Not found.")] - NotFoundError { message: String }, - /// Used to specify authentication error. - /// Example: Password incorrect for user - #[error("Credential supplied is incorrect. {message}")] - IncorrectCredentialError { message: String }, - #[error("Too many credentials supplied, maximum is 3.")] - TooManyCredentialsError, - /// Used for anything else. - #[error("Unexpected Error: {message}")] - UnexpectedError { message: String }, -} - -/// Any string validation error such as Phone number validation or email, etc... -/// Reason should be a Key for internationalization -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Error)] -#[error("Error validating `{what}`. Reason: {reason}")] -pub struct ValidationError { - pub what: String, - pub reason: String, -} - -pub fn ser_with(id: &sqlx::Error, s: S) -> Result where - S: Serializer, -{ - let mut ser = s.serialize_map(Some(1))?; - ser.serialize_entry("$oid", &id.to_string())?; - ser.end() -} pub trait VecRemove { type T; diff --git a/src/macros.rs b/src/macros.rs index 3828de5..5260fd0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -24,46 +24,4 @@ macro_rules! test_trace { service: env!("CARGO_PKG_NAME").into(), } }; -} - -/// Macro used to 'unwrap' a result that returns a Error -/// -/// If there's an error returns the generated Error and push a trace on it. -#[allow(unused_macros)] -#[macro_export] -macro_rules! u_res_or_res { - ( $e:expr ) => { - match $e { - Ok(result) => result, - Err(mut error) => return Err(error.push_trace(err::trace!())) - } - }; -} - -/// Macro used to 'unwrap' a result that returns a Error -/// -/// If there's an error returns the generated Error and push a trace on it. -#[allow(unused_macros)] -#[macro_export] -macro_rules! x_u_res_or_res { - ( $e:expr, $t:expr ) => { - match $e { - Ok(result) => result, - Err(error) => return Err(err::Error::new(err::trace!()).message(error.to_string()).error_type($t)) - } - }; -} - -/// Macro used to 'unwrap' a result that returns a Error -/// -/// If there's an error returns the generated Error and push a trace on it. -#[allow(unused_macros)] -#[macro_export] -macro_rules! x_u_res_db_or_res { - ( $e:expr ) => { - match $e { - Ok(result) => result, - Err(error) => return Err(err::Error::new(err::trace!()).message(error.to_string()).error_type(err::ErrorType::Service { error: err::ServiceError::DatabaseError{error: error} } )) - } - }; } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs deleted file mode 100644 index 2424030..0000000 --- a/src/tests.rs +++ /dev/null @@ -1,45 +0,0 @@ - -#[cfg(test)] -mod tests { - use crate::{Error, ErrorType, ServiceError, test_trace}; - - #[test] - fn print_json() { - let error = Error::new(test_trace!()) - .message("Hi there g") - .push_trace(test_trace!()) - .key(Some("This key")) - .push_error( - Error::new(test_trace!()) - .error_type(ErrorType::Service { error: ServiceError::AlreadyExistsError { message: String::from("Hey now") } }) - .message("Hi there g") - .push_trace(test_trace!()) - .key(Some("key for nested err")) - ); - println!("Object in rust: {:#?}", error); - println!(""); - println!("#############################################"); - println!(""); - println!("Object in json: {}", serde_json::to_string_pretty(&error).unwrap()) - } - - #[test] - fn print_json_with_db_error_variant() { - let error = Error::new(test_trace!()) - .message("Hi there g") - .push_trace(test_trace!()) - .key(Some("This key")) - .push_error( - Error::new(test_trace!()) - .error_type(ErrorType::Service { error: ServiceError::DatabaseError { error: sqlx::Error::Protocol("AAAA".into()) } }) - .message("Hi there g") - .push_trace(test_trace!()) - .key(Some("key for nested err")) - ); - println!("Object in rust: {:#?}", error); - println!(""); - println!("#############################################"); - println!(""); - println!("Object in json: {}", serde_json::to_string_pretty(&error).unwrap()) - } -} \ No newline at end of file