systemprompt_models/api/responses/
envelopes.rs1use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8
9use crate::api::pagination::PaginationInfo;
10
11#[cfg(feature = "web")]
12use axum::Json;
13#[cfg(feature = "web")]
14use axum::http::StatusCode;
15#[cfg(feature = "web")]
16use axum::response::IntoResponse;
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ResponseLinks {
20 pub self_link: String,
21
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub next: Option<String>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub prev: Option<String>,
27
28 pub docs: String,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct ResponseMeta {
33 pub timestamp: DateTime<Utc>,
34
35 pub version: String,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub pagination: Option<PaginationInfo>,
39}
40
41impl ResponseMeta {
42 #[must_use]
43 pub fn new() -> Self {
44 Self {
45 timestamp: Utc::now(),
46 version: "1.0.0".to_owned(),
47 pagination: None,
48 }
49 }
50
51 #[must_use]
52 pub fn with_pagination(mut self, pagination: PaginationInfo) -> Self {
53 self.pagination = Some(pagination);
54 self
55 }
56}
57
58impl Default for ResponseMeta {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64#[derive(Debug, Serialize, Deserialize)]
65pub struct ApiResponse<T>
66where
67 T: 'static,
68{
69 pub data: T,
70
71 pub meta: ResponseMeta,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub links: Option<ResponseLinks>,
75}
76
77impl<T: Serialize + 'static> ApiResponse<T> {
78 pub fn new(data: T) -> Self {
79 Self {
80 data,
81 meta: ResponseMeta::new(),
82 links: None,
83 }
84 }
85
86 #[must_use]
87 pub fn with_links(mut self, links: ResponseLinks) -> Self {
88 self.links = Some(links);
89 self
90 }
91
92 #[must_use]
93 pub fn with_meta(mut self, meta: ResponseMeta) -> Self {
94 self.meta = meta;
95 self
96 }
97}
98
99#[derive(Debug, Serialize, Deserialize)]
100pub struct SingleResponse<T>
101where
102 T: 'static,
103{
104 pub data: T,
105
106 pub meta: ResponseMeta,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
109 pub links: Option<ResponseLinks>,
110}
111
112impl<T: Serialize + 'static> SingleResponse<T> {
113 pub fn new(data: T) -> Self {
114 Self {
115 data,
116 meta: ResponseMeta::new(),
117 links: None,
118 }
119 }
120
121 pub const fn with_meta(data: T, meta: ResponseMeta) -> Self {
122 Self {
123 data,
124 meta,
125 links: None,
126 }
127 }
128
129 #[must_use]
130 pub fn with_links(mut self, links: ResponseLinks) -> Self {
131 self.links = Some(links);
132 self
133 }
134}
135
136#[derive(Debug, Serialize, Deserialize)]
137pub struct CollectionResponse<T>
138where
139 T: 'static,
140{
141 pub data: Vec<T>,
142
143 pub meta: ResponseMeta,
144
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub links: Option<ResponseLinks>,
147}
148
149impl<T: Serialize + 'static> CollectionResponse<T> {
150 pub fn new(data: Vec<T>) -> Self {
151 Self {
152 data,
153 meta: ResponseMeta::new(),
154 links: None,
155 }
156 }
157
158 pub fn paginated(data: Vec<T>, pagination: PaginationInfo) -> Self {
159 Self {
160 data,
161 meta: ResponseMeta::new().with_pagination(pagination),
162 links: None,
163 }
164 }
165
166 #[must_use]
167 pub fn with_links(mut self, links: ResponseLinks) -> Self {
168 self.links = Some(links);
169 self
170 }
171}
172
173#[cfg(feature = "web")]
174impl<T: Serialize + 'static> IntoResponse for SingleResponse<T> {
175 fn into_response(self) -> axum::response::Response {
176 (StatusCode::OK, Json(self)).into_response()
177 }
178}
179
180#[cfg(feature = "web")]
181impl<T: Serialize + 'static> IntoResponse for CollectionResponse<T> {
182 fn into_response(self) -> axum::response::Response {
183 (StatusCode::OK, Json(self)).into_response()
184 }
185}