1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use std::borrow::Cow; use indexmap::IndexMap; use crate::parser::types::Field; use crate::registry::{MetaType, Registry}; use crate::resolver_utils::resolve_container; use crate::{ CacheControl, ContainerType, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerResult, SimpleObject, Type, Value, }; use async_graphql_value::ConstValue; #[doc(hidden)] pub struct MergedObject<A, B>(pub A, pub B); impl<A: Type, B: Type> Type for MergedObject<A, B> { fn type_name() -> Cow<'static, str> { Cow::Owned(format!("{}_{}", A::type_name(), B::type_name())) } fn create_type_info(registry: &mut Registry) -> String { registry.create_type::<Self, _>(|registry| { let mut fields = IndexMap::new(); let mut cc = CacheControl::default(); if let MetaType::Object { fields: a_fields, cache_control: a_cc, .. } = registry.create_dummy_type::<A>() { fields.extend(a_fields); cc = cc.merge(&a_cc); } if let MetaType::Object { fields: b_fields, cache_control: b_cc, .. } = registry.create_dummy_type::<B>() { fields.extend(b_fields); cc = cc.merge(&b_cc); } MetaType::Object { name: Self::type_name().to_string(), description: None, fields, cache_control: cc, extends: false, keys: None, visible: None, } }) } } #[async_trait::async_trait] impl<A, B> ContainerType for MergedObject<A, B> where A: ObjectType + Send + Sync, B: ObjectType + Send + Sync, { async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> { match self.0.resolve_field(ctx).await { Ok(Some(value)) => Ok(Some(value)), Ok(None) => self.1.resolve_field(ctx).await, Err(err) => Err(err), } } async fn find_entity( &self, ctx: &Context<'_>, params: &ConstValue, ) -> ServerResult<Option<ConstValue>> { match self.0.find_entity(ctx, params).await { Ok(Some(value)) => Ok(Some(value)), Ok(None) => self.1.find_entity(ctx, params).await, Err(err) => Err(err), } } } #[async_trait::async_trait] impl<A, B> OutputType for MergedObject<A, B> where A: ObjectType + Send + Sync, B: ObjectType + Send + Sync, { async fn resolve( &self, ctx: &ContextSelectionSet<'_>, _field: &Positioned<Field>, ) -> ServerResult<Value> { resolve_container(ctx, self).await } } impl<A, B> ObjectType for MergedObject<A, B> where A: ObjectType + Send + Sync, B: ObjectType + Send + Sync, { } #[doc(hidden)] #[derive(SimpleObject, Default)] #[graphql(internal, dummy)] pub struct MergedObjectTail;