feat: add error handling

This commit is contained in:
Alexander Navarro 2025-02-13 15:45:06 -03:00
parent 6bf3947df3
commit 8d8388e81a
5 changed files with 77 additions and 9 deletions

21
Cargo.lock generated
View file

@ -118,6 +118,7 @@ dependencies = [
"minijinja", "minijinja",
"notify", "notify",
"serde", "serde",
"thiserror",
"tokio", "tokio",
"tower-livereload", "tower-livereload",
] ]
@ -594,6 +595,26 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
[[package]]
name = "thiserror"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.43.0" version = "1.43.0"

View file

@ -8,5 +8,6 @@ axum = "0.8.1"
minijinja = "2.7.0" minijinja = "2.7.0"
notify = "8.0.0" notify = "8.0.0"
serde = "1.0.217" serde = "1.0.217"
thiserror = "2.0.11"
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
tower-livereload = "0.9.6" tower-livereload = "0.9.6"

39
src/error.rs Normal file
View file

@ -0,0 +1,39 @@
use axum::response::Html;
use axum::{http::StatusCode, response::IntoResponse};
pub type Result<T> = std::result::Result<T, Error>;
pub type ResultTemplate = std::result::Result<Html<String>, Error>;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Unhandled error: {0}")]
Generic(String),
#[error("Unhandled error: {0}")]
Static(&'static str),
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
Template(#[from] minijinja::Error),
#[error("Error in runtime execution: {0}")]
Runtime(&'static str),
// #[error(transparent)]
// DatabaseOperation(#[from] sqlx::Error),
}
impl IntoResponse for Error {
fn into_response(self) -> axum::response::Response {
let (status, message) = match self {
_ => (
StatusCode::INTERNAL_SERVER_ERROR,
"An unexpected error has ocurred!",
),
};
(status, message).into_response()
}
}

3
src/lib.rs Normal file
View file

@ -0,0 +1,3 @@
mod error;
pub use error::{Error, Result, ResultTemplate};

View file

@ -1,3 +1,6 @@
#![allow(unused)]
#![allow(dead_code)]
use std::sync::Arc; use std::sync::Arc;
use axum::extract::State; use axum::extract::State;
@ -5,6 +8,7 @@ use axum::http::StatusCode;
use axum::response::Html; use axum::response::Html;
use axum::routing::get; use axum::routing::get;
use axum::Router; use axum::Router;
use compendium::{Result, ResultTemplate};
use minijinja::{context, Environment}; use minijinja::{context, Environment};
struct AppState { struct AppState {
@ -12,11 +16,9 @@ struct AppState {
} }
#[tokio::main] #[tokio::main]
async fn main() { async fn main() -> Result<()> {
let mut tmpl_env = Environment::new(); let mut tmpl_env = Environment::new();
tmpl_env tmpl_env.add_template("base", include_str!("../templates/base.html"))?;
.add_template("base", include_str!("../templates/base.html"))
.unwrap();
let app_state = Arc::new(AppState { tmpl_env }); let app_state = Arc::new(AppState { tmpl_env });
@ -28,14 +30,16 @@ async fn main() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let app = app.layer(tower_livereload::LiveReloadLayer::new()); let app = app.layer(tower_livereload::LiveReloadLayer::new());
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
axum::serve(listener, app).await.unwrap(); axum::serve(listener, app).await?;
Ok(())
} }
async fn handler_home(State(state): State<Arc<AppState>>) -> Result<Html<String>, StatusCode> { async fn handler_home(State(state): State<Arc<AppState>>) -> ResultTemplate {
let template = state.tmpl_env.get_template("base").unwrap(); let template = state.tmpl_env.get_template("base")?;
let content = template.render(context!()).unwrap(); let content = template.render(context!())?;
Ok(Html(content)) Ok(Html(content))
} }