fraiseql_server/routes/api/
types.rs1use std::fmt;
4
5use axum::{
6 Json,
7 http::StatusCode,
8 response::{IntoResponse, Response},
9};
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Serialize, Deserialize, Clone)]
14pub struct ApiError {
15 pub error: String,
17 pub code: String,
19 pub details: Option<String>,
21}
22
23impl ApiError {
24 pub fn new(error: impl Into<String>, code: impl Into<String>) -> Self {
26 Self {
27 error: error.into(),
28 code: code.into(),
29 details: None,
30 }
31 }
32
33 pub fn with_details(mut self, details: impl Into<String>) -> Self {
35 self.details = Some(details.into());
36 self
37 }
38
39 pub fn parse_error(msg: impl fmt::Display) -> Self {
41 Self::new(format!("Parse error: {}", msg), "PARSE_ERROR")
42 }
43
44 pub fn validation_error(msg: impl fmt::Display) -> Self {
46 Self::new(format!("Validation error: {}", msg), "VALIDATION_ERROR")
47 }
48
49 pub fn internal_error(msg: impl fmt::Display) -> Self {
51 Self::new(format!("Internal server error: {}", msg), "INTERNAL_ERROR")
52 }
53
54 pub fn unauthorized() -> Self {
56 Self::new("Unauthorized", "UNAUTHORIZED")
57 }
58
59 pub fn not_found(msg: impl fmt::Display) -> Self {
61 Self::new(format!("Not found: {}", msg), "NOT_FOUND")
62 }
63}
64
65impl fmt::Display for ApiError {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "{}: {}", self.code, self.error)
68 }
69}
70
71impl IntoResponse for ApiError {
72 fn into_response(self) -> Response {
73 let status = match self.code.as_str() {
74 "UNAUTHORIZED" => StatusCode::UNAUTHORIZED,
75 "NOT_FOUND" => StatusCode::NOT_FOUND,
76 "VALIDATION_ERROR" | "PARSE_ERROR" => StatusCode::BAD_REQUEST,
77 _ => StatusCode::INTERNAL_SERVER_ERROR,
78 };
79
80 (status, Json(self)).into_response()
81 }
82}
83
84#[derive(Debug, Serialize, Deserialize)]
86pub struct ApiResponse<T> {
87 pub status: String,
89 pub data: T,
91}
92
93impl<T: Serialize> ApiResponse<T> {
94 pub fn success(data: T) -> Json<Self> {
96 Json(Self {
97 status: "success".to_string(),
98 data,
99 })
100 }
101}
102
103#[derive(Debug, Serialize, Deserialize, Clone)]
108pub struct SanitizedConfig {
109 pub port: u16,
111
112 pub host: String,
114
115 pub workers: Option<usize>,
117
118 pub tls_enabled: bool,
120
121 pub sanitized: bool,
123}
124
125impl SanitizedConfig {
126 pub fn from_config(config: &crate::config::HttpServerConfig) -> Self {
133 Self {
134 port: config.port,
135 host: config.host.clone(),
136 workers: config.workers,
137 tls_enabled: config.tls.is_some(),
138 sanitized: true,
139 }
140 }
141
142 pub const fn is_sanitized(&self) -> bool {
144 self.sanitized
145 }
146}