1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct OpenApiConfig {
7 pub openapi_version: String,
9
10 pub info: ApiInfo,
12
13 pub servers: Vec<ServerConfig>,
15
16 pub security_schemes: HashMap<String, SecurityScheme>,
18
19 pub tags: Vec<TagConfig>,
21
22 pub external_docs: Option<ExternalDocs>,
24
25 pub include_examples: bool,
27
28 pub nullable_optional: bool,
30
31 pub custom_schemas: HashMap<String, String>,
33
34 pub export: ExportConfig,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct ApiInfo {
41 pub title: String,
43
44 pub description: Option<String>,
46
47 pub version: String,
49
50 pub terms_of_service: Option<String>,
52
53 pub contact: Option<Contact>,
55
56 pub license: Option<License>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct Contact {
63 pub name: Option<String>,
64 pub url: Option<String>,
65 pub email: Option<String>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct License {
71 pub name: String,
72 pub url: Option<String>,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ServerConfig {
78 pub url: String,
79 pub description: Option<String>,
80 pub variables: Option<HashMap<String, ServerVariable>>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct ServerVariable {
86 pub default: String,
87 pub description: Option<String>,
88 pub r#enum: Option<Vec<String>>,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
93#[serde(tag = "type", rename_all = "camelCase")]
94pub enum SecurityScheme {
95 #[serde(rename = "http")]
96 Http {
97 scheme: String,
98 bearer_format: Option<String>,
99 },
100 #[serde(rename = "apiKey")]
101 ApiKey { name: String, r#in: String },
102 #[serde(rename = "oauth2")]
103 OAuth2 { flows: OAuth2Flows },
104 #[serde(rename = "openIdConnect")]
105 OpenIdConnect { open_id_connect_url: String },
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct OAuth2Flows {
111 pub authorization_code: Option<OAuth2Flow>,
112 pub implicit: Option<OAuth2Flow>,
113 pub password: Option<OAuth2Flow>,
114 pub client_credentials: Option<OAuth2Flow>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct OAuth2Flow {
120 pub authorization_url: Option<String>,
121 pub token_url: Option<String>,
122 pub refresh_url: Option<String>,
123 pub scopes: HashMap<String, String>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct TagConfig {
129 pub name: String,
130 pub description: Option<String>,
131 pub external_docs: Option<ExternalDocs>,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct ExternalDocs {
137 pub url: String,
138 pub description: Option<String>,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct ExportConfig {
144 pub formats: Vec<ExportFormat>,
146
147 pub validate: bool,
149
150 pub pretty_print: bool,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156#[serde(rename_all = "lowercase")]
157pub enum ExportFormat {
158 Json,
159 Yaml,
160 Postman,
161 Insomnia,
162}
163
164impl Default for OpenApiConfig {
165 fn default() -> Self {
166 Self {
167 openapi_version: "3.0.3".to_string(),
168 info: ApiInfo {
169 title: "API Documentation".to_string(),
170 description: Some("Auto-generated API documentation".to_string()),
171 version: "1.0.0".to_string(),
172 terms_of_service: None,
173 contact: None,
174 license: Some(License {
175 name: "MIT".to_string(),
176 url: Some("https://opensource.org/licenses/MIT".to_string()),
177 }),
178 },
179 servers: vec![ServerConfig {
180 url: "http://localhost:3000".to_string(),
181 description: Some("Development server".to_string()),
182 variables: None,
183 }],
184 security_schemes: {
185 let mut schemes = HashMap::new();
186 schemes.insert(
187 "bearerAuth".to_string(),
188 SecurityScheme::Http {
189 scheme: "bearer".to_string(),
190 bearer_format: Some("JWT".to_string()),
191 },
192 );
193 schemes
194 },
195 tags: Vec::new(),
196 external_docs: None,
197 include_examples: true,
198 nullable_optional: true,
199 custom_schemas: HashMap::new(),
200 export: ExportConfig {
201 formats: vec![ExportFormat::Json, ExportFormat::Yaml],
202 validate: true,
203 pretty_print: true,
204 },
205 }
206 }
207}
208
209impl OpenApiConfig {
210 pub fn new(title: &str, version: &str) -> Self {
212 let mut config = Self::default();
213 config.info.title = title.to_string();
214 config.info.version = version.to_string();
215 config
216 }
217
218 pub fn add_server(mut self, url: &str, description: Option<&str>) -> Self {
220 self.servers.push(ServerConfig {
221 url: url.to_string(),
222 description: description.map(|s| s.to_string()),
223 variables: None,
224 });
225 self
226 }
227
228 pub fn add_security_scheme(mut self, name: &str, scheme: SecurityScheme) -> Self {
230 self.security_schemes.insert(name.to_string(), scheme);
231 self
232 }
233
234 pub fn add_tag(mut self, name: &str, description: Option<&str>) -> Self {
236 self.tags.push(TagConfig {
237 name: name.to_string(),
238 description: description.map(|s| s.to_string()),
239 external_docs: None,
240 });
241 self
242 }
243}