Skip to main content

wae_schema/openapi/
mod.rs

1//! OpenAPI 相关功能
2
3use serde::{Deserialize, Serialize};
4
5mod components;
6mod paths;
7mod security;
8
9pub use components::*;
10pub use paths::*;
11pub use security::*;
12
13/// OpenAPI 文档信息
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct OpenApiInfo {
16    /// API 标题
17    pub title: String,
18    /// API 版本
19    pub version: String,
20    /// API 描述
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub description: Option<String>,
23    /// 服务条款 URL
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub terms_of_service: Option<String>,
26    /// 联系信息
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub contact: Option<Contact>,
29    /// 许可信息
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub license: Option<License>,
32}
33
34impl Default for OpenApiInfo {
35    /// 创建默认的 OpenAPI 信息
36    fn default() -> Self {
37        Self {
38            title: "API".to_string(),
39            version: "1.0.0".to_string(),
40            description: None,
41            terms_of_service: None,
42            contact: None,
43            license: None,
44        }
45    }
46}
47
48/// 联系信息
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct Contact {
51    /// 联系人姓名
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub name: Option<String>,
54    /// 联系人邮箱
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub email: Option<String>,
57    /// 联系人 URL
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub url: Option<String>,
60}
61
62/// 许可信息
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct License {
65    /// 许可证名称
66    pub name: String,
67    /// 许可证 URL
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub url: Option<String>,
70}
71
72/// 外部文档定义
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct ExternalDocumentation {
75    /// 外部文档 URL
76    pub url: String,
77    /// 外部文档描述
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub description: Option<String>,
80}
81
82/// 标签定义
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct Tag {
85    /// 标签名称
86    pub name: String,
87    /// 标签描述
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub description: Option<String>,
90    /// 标签的外部文档
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub external_docs: Option<ExternalDocumentation>,
93}
94
95/// 服务器定义
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct Server {
98    /// 服务器 URL
99    pub url: String,
100    /// 服务器描述
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub description: Option<String>,
103    /// 服务器变量
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub variables: Option<std::collections::BTreeMap<String, ServerVariable>>,
106}
107
108/// 服务器变量
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct ServerVariable {
111    /// 默认值
112    pub default: String,
113    /// 枚举值
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub enum_values: Option<Vec<String>>,
116    /// 描述
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub description: Option<String>,
119}
120
121/// OpenAPI 文档
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct OpenApiDoc {
124    /// OpenAPI 版本
125    pub openapi: String,
126    /// API 信息
127    pub info: OpenApiInfo,
128    /// 路径定义
129    pub paths: std::collections::BTreeMap<String, PathItem>,
130    /// 组件定义
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub components: Option<Components>,
133    /// 服务器列表
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub servers: Option<Vec<Server>>,
136    /// 标签列表
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub tags: Option<Vec<Tag>>,
139    /// 外部文档
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub external_docs: Option<ExternalDocumentation>,
142    /// 安全要求
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub security: Option<Vec<SecurityRequirement>>,
145}
146
147impl Default for OpenApiDoc {
148    /// 创建默认的 OpenAPI 文档
149    fn default() -> Self {
150        Self {
151            openapi: "3.1.0".to_string(),
152            info: OpenApiInfo::default(),
153            paths: std::collections::BTreeMap::new(),
154            components: None,
155            servers: None,
156            tags: None,
157            external_docs: None,
158            security: None,
159        }
160    }
161}
162
163impl OpenApiDoc {
164    /// 创建新的 OpenAPI 文档
165    pub fn new(title: impl Into<String>, version: impl Into<String>) -> Self {
166        Self { info: OpenApiInfo { title: title.into(), version: version.into(), ..Default::default() }, ..Default::default() }
167    }
168
169    /// 设置描述
170    pub fn description(mut self, desc: impl Into<String>) -> Self {
171        self.info.description = Some(desc.into());
172        self
173    }
174
175    /// 添加路径
176    pub fn path(mut self, path: impl Into<String>, item: PathItem) -> Self {
177        self.paths.insert(path.into(), item);
178        self
179    }
180
181    /// 添加 Schema 组件
182    pub fn schema(mut self, name: impl Into<String>, schema: crate::Schema) -> Self {
183        let components = self.components.get_or_insert_with(Components::default);
184        components.schemas.insert(name.into(), schema);
185        self
186    }
187
188    /// 添加安全方案组件
189    pub fn security_scheme(mut self, name: impl Into<String>, scheme: SecurityScheme) -> Self {
190        let components = self.components.get_or_insert_with(Components::default);
191        components.security_schemes.insert(name.into(), scheme);
192        self
193    }
194
195    /// 添加响应组件
196    pub fn response(mut self, name: impl Into<String>, response: Response) -> Self {
197        let components = self.components.get_or_insert_with(Components::default);
198        components.responses.insert(name.into(), response);
199        self
200    }
201
202    /// 添加参数组件
203    pub fn parameter(mut self, name: impl Into<String>, parameter: Parameter) -> Self {
204        let components = self.components.get_or_insert_with(Components::default);
205        components.parameters.insert(name.into(), parameter);
206        self
207    }
208
209    /// 添加请求体组件
210    pub fn request_body(mut self, name: impl Into<String>, body: RequestBody) -> Self {
211        let components = self.components.get_or_insert_with(Components::default);
212        components.request_bodies.insert(name.into(), body);
213        self
214    }
215
216    /// 添加服务器
217    pub fn server(mut self, url: impl Into<String>, description: Option<String>) -> Self {
218        let servers = self.servers.get_or_insert_with(Vec::new);
219        servers.push(Server { url: url.into(), description, variables: None });
220        self
221    }
222
223    /// 添加标签
224    pub fn tag(mut self, name: impl Into<String>, description: Option<String>) -> Self {
225        let tags = self.tags.get_or_insert_with(Vec::new);
226        tags.push(Tag { name: name.into(), description, external_docs: None });
227        self
228    }
229
230    /// 设置外部文档
231    pub fn external_docs(mut self, url: impl Into<String>, description: Option<String>) -> Self {
232        self.external_docs = Some(ExternalDocumentation { url: url.into(), description });
233        self
234    }
235
236    /// 设置安全要求
237    pub fn security(mut self, security: SecurityRequirement) -> Self {
238        let securities = self.security.get_or_insert_with(Vec::new);
239        securities.push(security);
240        self
241    }
242
243    /// 转换为 JSON
244    pub fn to_json(&self) -> serde_json::Value {
245        serde_json::to_value(self).unwrap_or(serde_json::Value::Null)
246    }
247
248    /// 转换为 YAML
249    #[cfg(feature = "yaml")]
250    pub fn to_yaml(&self) -> String {
251        serde_yaml::to_string(self).unwrap_or_default()
252    }
253}