1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ApiResponse<T> {
11 pub success: bool,
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub data: Option<T>,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub error: Option<ApiError>,
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub meta: Option<HashMap<String, serde_json::Value>>,
22}
23
24impl<T> ApiResponse<T> {
25 pub fn success(data: T) -> Self {
27 Self {
28 success: true,
29 data: Some(data),
30 error: None,
31 meta: None,
32 }
33 }
34
35 pub fn success_with_meta(data: T, meta: HashMap<String, serde_json::Value>) -> Self {
37 Self {
38 success: true,
39 data: Some(data),
40 error: None,
41 meta: Some(meta),
42 }
43 }
44
45 pub fn error(error: ApiError) -> Self {
47 Self {
48 success: false,
49 data: None,
50 error: Some(error),
51 meta: None,
52 }
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ApiError {
59 pub code: String,
61 pub message: String,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub details: Option<HashMap<String, serde_json::Value>>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub suggestions: Option<Vec<String>>,
69}
70
71impl ApiError {
72 pub fn new<S: Into<String>>(code: S, message: S) -> Self {
74 Self {
75 code: code.into(),
76 message: message.into(),
77 details: None,
78 suggestions: None,
79 }
80 }
81
82 pub fn with_details(mut self, details: HashMap<String, serde_json::Value>) -> Self {
84 self.details = Some(details);
85 self
86 }
87
88 pub fn with_suggestions(mut self, suggestions: Vec<String>) -> Self {
90 self.suggestions = Some(suggestions);
91 self
92 }
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct ProviderInfo {
98 pub name: String,
99 pub version: String,
100 pub description: String,
101 pub author: Option<String>,
102 pub license: Option<String>,
103 pub features: Vec<FeatureInfo>,
104 pub file_path: Option<String>,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct FeatureInfo {
110 pub name: String,
111 pub description: String,
112 pub version: String,
113 pub operations: Vec<OperationInfo>,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct OperationInfo {
119 pub name: String,
120 pub description: String,
121 pub arguments: Vec<ArgumentInfo>,
122 pub return_type: String,
123 pub is_mutating: bool,
124 pub estimated_duration_ms: Option<u64>,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct ArgumentInfo {
130 pub name: String,
131 pub argument_type: String,
132 pub description: String,
133 pub required: bool,
134 pub default_value: Option<serde_json::Value>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct ExecutionResult {
140 pub result: serde_json::Value,
141 pub execution_time_ms: u64,
142 pub provider: String,
143 pub feature: String,
144 pub operation: String,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct HealthStatus {
150 pub status: String,
151 pub version: String,
152 pub uptime_seconds: u64,
153 pub providers_loaded: usize,
154 pub total_features: usize,
155 pub total_operations: usize,
156 pub memory_usage_mb: f64,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct DiscoveryResponse {
162 pub total_providers: usize,
163 pub total_features: usize,
164 pub total_operations: usize,
165 pub providers: Vec<ProviderSummary>,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct ProviderSummary {
171 pub name: String,
172 pub version: String,
173 pub description: String,
174 pub features: Vec<FeatureSummary>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct FeatureSummary {
180 pub name: String,
181 pub description: String,
182 pub operations: Vec<String>,
183}
184
185impl From<crate::providers::ProviderMetadata> for ProviderInfo {
187 fn from(metadata: crate::providers::ProviderMetadata) -> Self {
188 Self {
189 name: metadata.name,
190 version: metadata.version,
191 description: metadata.description,
192 author: metadata.author,
193 license: metadata.license,
194 features: metadata.features.into_iter().map(Into::into).collect(),
195 file_path: metadata.file_path,
196 }
197 }
198}
199
200impl From<crate::providers::FeatureMetadata> for FeatureInfo {
201 fn from(metadata: crate::providers::FeatureMetadata) -> Self {
202 Self {
203 name: metadata.name,
204 description: metadata.description,
205 version: metadata.version,
206 operations: metadata.operations.into_iter().map(Into::into).collect(),
207 }
208 }
209}
210
211impl From<crate::providers::OperationMetadata> for OperationInfo {
212 fn from(metadata: crate::providers::OperationMetadata) -> Self {
213 Self {
214 name: metadata.name,
215 description: metadata.description,
216 arguments: metadata.arguments.into_iter().map(Into::into).collect(),
217 return_type: metadata.return_type,
218 is_mutating: metadata.is_mutating,
219 estimated_duration_ms: metadata.estimated_duration_ms,
220 }
221 }
222}
223
224impl From<crate::providers::ArgumentMetadata> for ArgumentInfo {
225 fn from(metadata: crate::providers::ArgumentMetadata) -> Self {
226 Self {
227 name: metadata.name,
228 argument_type: format!("{:?}", metadata.arg_type), description: metadata.description,
230 required: metadata.required,
231 default_value: metadata.default_value,
232 }
233 }
234}