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