Skip to main content

openapi_ops_mut/
lib.rs

1use openapiv3::{OpenAPI, Operation, ReferenceOr};
2
3/// Newtype wrapper around `OpenAPI` to provide mutable operations iterator.
4pub struct OpenAPIExt<'a> {
5    pub openapi: &'a mut OpenAPI,
6}
7
8impl OpenAPIExt<'_> {
9    pub fn new(openapi: &mut OpenAPI) -> OpenAPIExt {
10        OpenAPIExt { openapi }
11    }
12
13    /// Mutably iterates through all [Operation]s in this API.
14    ///
15    /// The iterated items are tuples of `(&str, &str, &mut Operation)` containing
16    /// the path, method, and the operation.
17    ///
18    /// Path items containing `$ref`s are skipped.
19    pub fn operations_mut(&mut self) -> impl Iterator<Item = (&str, &str, &mut Operation)> {
20        self.openapi
21            .paths
22            .paths
23            .iter_mut()
24            .filter_map(|(path, item)| match *item {
25                ReferenceOr::Item(ref mut path_item) => Some((path, path_item)),
26                ReferenceOr::Reference { .. } => None,
27            })
28            .flat_map(|(path, path_item)| {
29                vec![
30                    (path.as_str(), "get", &mut path_item.get),
31                    (path.as_str(), "put", &mut path_item.put),
32                    (path.as_str(), "post", &mut path_item.post),
33                    (path.as_str(), "delete", &mut path_item.delete),
34                    (path.as_str(), "options", &mut path_item.options),
35                    (path.as_str(), "head", &mut path_item.head),
36                    (path.as_str(), "patch", &mut path_item.patch),
37                    (path.as_str(), "trace", &mut path_item.trace),
38                ]
39                .into_iter()
40                .filter_map(|(path, method, maybe_op)| {
41                    maybe_op.as_mut().map(|op| (path, method, op))
42                })
43            })
44    }
45}
46
47#[test]
48fn test_add_operation_ids() {
49    const SCHEMA: &str = r#"
50{
51    "openapi": "3.0.0",
52    "info": {
53        "title": "Test API",
54        "version": "1.0.0"
55    },
56    "paths": {
57        "/foo": {
58            "get": {
59                "responses": {}
60            }
61        }
62    }
63}
64"#;
65
66    let mut openapi: OpenAPI = serde_json::from_str(SCHEMA).unwrap();
67    let mut oa_ext = OpenAPIExt::new(&mut openapi);
68    for (path, method, op) in oa_ext.operations_mut() {
69        op.operation_id = Some(format!("{}_{}", path, method));
70    }
71
72    assert_eq!(
73        openapi.paths.paths["/foo"]
74            .as_item()
75            .unwrap()
76            .get
77            .as_ref()
78            .unwrap()
79            .operation_id,
80        Some("/foo_get".to_string())
81    );
82}