use std::{collections::btree_map::Entry, fs::create_dir_all, io, path::Path};
use brk_query::Vecs;
mod javascript;
mod js;
mod openapi;
mod python;
mod rust;
mod types;
pub use javascript::*;
pub use js::*;
pub use openapi::*;
pub use python::*;
pub use rust::*;
pub use types::*;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub fn generate_clients(vecs: &Vecs, openapi_json: &str, output_dir: &Path) -> io::Result<()> {
let metadata = ClientMetadata::from_vecs(vecs);
let spec = parse_openapi_json(openapi_json)?;
let endpoints = extract_endpoints(&spec);
let mut schemas = extract_schemas(openapi_json);
collect_leaf_type_schemas(&metadata.catalog, &mut schemas);
let schema_values: Vec<_> = schemas.values().cloned().collect();
for schema in &schema_values {
collect_schema_definitions(schema, &mut schemas);
}
let rust_path = output_dir.join("rust");
create_dir_all(&rust_path)?;
generate_rust_client(&metadata, &endpoints, &rust_path)?;
let js_path = output_dir.join("javascript");
create_dir_all(&js_path)?;
generate_javascript_client(&metadata, &endpoints, &schemas, &js_path)?;
let python_path = output_dir.join("python");
create_dir_all(&python_path)?;
generate_python_client(&metadata, &endpoints, &schemas, &python_path)?;
Ok(())
}
use brk_types::TreeNode;
use serde_json::Value;
fn collect_leaf_type_schemas(node: &TreeNode, schemas: &mut TypeSchemas) {
match node {
TreeNode::Leaf(leaf) => {
collect_schema_definitions(&leaf.schema, schemas);
let type_name = extract_inner_type(leaf.value_type());
if let Entry::Vacant(e) = schemas.entry(type_name) {
let schema = unwrap_allof(&leaf.schema);
let has_type = schema.get("type").is_some();
let has_properties = schema.get("properties").is_some();
let has_enum = schema.get("enum").is_some() || schema.get("oneOf").is_some();
let is_ref = schema.get("$ref").is_some();
if has_type || has_properties || has_enum || is_ref {
e.insert(schema.clone());
}
}
}
TreeNode::Branch(children) => {
for child in children.values() {
collect_leaf_type_schemas(child, schemas);
}
}
}
}
fn collect_schema_definitions(schema: &Value, schemas: &mut TypeSchemas) {
if let Some(defs) = schema.get("definitions").and_then(|d| d.as_object()) {
for (name, def_schema) in defs {
if !schemas.contains_key(name) {
schemas.insert(name.clone(), def_schema.clone());
}
}
}
if let Some(defs) = schema.get("$defs").and_then(|d| d.as_object()) {
for (name, def_schema) in defs {
if !schemas.contains_key(name) {
schemas.insert(name.clone(), def_schema.clone());
}
}
}
}