Skip to main content

nestforge_core/
response.rs

1use axum::{
2    response::{IntoResponse, Response},
3    Json,
4};
5use http::StatusCode;
6use serde::Serialize;
7use serde_json::json;
8
9use crate::HttpException;
10
11pub trait ResponseSerializer<T>: Send + Sync + 'static {
12    type Output: Serialize;
13
14    fn serialize(value: T) -> Self::Output;
15}
16
17#[derive(Debug, Clone, Serialize)]
18pub struct ResponseEnvelope<T> {
19    pub success: bool,
20    pub data: T,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub meta: Option<serde_json::Value>,
23}
24
25pub struct Serialized<T, S>
26where
27    S: ResponseSerializer<T>,
28{
29    value: T,
30    _marker: std::marker::PhantomData<S>,
31}
32
33impl<T, S> Serialized<T, S>
34where
35    S: ResponseSerializer<T>,
36{
37    pub fn new(value: T) -> Self {
38        Self {
39            value,
40            _marker: std::marker::PhantomData,
41        }
42    }
43}
44
45impl<T> ResponseEnvelope<T> {
46    pub fn ok(data: T) -> Self {
47        Self {
48            success: true,
49            data,
50            meta: None,
51        }
52    }
53
54    pub fn with_meta(mut self, meta: impl Into<serde_json::Value>) -> Self {
55        self.meta = Some(meta.into());
56        self
57    }
58
59    pub fn paginated(data: T, page: u64, per_page: u64, total: u64) -> Self {
60        Self::ok(data).with_meta(json!({
61            "page": page,
62            "per_page": per_page,
63            "total": total,
64        }))
65    }
66}
67
68impl<T> IntoResponse for ResponseEnvelope<T>
69where
70    T: Serialize,
71{
72    fn into_response(self) -> Response {
73        (StatusCode::OK, Json(self)).into_response()
74    }
75}
76
77impl<T, S> IntoResponse for Serialized<T, S>
78where
79    S: ResponseSerializer<T>,
80{
81    fn into_response(self) -> Response {
82        (StatusCode::OK, Json(S::serialize(self.value))).into_response()
83    }
84}
85
86pub type ApiEnvelopeResult<T> = Result<ResponseEnvelope<T>, HttpException>;
87pub type ApiSerializedResult<T, S> = Result<Serialized<T, S>, HttpException>;