use std::sync::Arc; use dagger_core::introspection::{FullType, Schema, __TypeKind}; use itertools::Itertools; pub struct Visitor { pub schema: Schema, pub handlers: VisitHandlers, } pub type VisitFunc = Arc eyre::Result<()>>; pub struct VisitHandlers { pub visit_scalar: VisitFunc, pub visit_object: VisitFunc, pub visit_input: VisitFunc, pub visit_enum: VisitFunc, } struct SequenceItem { kind: __TypeKind, handler: VisitFunc, ignore: Option>, } impl Visitor { pub fn run(&self) -> eyre::Result<()> { let sequence = vec![ SequenceItem { kind: __TypeKind::SCALAR, handler: self.handlers.visit_scalar.clone(), ignore: Some(vec![ "String".into(), "Float".into(), "Int".into(), "Boolean".into(), "DateTime".into(), "ID".into(), ]), }, SequenceItem { kind: __TypeKind::INPUT_OBJECT, handler: self.handlers.visit_input.clone(), ignore: None, }, SequenceItem { kind: __TypeKind::OBJECT, handler: self.handlers.visit_object.clone(), ignore: None, }, SequenceItem { kind: __TypeKind::ENUM, handler: self.handlers.visit_enum.clone(), ignore: None, }, ]; for item in sequence { self.visit(&item)?; } Ok(()) } fn visit(&self, item: &SequenceItem) -> eyre::Result<()> { self.schema .types .as_ref() .unwrap() .into_iter() .map(|t| t.as_ref().unwrap()) .filter(|t| match t.full_type.kind.as_ref().unwrap() == &item.kind { true => match (item.ignore.as_ref(), t.full_type.name.as_ref()) { (Some(ignore), Some(name)) => { if name.starts_with("__") { return false; } if ignore.contains(name) { return false; } return true; } (None, Some(name)) => { if name.starts_with("__") { return false; } return true; } _ => false, }, false => false, }) .sorted_by(|a, b| { a.full_type .name .as_ref() .unwrap() .cmp(&b.full_type.name.as_ref().unwrap()) }) .map(|t| (*item.handler)(&t.full_type)) .collect::>>()?; Ok(()) } }