use axum::{ Json, http::StatusCode, response::{IntoResponse, Response}, }; use serde_json::json; use thiserror::Error; #[derive(Error, Debug)] pub enum StashError { #[error("IO 错误: {0}")] Io(#[from] std::io::Error), #[error("文件监听失败: {0}")] Watch(#[from] notify::Error), #[error("目录不存在或非法: {0}")] InvalidDirectory(String), #[error("网络地址解析失败: {0}")] AddrParse(#[from] std::net::AddrParseError), #[error("端口绑定失败: {0}")] ServerBind(String), #[error("未找到资源: {0}")] NotFound(String), /// 数据库相关失败:打开、建表、种子导入、查询。 /// 统一收敛成一个变体,避免把 rusqlite 的类型泄漏到库的公开 API。 #[error("数据库错误: {0}")] Database(String), /// 乐观锁冲突:资源在本次编辑期间被别人改过。 #[error("冲突: {0}")] Conflict(String), } impl IntoResponse for StashError { fn into_response(self) -> Response { let (status, err_msg) = match self { StashError::NotFound(msg) => (StatusCode::NOT_FOUND, msg), StashError::InvalidDirectory(msg) => (StatusCode::BAD_REQUEST, msg), StashError::Conflict(msg) => (StatusCode::CONFLICT, msg), _ => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()), }; let body = Json(json!({ "error": err_msg, "status": status.as_u16(), })); (status, body).into_response() } }