use convert_case::{Case, Casing}; use dagger_core::introspection::{FullTypeFields, FullTypeFieldsArgs}; use genco::{prelude::rust, quote}; use super::{ type_ref::{self, render_type_ref}, utility::{render_description_from_field, render_description_from_input_value}, }; pub fn render_fields(fields: &Vec) -> eyre::Result> { let mut collected_fields: Vec = vec![]; for field in fields.iter() { let name = field.name.as_ref().map(|n| n.to_case(Case::Snake)).unwrap(); let output = render_field_output(field)?; let description = render_description_from_field(field); let args = match field.args.as_ref() { Some(a) => render_args(a), None => None, }; let mut tkns = rust::Tokens::new(); if let Some(args) = args.as_ref() { tkns.append(quote! { $description pub struct $(&name)Args { $(&args.args) } }); tkns.push(); } tkns.append(quote! { pub fn $(&name)( &self, $(if let Some(_) = args.as_ref() => args: $(&name)Args) ) -> $(&output) { let query = self.selection.select($(field.name.as_ref().map(|n| format!("\"{}\"", n)))); $(if let Some(_) = args.as_ref() => query.args(args);) $output { conn: self.conn.clone(), proc: self.proc.clone(), selection: query, } todo!() } }); collected_fields.push(tkns); } Ok(Some(quote! { $(for field in collected_fields => $field $['\n'] ) })) } struct Arg { name: String, description: Option, type_: rust::Tokens, } struct CollectedArgs { description: Option, args: rust::Tokens, } fn render_args(args: &[Option]) -> Option { let mut collected_args: Vec = vec![]; for arg in args { if let Some(arg) = arg.as_ref().map(|a| &a.input_value) { let name = arg.name.clone(); let description = render_description_from_input_value(&arg, &name); let t = render_type_ref(&arg.type_).unwrap(); collected_args.push(Arg { name, description, type_: t, }) } } if collected_args.len() > 0 { let mut collected_arg = CollectedArgs { description: Some(rust::Tokens::new()), args: rust::Tokens::new(), }; for arg in collected_args { if let Some(desc) = arg.description { if let Some(inner_desc) = collected_arg.description.as_mut() { inner_desc.append(desc); inner_desc.push(); } } collected_arg.args.append(quote! { $(arg.name.to_case(Case::Snake)): $(arg.type_), }); collected_arg.args.push(); } if let Some(desc) = collected_arg.description.as_ref() { if desc.is_empty() { collected_arg.description = None; } } Some(collected_arg) } else { None } } pub fn render_field_output(field: &FullTypeFields) -> eyre::Result { let inner = &field.type_.as_ref().unwrap(); type_ref::render_type_ref(&inner.type_ref) }