use super::SchemaRenderer;
use indexmap::IndexMap;
use miette::IntoDiagnostic;
use schematic_types::*;
use std::fs;
use std::path::Path;
#[derive(Debug, Default)]
pub struct SchemaGenerator {
pub schemas: IndexMap<String, Schema>,
}
impl SchemaGenerator {
pub fn add<T: Schematic>(&mut self) {
let schema = SchemaBuilder::build_root::<T>();
self.add_schema(&schema);
}
pub fn add_schema(&mut self, schema: &Schema) {
let mut schema = schema.to_owned();
match &mut schema.ty {
SchemaType::Array(inner) => {
self.add_schema(&inner.items_type);
}
SchemaType::Object(inner) => {
self.add_schema(&inner.key_type);
self.add_schema(&inner.value_type);
}
SchemaType::Struct(inner) => {
for field in inner.fields.values() {
self.add_schema(&field.schema);
}
}
SchemaType::Tuple(inner) => {
for item in &inner.items_types {
self.add_schema(item);
}
}
SchemaType::Union(inner) => {
for variant in &inner.variants_types {
self.add_schema(variant);
}
}
_ => {}
};
if let Some(name) = &schema.name {
if !self.schemas.contains_key(name) {
self.schemas.insert(name.to_owned(), schema);
}
}
}
pub fn generate<P: AsRef<Path>, O, R: SchemaRenderer<O>>(
&self,
output_file: P,
mut renderer: R,
) -> miette::Result<()> {
let output_file = output_file.as_ref();
let mut output = renderer.render(self.schemas.clone())?;
output.push('\n');
if let Some(parent) = output_file.parent() {
fs::create_dir_all(parent).into_diagnostic()?;
}
fs::write(output_file, output).into_diagnostic()?;
Ok(())
}
}