mycelium_openapi/dtos/
operation.rs1use crate::{
2 dtos::{content::Content, parameter::Parameter},
3 entities::{DepthTracker, ReferenceResolver},
4};
5
6use mycelium_base::utils::errors::{execution_err, MappedErrors};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use utoipa::ToSchema;
10
11#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, ToSchema)]
12#[serde(rename_all = "camelCase")]
13pub struct Operation {
14 #[serde(default)]
15 pub operation_id: Option<String>,
16
17 #[serde(default)]
18 pub tags: Vec<String>,
19
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub summary: Option<String>,
22
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub description: Option<String>,
25
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub parameters: Option<Vec<Parameter>>,
28
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub request_body: Option<Content>,
31
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub responses: Option<HashMap<String, Content>>,
34
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub deprecated: Option<bool>,
37
38 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub security: Option<serde_json::Value>,
40}
41
42impl ReferenceResolver for Operation {
43 fn resolve_ref(
44 &self,
45 components: &serde_json::Value,
46 depth_tracker: &mut DepthTracker,
47 ) -> Result<serde_json::Value, MappedErrors> {
48 if depth_tracker.should_stop() {
49 return Ok(depth_tracker.empty_value());
50 }
51
52 depth_tracker.increment();
53
54 let mut value = serde_json::to_value(self).map_err(|e| {
55 execution_err(format!("Failed to resolve operation: {e}"))
56 })?;
57
58 if let Some(parameters) = self.parameters.as_ref() {
62 value["parameters"] = if let false = parameters.is_empty() {
63 parameters
64 .iter()
65 .filter_map(|parameter| {
66 let mut tracker_clone = depth_tracker.clone();
71
72 parameter
76 .resolve_ref(components, &mut tracker_clone)
77 .map_err(|e| {
78 execution_err(format!(
79 "Failed to resolve parameter: {e}"
80 ))
81 })
82 .ok()
83 })
84 .collect::<Vec<serde_json::Value>>()
85 .into()
86 } else {
87 depth_tracker.empty_value()
88 };
89 }
90
91 if let Some(request_body) = self.request_body.as_ref() {
95 value["requestBody"] =
96 request_body.resolve_ref(components, depth_tracker)?;
97 }
98
99 if let Some(responses) = self.responses.as_ref() {
103 let mut responses_value = serde_json::Map::new();
104
105 for (key, response) in responses {
106 let resolved =
107 response.resolve_ref(components, depth_tracker)?;
108
109 responses_value.insert(key.clone(), resolved);
110 }
111
112 value["responses"] = serde_json::Value::Object(responses_value);
113 }
114
115 Ok(value)
116 }
117}