openzeppelin_relayer/models/
api_response.rs

1use serde::{Deserialize, Serialize};
2use utoipa::ToSchema;
3
4use crate::services::plugins::LogEntry;
5
6#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
7pub struct PaginationMeta {
8    pub current_page: u32,
9    pub per_page: u32,
10    pub total_items: u64,
11}
12
13#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
14pub struct PluginMetadata {
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub logs: Option<Vec<LogEntry>>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub traces: Option<Vec<serde_json::Value>>,
19}
20
21#[derive(Serialize, Deserialize, ToSchema)]
22pub struct ApiResponse<T> {
23    pub success: bool,
24    pub data: Option<T>,
25    #[schema(nullable = false)]
26    pub error: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    #[schema(nullable = false)]
29    pub pagination: Option<PaginationMeta>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    #[schema(nullable = false)]
32    pub metadata: Option<PluginMetadata>,
33}
34
35#[allow(dead_code)]
36impl<T> ApiResponse<T> {
37    pub fn new(data: Option<T>, error: Option<String>, pagination: Option<PaginationMeta>) -> Self {
38        Self {
39            success: error.is_none(),
40            data,
41            error,
42            pagination,
43            metadata: None,
44        }
45    }
46
47    pub fn success(data: T) -> Self {
48        Self {
49            success: true,
50            data: Some(data),
51            error: None,
52            pagination: None,
53            metadata: None,
54        }
55    }
56
57    pub fn error(message: impl Into<String>) -> Self {
58        Self {
59            success: false,
60            data: None,
61            error: Some(message.into()),
62            pagination: None,
63            metadata: None,
64        }
65    }
66
67    pub fn no_data() -> Self {
68        Self {
69            success: true,
70            data: None,
71            error: None,
72            pagination: None,
73            metadata: None,
74        }
75    }
76
77    pub fn paginated(data: T, meta: PaginationMeta) -> Self {
78        Self {
79            success: true,
80            data: Some(data),
81            error: None,
82            pagination: Some(meta),
83            metadata: None,
84        }
85    }
86
87    pub fn with_metadata(data: T, metadata: PluginMetadata) -> Self {
88        Self {
89            success: true,
90            data: Some(data),
91            error: None,
92            pagination: None,
93            metadata: Some(metadata),
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_new_with_data() {
104        let data = "test data";
105        let response = ApiResponse::new(Some(data), None, None);
106
107        assert!(response.success);
108        assert_eq!(response.data, Some(data));
109        assert_eq!(response.error, None);
110        assert_eq!(response.pagination, None);
111    }
112
113    #[test]
114    fn test_new_with_error() {
115        let error = "test error";
116        let response: ApiResponse<()> = ApiResponse::new(None, Some(error.to_string()), None);
117
118        assert!(!response.success);
119        assert_eq!(response.data, None);
120        assert_eq!(response.error, Some(error.to_string()));
121        assert_eq!(response.pagination, None);
122    }
123
124    #[test]
125    fn test_success() {
126        let data = "test data";
127        let response = ApiResponse::success(data);
128
129        assert!(response.success);
130        assert_eq!(response.data, Some(data));
131        assert_eq!(response.error, None);
132        assert_eq!(response.pagination, None);
133    }
134
135    #[test]
136    fn test_error() {
137        let error = "test error";
138        let response: ApiResponse<()> = ApiResponse::error(error);
139
140        assert!(!response.success);
141        assert_eq!(response.data, None);
142        assert_eq!(response.error, Some(error.to_string()));
143        assert_eq!(response.pagination, None);
144    }
145
146    #[test]
147    fn test_no_data() {
148        let response: ApiResponse<String> = ApiResponse::no_data();
149
150        assert!(response.success);
151        assert_eq!(response.data, None);
152        assert_eq!(response.error, None);
153        assert_eq!(response.pagination, None);
154    }
155
156    #[test]
157    fn test_paginated() {
158        let data = "test data";
159        let pagination = PaginationMeta {
160            current_page: 1,
161            per_page: 10,
162            total_items: 100,
163        };
164
165        let response = ApiResponse::paginated(data, pagination.clone());
166
167        assert!(response.success);
168        assert_eq!(response.data, Some(data));
169        assert_eq!(response.error, None);
170        assert_eq!(response.pagination, Some(pagination));
171    }
172}