feat: initialize thoughts-frontend with Next.js, TypeScript, and ESLint
- Add ESLint configuration for Next.js and TypeScript support. - Create Next.js configuration file with standalone output option. - Initialize package.json with scripts for development, build, and linting. - Set up PostCSS configuration for Tailwind CSS. - Add SVG assets for UI components. - Create TypeScript configuration for strict type checking and module resolution.
This commit is contained in:
32
thoughts-backend/api/src/error/adapter.rs
Normal file
32
thoughts-backend/api/src/error/adapter.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use axum::{extract::rejection::JsonRejection, http::StatusCode};
|
||||
use sea_orm::DbErr;
|
||||
|
||||
use app::error::UserError;
|
||||
|
||||
use super::traits::HTTPError;
|
||||
|
||||
impl HTTPError for JsonRejection {
|
||||
fn to_status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
JsonRejection::JsonSyntaxError(_) => StatusCode::BAD_REQUEST,
|
||||
_ => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HTTPError for DbErr {
|
||||
fn to_status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
DbErr::ConnectionAcquire(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
_ => StatusCode::INTERNAL_SERVER_ERROR, // TODO:: more granularity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HTTPError for UserError {
|
||||
fn to_status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
UserError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
}
|
10
thoughts-backend/api/src/error/core.rs
Normal file
10
thoughts-backend/api/src/error/core.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
pub struct ApiError(pub(super) anyhow::Error);
|
||||
|
||||
impl<E> From<E> for ApiError
|
||||
where
|
||||
E: Into<anyhow::Error>,
|
||||
{
|
||||
fn from(err: E) -> Self {
|
||||
Self(err.into())
|
||||
}
|
||||
}
|
36
thoughts-backend/api/src/error/handler.rs
Normal file
36
thoughts-backend/api/src/error/handler.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use axum::{
|
||||
extract::rejection::JsonRejection,
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use sea_orm::DbErr;
|
||||
|
||||
use app::error::UserError;
|
||||
|
||||
use super::{ApiError, HTTPError};
|
||||
use crate::models::ApiErrorResponse;
|
||||
|
||||
impl IntoResponse for ApiError {
|
||||
fn into_response(self) -> Response {
|
||||
let err = self.0;
|
||||
|
||||
let (status, message) = if let Some(err) = err.downcast_ref::<DbErr>() {
|
||||
tracing::error!(%err, "error from db:");
|
||||
(err.to_status_code(), "DB error".to_string()) // hide the detail
|
||||
} else if let Some(err) = err.downcast_ref::<UserError>() {
|
||||
(err.to_status_code(), err.to_string())
|
||||
} else if let Some(err) = err.downcast_ref::<JsonRejection>() {
|
||||
tracing::error!(%err, "error from extractor:");
|
||||
(err.to_status_code(), err.to_string())
|
||||
} else {
|
||||
tracing::error!(%err, "error from other source:");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Unknown error".to_string(),
|
||||
)
|
||||
};
|
||||
|
||||
(status, Json(ApiErrorResponse { message })).into_response()
|
||||
}
|
||||
}
|
7
thoughts-backend/api/src/error/mod.rs
Normal file
7
thoughts-backend/api/src/error/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
mod adapter;
|
||||
mod core;
|
||||
mod handler;
|
||||
mod traits;
|
||||
|
||||
pub use core::ApiError;
|
||||
pub use traits::HTTPError;
|
5
thoughts-backend/api/src/error/traits.rs
Normal file
5
thoughts-backend/api/src/error/traits.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
use axum::http::StatusCode;
|
||||
|
||||
pub trait HTTPError {
|
||||
fn to_status_code(&self) -> StatusCode;
|
||||
}
|
Reference in New Issue
Block a user