1pub(crate) mod common;
2pub(crate) mod content;
3pub(crate) mod media_type;
4pub(crate) mod operations;
5pub(crate) mod parameter;
6pub(crate) mod parameters;
7pub(crate) mod path_items;
8pub(crate) mod paths;
9pub(crate) mod request_body;
10pub(crate) mod response;
11pub(crate) mod responses;
12pub(crate) mod schema;
13
14use crate::openapi::OpenAPI;
15use common::StringDiff;
16use paths::PathsDiff;
17use serde::Serialize;
18use std::path::PathBuf;
19use thiserror::Error;
20
21#[derive(Error, Debug)]
23pub enum DiffError {
24 #[error("Unsupported feature: {0}")]
26 UnsupportedFeature(String),
27
28 #[error(transparent)]
30 IOError(#[from] std::io::Error),
31
32 #[error(transparent)]
34 SerdeError(#[from] serde_yaml::Error),
35}
36
37#[derive(Debug, Serialize)]
38pub struct Diff {
39 pub version: Option<StringDiff>,
40 pub paths: PathsDiff,
41}
42
43pub fn diff_files(base: PathBuf, head: PathBuf) -> Result<Diff, DiffError> {
44 let base_contents = std::fs::read_to_string(base)?;
45 let head_contents = std::fs::read_to_string(head)?;
46 let base_openapi: OpenAPI = serde_yaml::from_str(&base_contents)?;
47 let head_openapi: OpenAPI = serde_yaml::from_str(&head_contents)?;
48 diff(base_openapi, head_openapi)
49}
50
51pub fn diff(base: OpenAPI, head: OpenAPI) -> Result<Diff, DiffError> {
52 let version_diff = StringDiff::from_strings(base.openapi, head.openapi);
53 let paths_diff = PathsDiff::from_paths(&base.paths, &head.paths)?;
54 Ok(Diff {
55 version: version_diff,
56 paths: paths_diff,
57 })
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn from_json_files() {
66 let diff = diff_files(
67 PathBuf::from("fixtures/pet-store.json"),
68 PathBuf::from("fixtures/pet-store-changed.json"),
69 )
70 .expect("Failed to diff JSON");
71
72 let version_change = diff.version.unwrap();
73
74 assert_eq!("3.0.0", version_change.from);
75 assert_eq!("3.1.0", version_change.to);
76 }
77
78 #[test]
79 fn from_yaml_files() {
80 let diff = diff_files(
81 PathBuf::from("fixtures/pet-store.yaml"),
82 PathBuf::from("fixtures/pet-store-changed.yaml"),
83 )
84 .expect("Failed to diff JSON");
85
86 let version_change = diff.version.unwrap();
87
88 assert_eq!("3.0.0", version_change.from);
89 assert_eq!("3.1.0", version_change.to);
90 }
91
92 #[test]
93 fn openapi_version_change() {
94 let mut base = OpenAPI::default();
95 base.openapi = String::from("3.0.0");
96 let mut head = OpenAPI::default();
97 head.openapi = String::from("4.0.0");
98
99 let result = diff(base, head);
100 let diff = result.expect("Failed to diff");
101
102 let version_change = diff.version.unwrap();
103
104 assert_eq!("3.0.0", version_change.from);
105 assert_eq!("4.0.0", version_change.to);
106 }
107}