openapi_merge/
merge.rs

1use super::*;
2
3#[derive(Debug, Default)]
4pub struct Merge {
5    pub config: MergeConfig,
6    pub merged: OpenAPI,
7    pub merge_time: time::Duration,
8    pub save_time: time::Duration,
9}
10
11impl Merge {
12    pub fn merge(mut self) -> io::Result<Self> {
13        let now = time::Instant::now();
14        let mut inputs = self.config.inputs.drain(..);
15        // Use first element is a base for merging
16        let base = inputs
17            .next()
18            .ok_or(io::Error::other("At least one input required"))?;
19        let merged = inputs.fold(base, merge_into_base).openapi;
20        let merge_time = now.elapsed();
21
22        Ok(Self {
23            merged,
24            merge_time,
25            ..self
26        })
27    }
28
29    pub fn save(self) -> io::Result<Self> {
30        let now = time::Instant::now();
31        let path = self.config.output();
32        save_json_file(&path, &self.merged)?;
33        let save_time = now.elapsed();
34
35        Ok(Self { save_time, ..self })
36    }
37}
38
39impl From<MergeConfig> for Merge {
40    fn from(config: MergeConfig) -> Self {
41        Self {
42            config,
43            ..default()
44        }
45    }
46}
47
48fn merge_into_base(base: Input, mut other: Input) -> Input {
49    tracing::info!(other = %other.source, "Processing");
50
51    let mut openapi = base.openapi;
52    openapi.merge_components(other.components());
53    openapi.merge_security(other.security());
54    openapi.merge_tags(other.tags());
55    openapi.merge_extensions(other.extensions());
56
57    for (path, method, operation) in other.operations() {
58        openapi.merge_operation(path, method, operation);
59    }
60
61    Input { openapi, ..base }
62}