use crate::codegen::render::graphql::field::FieldDefinitionExt;
use crate::codegen::{context::Context, generate::GenericErrors, render::render::Render};
use async_graphql_parser::types::{TypeDefinition, TypeKind};
use codegen::{Impl, Scope, Struct};
const DENYLIST: [&str; 2] = ["Mutation", "Subscription"];
pub struct ObjectWrapper<'a> {
pub doc: &'a TypeDefinition,
pub context: &'a Context<'a>,
}
impl<'a> ObjectWrapper<'a> {
fn object_name(&self) -> &'a str {
self.doc.name.node.as_str()
}
fn domain_name(&self) -> String {
format!("{}.rs", self.object_name().to_lowercase())
}
pub fn generate_domain_file(&self) -> Result<(), GenericErrors> {
let mut scope = Scope::new();
scope.import("serde", "Serialize");
scope.import("serde", "Deserialize");
let mut object_struct = Struct::new(self.object_name());
object_struct
.vis("pub")
.derive("Serialize")
.derive("Deserialize")
.derive("Debug")
.derive("Default")
.derive("Clone");
let _fields = match &self.doc.kind {
TypeKind::Object(object) => &object.fields,
_ => {
return Err(GenericErrors::GenericGeneratorError);
}
}
.iter()
.filter_map(|x| {
let len = x.node.arguments.len();
if len != 0 {
return None;
}
x.node
.generate_domain_struct(&self.context, &mut scope, &mut object_struct);
Some((&x.node.name.node, &x.node.description))
})
.collect::<Vec<_>>();
scope.push_struct(object_struct);
self.context.create_a_new_file(
format!("domain/{}", &self.domain_name()),
scope.to_string().as_bytes(),
)?;
Ok(())
}
pub fn generate_application_file(&self) -> Result<(), GenericErrors> {
let mut scope = Scope::new();
scope.import("async_graphql", "*");
scope.import(
&format!("crate::domain::{}", self.object_name().to_lowercase()),
self.object_name(),
);
let mut impl_struct = Impl::new(self.object_name());
impl_struct.r#macro("#[Object]");
let _fields = match &self.doc.kind {
TypeKind::Object(object) => &object.fields,
_ => {
return Err(GenericErrors::GenericGeneratorError);
}
}
.iter()
.map(|x| {
let len = x.node.arguments.len();
if len != 0 {
x.node
.generate_method(&self.context, &mut scope, &mut impl_struct);
return None;
}
x.node
.generate_method(&self.context, &mut scope, &mut impl_struct);
Some((&x.node.name.node, &x.node.description))
})
.collect::<Vec<_>>();
scope.push_impl(impl_struct);
self.context.create_a_new_file(
format!("application/{}", &self.domain_name()),
scope.to_string().as_bytes(),
)?;
Ok(())
}
}
impl<'a> Render for ObjectWrapper<'a> {
fn generate(&self) -> Result<(), GenericErrors> {
let object_name = self.doc.name.node.as_str();
if DENYLIST.iter().find(|name| **name == object_name).is_some() {
return Ok(());
};
if object_name.ends_with("Connection") {
return Ok(());
};
if object_name.ends_with("Payload") {
return Ok(());
};
self.generate_domain_file()?;
self.generate_application_file()?;
Ok(())
}
}