Skip to content

Commit

Permalink
v0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kshyr committed Mar 24, 2024
1 parent 5c4bb9a commit 57de11b
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 58 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
openapi.json
.env
types.js
.env
147 changes: 137 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
[package]
name = "openapi-to-jsdoc"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
description = "Generate JSDoc typedefs from OpenAPI 3.0.x spec schemas"
license = "MIT"
repository = "https://github.com/kshyr/openapi-to-jsdoc"


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dotenv = "0.15.0"
oas3 = "0.4"
reqwest = { version = "0.12", features = ["json", "blocking"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }
clap = { version = "4.5.3", features = ["derive"] }
oas3 = "0.4.0"
openapiv3-extended = "6.0.0"
reqwest = { version = "0.12.1", features = ["json", "blocking"] }
serde_json = "1.0.114"
tokio = { version = "1.36.0", features = ["full"] }
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
### Environmental variables (`.env`)
### Usage

```
OPENAPI_JSON_URL = "https://api.example.com/openapi.json"
```
`cargo install openapi-to-jsdoc`
17 changes: 15 additions & 2 deletions src/jsdoc/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ impl JSDocBuilder {
}

pub fn build(&mut self) -> String {
self.add_line("*/");
self.doc.push_str(" */\n");
self.doc.clone()
}
}

mod tests {
use std::fs;

use super::*;

#[test]
Expand All @@ -48,6 +50,17 @@ mod tests {
jsdoc.add_line("This is a test");
jsdoc.add_line("let a = 1;");
let section = jsdoc.build();
assert_eq!(section, "/**\n * This is a test\n * let a = 1;\n * */\n");
assert_eq!(section, "/**\n * This is a test\n * let a = 1;\n */\n");
}

#[test]
fn build_typedef() {
let mut jsdoc = JSDocBuilder::new();
jsdoc.add_tag_line(JSDocTag::Typedef, "{Object} Meeting");
jsdoc.add_tag_line(JSDocTag::Property, "{string} name");
jsdoc.add_tag_line(JSDocTag::Property, "{string} date");
let section = jsdoc.build();
let expected = "/**\n * @typedef {Object} Meeting\n * @property {string} name\n * @property {string} date\n */\n";
assert_eq!(section, expected);
}
}
82 changes: 82 additions & 0 deletions src/jsdoc/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,83 @@
use std::fs;

use openapiv3::{OpenAPI, RefOr, SchemaKind, Type};

pub mod builder;

pub fn generate_typedef(file: String, spec: &OpenAPI, schema_name: &str) -> String {
let mut jsdoc = builder::JSDocBuilder::new();
let schema = spec
.components
.schemas
.get(schema_name)
.expect("Schema not found")
.as_item() // This is safe because we know the schema exists and it's not a reference
.unwrap();

jsdoc.add_tag_line(
builder::JSDocTag::Typedef,
&format!("{{Object}} {}", schema_name),
);

for (prop_name, prop) in schema.properties() {
let prop_type = match prop {
RefOr::Reference { reference } => reference
.strip_prefix("#/components/schemas/")
.unwrap()
.to_string(),
RefOr::Item(item) => match &item.kind {
SchemaKind::Type(t) => match t {
Type::String(_) => "string".to_string(),
Type::Number(_) => "number".to_string(),
Type::Integer(_) => "number".to_string(),
Type::Boolean {} => "boolean".to_string(),
Type::Object(_) => "Object".to_string(),
Type::Array(array) => {
let item = *array.items.clone().unwrap();
let item_type: String = match item {
RefOr::Reference { reference } => {
let mut reference = reference
.strip_prefix("#/components/schemas/")
.unwrap()
.to_string();
reference.push_str("[]");
reference
}
RefOr::Item(item) => match &item.kind {
SchemaKind::Type(t) => match t {
Type::String(_) => "string[]".to_string(),
Type::Number(_) => "number[]".to_string(),
Type::Integer(_) => "number[]".to_string(),
Type::Boolean {} => "boolean[]".to_string(),
Type::Object(_) => "Object[]".to_string(),
_ => todo!(),
},
_ => todo!(),
},
};
item_type
}
},
_ => todo!(),
},
};

let prop_name = if schema.get_required().unwrap().contains(prop_name) {
prop_name.to_string()
} else {
format!("[{}]", prop_name)
};

jsdoc.add_tag_line(
builder::JSDocTag::Property,
&format!("{{{}}} {}", prop_type, prop_name),
);
}
if fs::File::open(&file).is_err() {
fs::write(&file, "").unwrap();
}
let file_contents = fs::read_to_string(&file).unwrap();
let doc = format!("{}\n{}", &file_contents, jsdoc.build().as_str());
fs::write(file, &doc).unwrap();
doc
}
Loading

0 comments on commit 57de11b

Please sign in to comment.