Improve trait for GraphQL types.

This commit is contained in:
Sunli 2020-09-30 07:45:48 +08:00
parent 4e7bb1a59c
commit 35f886a7f8
28 changed files with 113 additions and 98 deletions

View File

@ -1,4 +1,4 @@
use async_graphql::{resolver_utils::ObjectType, Response, Schema, SubscriptionType};
use async_graphql::{ObjectType, Response, Schema, SubscriptionType};
use async_graphql_parser::{parse_query, types::ExecutableDocument};
use async_std::task;

View File

@ -156,8 +156,6 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
}
#remote_conversion
impl #crate_name::type_mark::TypeMarkEnum for #ident {}
};
Ok(expanded.into())
}

View File

@ -64,7 +64,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
flatten_fields.push((ident, ty));
schema_fields.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::type_mark::TypeMarkInputObject);
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::InputObjectType);
#ty::create_type_info(registry);
if let Some(#crate_name::registry::MetaType::InputObject{ input_fields, .. }) =
registry.types.remove(&*<#ty as #crate_name::Type>::type_name()) {
@ -176,7 +176,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
}
}
impl #crate_name::type_mark::TypeMarkInputObject for #ident {}
impl #crate_name::InputObjectType for #ident {}
};
Ok(expanded.into())
}

View File

@ -311,7 +311,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
#[allow(clippy::all, clippy::pedantic)]
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::resolver_utils::ObjectType for #ident #generics {
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics {
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#(#resolvers)*
Err(#crate_name::QueryError::FieldNotFound {
@ -331,11 +331,11 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::OutputValueType for #ident #generics {
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#crate_name::resolver_utils::resolve_object(ctx, self).await
#crate_name::resolver_utils::resolve_container(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkInterface for #ident #generics {}
impl #generics #crate_name::InterfaceType for #ident #generics {}
};
Ok(expanded.into())
}

View File

@ -89,7 +89,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
#[allow(clippy::all, clippy::pedantic)]
#[#crate_name::async_trait::async_trait]
impl #crate_name::resolver_utils::ObjectType for #ident {
impl #crate_name::resolver_utils::ContainerType for #ident {
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#create_merged_obj.resolve_field(ctx).await
}
@ -99,9 +99,11 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
#[#crate_name::async_trait::async_trait]
impl #crate_name::OutputValueType for #ident {
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#crate_name::resolver_utils::resolve_object(ctx, self).await
#crate_name::resolver_utils::resolve_container(ctx, self).await
}
}
impl #crate_name::ObjectType for #ident {}
};
Ok(expanded.into())
}

View File

@ -502,7 +502,7 @@ pub fn generate(
#[allow(clippy::all, clippy::pedantic, clippy::suspicious_else_formatting)]
#[allow(unused_braces, unused_variables, unused_parens, unused_mut)]
#[#crate_name::async_trait::async_trait]
impl#generics #crate_name::resolver_utils::ObjectType for #self_ty #where_clause {
impl#generics #crate_name::resolver_utils::ContainerType for #self_ty #where_clause {
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#(#resolvers)*
Err(#crate_name::QueryError::FieldNotFound {
@ -530,11 +530,11 @@ pub fn generate(
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::OutputValueType for #self_ty #where_clause {
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#crate_name::resolver_utils::resolve_object(ctx, self).await
#crate_name::resolver_utils::resolve_container(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkObject for #self_ty #where_clause {}
impl #generics #crate_name::ObjectType for #self_ty #where_clause {}
};
Ok(expanded.into())
}

View File

@ -68,8 +68,6 @@ pub fn generate(
Ok(#crate_name::ScalarType::to_value(self).into_json().unwrap())
}
}
impl #generic #crate_name::type_mark::TypeMarkScalar for #self_ty #where_clause {}
};
Ok(expanded.into())
}

View File

@ -178,7 +178,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
#[allow(clippy::all, clippy::pedantic)]
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::resolver_utils::ObjectType for #ident #generics #where_clause {
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics #where_clause {
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#(#resolvers)*
Err(#crate_name::QueryError::FieldNotFound {
@ -192,11 +192,11 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::OutputValueType for #ident #generics #where_clause {
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#crate_name::resolver_utils::resolve_object(ctx, self).await
#crate_name::resolver_utils::resolve_container(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkObject for #ident #generics #where_clause {}
impl #generics #crate_name::ObjectType for #ident #generics #where_clause {}
};
Ok(expanded.into())
}

View File

@ -403,8 +403,6 @@ pub fn generate(
::std::boxed::Box::pin(#crate_name::futures::stream::once(async { Err(error) }))
}
}
impl #crate_name::type_mark::TypeMarkSubscription for #self_ty #where_clause {}
};
Ok(expanded.into())
}

View File

@ -67,7 +67,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
if !variant.flatten {
type_into_impls.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#p: #crate_name::type_mark::TypeMarkObject);
#crate_name::static_assertions::assert_impl_one!(#p: #crate_name::ObjectType);
#[allow(clippy::all, clippy::pedantic)]
impl #generics ::std::convert::From<#p> for #ident #generics {
@ -78,7 +78,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
});
} else {
type_into_impls.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#p: #crate_name::type_mark::TypeMarkEnum);
#crate_name::static_assertions::assert_impl_one!(#p: #crate_name::UnionType);
#[allow(clippy::all, clippy::pedantic)]
impl #generics ::std::convert::From<#p> for #ident #generics {
@ -158,7 +158,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
#[allow(clippy::all, clippy::pedantic)]
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::resolver_utils::ObjectType for #ident #generics {
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics {
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
Err(#crate_name::QueryError::FieldNotFound {
field_name: ctx.item.node.name.to_string(),
@ -177,11 +177,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
#[#crate_name::async_trait::async_trait]
impl #generics #crate_name::OutputValueType for #ident #generics {
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::Result<#crate_name::serde_json::Value> {
#crate_name::resolver_utils::resolve_object(ctx, self).await
#crate_name::resolver_utils::resolve_container(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkEnum for #ident #generics {}
impl #generics #crate_name::UnionType for #ident #generics {}
};
Ok(expanded.into())
}

View File

@ -5,7 +5,7 @@ use actix::{
use actix_http::ws;
use actix_web_actors::ws::{Message, ProtocolError, WebsocketContext};
use async_graphql::http::WebSocket;
use async_graphql::{resolver_utils::ObjectType, Data, FieldResult, Schema, SubscriptionType};
use async_graphql::{Data, FieldResult, ObjectType, Schema, SubscriptionType};
use futures::channel::mpsc;
use futures::SinkExt;
use std::time::{Duration, Instant};

View File

@ -4,7 +4,7 @@
#![forbid(unsafe_code)]
use async_graphql::http::MultipartOptions;
use async_graphql::{resolver_utils::ObjectType, Schema, SubscriptionType, Variables};
use async_graphql::{ObjectType, Schema, SubscriptionType, Variables};
use log::{error, info};
use rocket::{
data::{self, FromData},

View File

@ -9,7 +9,7 @@
#![forbid(unsafe_code)]
use async_graphql::http::MultipartOptions;
use async_graphql::{resolver_utils::ObjectType, ParseRequestError, Schema, SubscriptionType};
use async_graphql::{ObjectType, ParseRequestError, Schema, SubscriptionType};
use async_trait::async_trait;
use tide::{
http::{

View File

@ -1,4 +1,4 @@
use async_graphql::{resolver_utils::ObjectType, Data, FieldResult, Schema, SubscriptionType};
use async_graphql::{Data, FieldResult, ObjectType, Schema, SubscriptionType};
use futures::{future, StreamExt};
use warp::filters::ws;
use warp::{Filter, Rejection, Reply};

View File

@ -1,7 +1,8 @@
use crate::parser::types::Field;
use crate::registry::Registry;
use crate::{
registry, ContextSelectionSet, FieldResult, InputValueResult, Positioned, Result, Value,
registry, ContainerType, ContextSelectionSet, FieldResult, InputValueResult, Positioned,
Result, Value,
};
use std::borrow::Cow;
@ -99,3 +100,18 @@ impl<T: OutputValueType + Sync> OutputValueType for FieldResult<T> {
}
}
}
/// A GraphQL object.
pub trait ObjectType: ContainerType {}
#[async_trait::async_trait]
impl<T: ObjectType + Send + Sync> ObjectType for &T {}
/// A GraphQL interface.
pub trait InterfaceType: ContainerType {}
/// A GraphQL interface.
pub trait UnionType: ContainerType {}
/// A GraphQL input object.
pub trait InputObjectType: InputValueType {}

View File

@ -1,7 +1,6 @@
//! WebSocket transport for subscription
use crate::resolver_utils::ObjectType;
use crate::{Data, FieldResult, Request, Response, Schema, SubscriptionType};
use crate::{Data, FieldResult, ObjectType, Request, Response, Schema, SubscriptionType};
use futures::Stream;
use pin_project_lite::pin_project;
use serde::{Deserialize, Serialize};

View File

@ -135,8 +135,6 @@ pub mod validators;
#[doc(hidden)]
pub mod registry;
#[doc(hidden)]
pub mod type_mark;
#[doc(hidden)]
pub use async_stream;
@ -156,7 +154,9 @@ pub use static_assertions;
pub use subscription::SubscriptionType;
pub use async_graphql_parser as parser;
pub use base::{InputValueType, OutputValueType, Type};
pub use base::{
InputObjectType, InputValueType, InterfaceType, ObjectType, OutputValueType, Type, UnionType,
};
pub use context::{
Context, ContextBase, Data, QueryEnv, QueryPathNode, QueryPathSegment, ResolveId, Variables,
};
@ -175,7 +175,7 @@ pub use validation::ValidationMode;
#[doc(no_inline)]
pub use parser::{Pos, Positioned};
#[doc(no_inline)]
pub use resolver_utils::{EnumType, ObjectType, ScalarType};
pub use resolver_utils::{ContainerType, EnumType, ScalarType};
pub use types::*;
/// Result type

View File

@ -6,12 +6,12 @@ use futures::TryFutureExt;
use std::future::Future;
use std::pin::Pin;
/// A GraphQL object.
/// A GraphQL container.
///
/// This helper trait allows the type to call `resolve_object` on itself in its
/// `OutputValueType::resolve` implementation.
#[async_trait::async_trait]
pub trait ObjectType: OutputValueType {
pub trait ContainerType: OutputValueType {
/// This function returns true of type `EmptyMutation` only.
#[doc(hidden)]
fn is_empty() -> bool {
@ -21,7 +21,7 @@ pub trait ObjectType: OutputValueType {
/// Resolves a field value and outputs it as a json value `serde_json::Value`.
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value>;
/// Collect all the fields of the object that are queried in the selection set.
/// Collect all the fields of the container that are queried in the selection set.
///
/// Objects do not have to override this, but interfaces and unions must call it on their
/// internal type.
@ -45,7 +45,7 @@ pub trait ObjectType: OutputValueType {
}
#[async_trait::async_trait]
impl<T: ObjectType + Send + Sync> ObjectType for &T {
impl<T: ContainerType + Send + Sync> ContainerType for &T {
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
T::resolve_field(*self, ctx).await
}
@ -53,8 +53,8 @@ impl<T: ObjectType + Send + Sync> ObjectType for &T {
// TODO: reduce code duplication between the two below functions?
/// Resolve an object by executing each of the fields concurrently.
pub async fn resolve_object<'a, T: ObjectType + Send + Sync>(
/// Resolve an container by executing each of the fields concurrently.
pub async fn resolve_container<'a, T: ContainerType + Send + Sync>(
ctx: &ContextSelectionSet<'a>,
root: &'a T,
) -> Result<serde_json::Value> {
@ -78,8 +78,8 @@ pub async fn resolve_object<'a, T: ObjectType + Send + Sync>(
Ok(map.into())
}
/// Resolve an object by executing each of the fields serially.
pub async fn resolve_object_serial<'a, T: ObjectType + Send + Sync>(
/// Resolve an container by executing each of the fields serially.
pub async fn resolve_container_serial<'a, T: ContainerType + Send + Sync>(
ctx: &ContextSelectionSet<'a>,
root: &'a T,
) -> Result<serde_json::Value> {
@ -112,7 +112,7 @@ pub struct Fields<'a>(Vec<BoxFieldFuture<'a>>);
impl<'a> Fields<'a> {
/// Add another set of fields to this set of fields using the given object.
pub fn add_set<T: ObjectType + Send + Sync>(
pub fn add_set<T: ContainerType + Send + Sync>(
&mut self,
ctx: &ContextSelectionSet<'a>,
root: &'a T,

View File

@ -1,12 +1,12 @@
//! Utilities for implementing
//! [`OutputValueType::resolve`](trait.OutputValueType.html#tymethod.resolve).
mod container;
mod r#enum;
mod list;
mod object;
mod scalar;
pub use container::*;
pub use list::*;
pub use object::*;
pub use r#enum::*;
pub use scalar::*;

View File

@ -4,13 +4,13 @@ use crate::model::__DirectiveLocation;
use crate::parser::parse_query;
use crate::parser::types::{DocumentOperations, OperationType};
use crate::registry::{MetaDirective, MetaInputValue, Registry};
use crate::resolver_utils::{resolve_object, resolve_object_serial, ObjectType};
use crate::resolver_utils::{resolve_container, resolve_container_serial, ContainerType};
use crate::subscription::collect_subscription_streams;
use crate::types::QueryRoot;
use crate::validation::{check_rules, CheckResult, ValidationMode};
use crate::{
BatchRequest, BatchResponse, CacheControl, ContextBase, Error, Pos, QueryEnv, QueryError,
Request, Response, Result, SubscriptionType, Type, ID,
BatchRequest, BatchResponse, CacheControl, ContextBase, Error, ObjectType, Pos, QueryEnv,
QueryError, Request, Response, Result, SubscriptionType, Type, ID,
};
use futures::stream::{self, Stream, StreamExt};
use indexmap::map::IndexMap;
@ -34,7 +34,7 @@ pub struct SchemaBuilder<Query, Mutation, Subscription> {
enable_federation: bool,
}
impl<Query: ObjectType, Mutation: ObjectType, Subscription: SubscriptionType>
impl<Query: ContainerType, Mutation: ContainerType, Subscription: SubscriptionType>
SchemaBuilder<Query, Mutation, Subscription>
{
/// Manually register a type in the schema.
@ -430,8 +430,8 @@ where
env.extensions.lock().execution_start(&ctx_extension);
let data = match &env.operation.node.ty {
OperationType::Query => resolve_object(&ctx, &self.query).await,
OperationType::Mutation => resolve_object_serial(&ctx, &self.mutation).await,
OperationType::Query => resolve_container(&ctx, &self.query).await,
OperationType::Mutation => resolve_container_serial(&ctx, &self.mutation).await,
OperationType::Subscription => {
return Error::Query {
pos: Pos::default(),

View File

@ -3,7 +3,7 @@ use crate::{Context, ContextSelectionSet, Result, Type};
use futures::{Stream, StreamExt};
use std::pin::Pin;
/// Represents a GraphQL subscription object
/// A GraphQL subscription object
pub trait SubscriptionType: Type {
/// This function returns true of type `EmptySubscription` only.
#[doc(hidden)]

View File

@ -1,7 +0,0 @@
pub trait TypeMarkScalar {}
pub trait TypeMarkObject {}
pub trait TypeMarkInterface {}
pub trait TypeMarkUnion {}
pub trait TypeMarkEnum {}
pub trait TypeMarkInputObject {}
pub trait TypeMarkSubscription {}

View File

@ -1,11 +1,11 @@
use crate::connection::edge::Edge;
use crate::connection::page_info::PageInfo;
use crate::parser::types::Field;
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::TypeMarkObject;
use crate::resolver_utils::{resolve_container, ContainerType};
use crate::types::connection::{CursorType, EmptyFields};
use crate::{
registry, Context, ContextSelectionSet, FieldResult, OutputValueType, Positioned, Result, Type,
registry, Context, ContextSelectionSet, FieldResult, ObjectType, OutputValueType, Positioned,
Result, Type,
};
use futures::{Stream, StreamExt, TryStreamExt};
use indexmap::map::IndexMap;
@ -189,7 +189,7 @@ where
}
#[async_trait::async_trait]
impl<C, T, EC, EE> ObjectType for Connection<C, T, EC, EE>
impl<C, T, EC, EE> ContainerType for Connection<C, T, EC, EE>
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
@ -228,8 +228,15 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> Result<serde_json::Value> {
resolve_object(ctx, self).await
resolve_container(ctx, self).await
}
}
impl<C, T, EC, EE> TypeMarkObject for Connection<C, T, EC, EE> {}
impl<C, T, EC, EE> ObjectType for Connection<C, T, EC, EE>
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
EC: ObjectType + Sync + Send,
EE: ObjectType + Sync + Send,
{
}

View File

@ -1,9 +1,10 @@
use crate::connection::EmptyFields;
use crate::parser::types::Field;
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::TypeMarkObject;
use crate::resolver_utils::{resolve_container, ContainerType};
use crate::types::connection::CursorType;
use crate::{registry, Context, ContextSelectionSet, OutputValueType, Positioned, Result, Type};
use crate::{
registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned, Result, Type,
};
use indexmap::map::IndexMap;
use std::borrow::Cow;
@ -105,7 +106,7 @@ where
}
#[async_trait::async_trait]
impl<C, T, E> ObjectType for Edge<C, T, E>
impl<C, T, E> ContainerType for Edge<C, T, E>
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
@ -135,8 +136,14 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> Result<serde_json::Value> {
resolve_object(ctx, self).await
resolve_container(ctx, self).await
}
}
impl<C, T, E> TypeMarkObject for Edge<C, T, E> {}
impl<C, T, E> ObjectType for Edge<C, T, E>
where
C: CursorType + Send + Sync,
T: OutputValueType + Send + Sync,
E: ObjectType + Sync + Send,
{
}

View File

@ -1,9 +1,8 @@
use crate::parser::types::Field;
use crate::resolver_utils::ObjectType;
use crate::type_mark::TypeMarkObject;
use crate::resolver_utils::ContainerType;
use crate::{
registry, Context, ContextSelectionSet, Error, OutputValueType, Positioned, QueryError, Result,
Type,
registry, Context, ContextSelectionSet, Error, ObjectType, OutputValueType, Positioned,
QueryError, Result, Type,
};
use std::borrow::Cow;
@ -44,7 +43,7 @@ impl Type for EmptyMutation {
}
#[async_trait::async_trait]
impl ObjectType for EmptyMutation {
impl ContainerType for EmptyMutation {
fn is_empty() -> bool {
true
}
@ -69,4 +68,4 @@ impl OutputValueType for EmptyMutation {
}
}
impl TypeMarkObject for EmptyMutation {}
impl ObjectType for EmptyMutation {}

View File

@ -1,4 +1,3 @@
use crate::type_mark::TypeMarkSubscription;
use crate::{registry, Context, Error, Pos, QueryError, Result, SubscriptionType, Type};
use futures::{stream, Stream};
use std::borrow::Cow;
@ -48,5 +47,3 @@ impl SubscriptionType for EmptySubscription {
}))
}
}
impl TypeMarkSubscription for EmptySubscription {}

View File

@ -1,10 +1,9 @@
use crate::parser::types::Field;
use crate::registry::{MetaType, Registry};
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::{TypeMarkObject, TypeMarkSubscription};
use crate::resolver_utils::{resolve_container, ContainerType};
use crate::{
CacheControl, Context, ContextSelectionSet, Error, OutputValueType, Positioned, QueryError,
Result, SimpleObject, Subscription, SubscriptionType, Type,
CacheControl, Context, ContextSelectionSet, Error, ObjectType, OutputValueType, Positioned,
QueryError, Result, SimpleObject, Subscription, SubscriptionType, Type,
};
use futures::{future::Either, stream, Stream, StreamExt};
use indexmap::IndexMap;
@ -69,7 +68,7 @@ impl<A: Type, B: Type> Type for MergedObject<A, B> {
}
#[async_trait::async_trait]
impl<A, B> ObjectType for MergedObject<A, B>
impl<A, B> ContainerType for MergedObject<A, B>
where
A: ObjectType + Send + Sync,
B: ObjectType + Send + Sync,
@ -97,11 +96,16 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> Result<serde_json::Value> {
resolve_object(ctx, self).await
resolve_container(ctx, self).await
}
}
impl<A, B> TypeMarkObject for MergedObject<A, B> {}
impl<A, B> ObjectType for MergedObject<A, B>
where
A: ObjectType + Send + Sync,
B: ObjectType + Send + Sync,
{
}
impl<A, B> SubscriptionType for MergedObject<A, B>
where
@ -124,8 +128,6 @@ where
}
}
impl<A, B> TypeMarkSubscription for MergedObject<A, B> {}
#[doc(hidden)]
#[derive(SimpleObject, Default)]
#[graphql(internal)]

View File

@ -1,12 +1,11 @@
use crate::model::{__Schema, __Type};
use crate::parser::types::Field;
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::resolver_utils::{resolve_container, ContainerType};
use crate::{
registry, Any, Context, ContextSelectionSet, Error, OutputValueType, Positioned, QueryError,
Result, SimpleObject, Type,
registry, Any, Context, ContextSelectionSet, Error, ObjectType, OutputValueType, Positioned,
QueryError, Result, SimpleObject, Type,
};
use crate::type_mark::TypeMarkObject;
use indexmap::map::IndexMap;
use std::borrow::Cow;
@ -81,7 +80,7 @@ impl<T: Type> Type for QueryRoot<T> {
}
#[async_trait::async_trait]
impl<T: ObjectType + Send + Sync> ObjectType for QueryRoot<T> {
impl<T: ObjectType + Send + Sync> ContainerType for QueryRoot<T> {
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
if ctx.item.node.name.node == "__schema" {
if self.disable_introspection {
@ -150,8 +149,8 @@ impl<T: ObjectType + Send + Sync> OutputValueType for QueryRoot<T> {
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> Result<serde_json::Value> {
resolve_object(ctx, self).await
resolve_container(ctx, self).await
}
}
impl<T: ObjectType + Send + Sync> TypeMarkObject for QueryRoot<T> {}
impl<T: ObjectType + Send + Sync> ObjectType for QueryRoot<T> {}