diff --git a/Cargo.lock b/Cargo.lock index ca42483..7c29559 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,7 +670,7 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openapi-to-jsdoc" -version = "0.1.2" +version = "0.1.3" dependencies = [ "clap", "oas3", diff --git a/Cargo.toml b/Cargo.toml index 2dd07d6..a6dd565 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openapi-to-jsdoc" -version = "0.1.2" +version = "0.1.3" edition = "2021" description = "Generate JSDoc typedefs from OpenAPI 3.0.x spec schemas" license = "MIT" diff --git a/src/jsdoc/mod.rs b/src/jsdoc/mod.rs index 940260b..ce83677 100644 --- a/src/jsdoc/mod.rs +++ b/src/jsdoc/mod.rs @@ -26,39 +26,39 @@ pub fn generate_typedef(file: String, spec: &OpenAPI, schema_name: &str) -> Stri .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 + SchemaKind::Type(t) => get_prop_type(t), + SchemaKind::OneOf { one_of } => { + // union type + let mut union = String::new(); + for (i, item) in one_of.iter().enumerate() { + let item_type = get_item_type(item); + let union_sign = if i == one_of.len() - 1 { "" } else { " | " }; + union.push_str(format!("{} {}", item_type, union_sign).as_str()); } - }, - _ => todo!(), + union + } + SchemaKind::AllOf { all_of } => { + let mut intersection = String::new(); + for (i, item) in all_of.iter().enumerate() { + let item_type = get_item_type(item); + let union_sign = if i == all_of.len() - 1 { "" } else { " & " }; + intersection.push_str(format!("{}{}", item_type, union_sign).as_str()); + } + intersection + } + SchemaKind::AnyOf { any_of } => { + println!(" AnyOf {:?}", any_of); + "Object".to_string() + } + + SchemaKind::Not { not } => { + println!("Not {:?}", not); + "Object".to_string() + } + SchemaKind::Any(_) => { + println!("Any"); + "Object".to_string() + } }, }; @@ -81,3 +81,94 @@ pub fn generate_typedef(file: String, spec: &OpenAPI, schema_name: &str) -> Stri fs::write(file, &doc).unwrap(); doc } + +fn get_item_type(item: &RefOr) -> String { + match item { + RefOr::Reference { reference } => reference + .strip_prefix("#/components/schemas/") + .unwrap() + .to_string(), + RefOr::Item(item) => match &item.kind { + SchemaKind::Type(t) => get_prop_type(t), + _ => todo!(), + }, + } +} + +fn get_prop_type(t: &Type) -> String { + match t { + Type::String(s) => { + let enum_array = s + .enumeration + .iter() + .map(|x| format!(r#""{}""#, x)) + .filter(|x| !x.is_empty()) + .collect(); + if let Some(en) = get_enum_type(&enum_array) { + return en; + } + println!("String {:?}", s); + "string".to_string() + } + Type::Number(n) => { + let enum_array = n + .enumeration + .iter() + .map(|x| { + if let Some(n_inner) = x { + n_inner.to_string() + } else { + "".to_string() + } + }) + .filter(|x| !x.is_empty()) + .collect(); + if let Some(en) = get_enum_type(&enum_array) { + en + } else { + "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 + } + } +} + +fn get_enum_type(enums: &Vec) -> Option { + if enums.is_empty() { + return None; + } + + let mut enum_type = String::new(); + for (i, value) in enums.iter().enumerate() { + let union_sign = if i == enums.len() - 1 { "" } else { " | " }; + enum_type.push_str(format!("{}{}", value, union_sign).as_str()); + } + Some(enum_type) +}