Merge branch 'master' into rework-errors

This commit is contained in:
Sunli 2020-10-01 09:07:19 +08:00
commit 97f0b0d419
29 changed files with 134 additions and 97 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()) {
@ -180,7 +180,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::ServerResult<Option<#crate_name::serde_json::Value>> {
#(#resolvers)*
Ok(None)
@ -328,11 +328,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::ServerResult<#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::ServerResult<::std::option::Option<#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::ServerResult<#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::ServerResult<::std::option::Option<#crate_name::serde_json::Value>> {
#(#resolvers)*
Ok(None)
@ -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::ServerResult<#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,8 @@ 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::ServerResult<::std::option::Option<#crate_name::serde_json::Value>> {
#(#resolvers)*
Ok(None)
@ -188,12 +189,13 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
#[allow(clippy::all, clippy::pedantic)]
#[#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::ServerResult<#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

@ -393,8 +393,6 @@ pub fn generate(
None
}
}
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,8 @@ 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::ServerResult<::std::option::Option<#crate_name::serde_json::Value>> {
Ok(None)
}
@ -174,11 +175,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::ServerResult<#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, Result, Schema, SubscriptionType};
use async_graphql::{Data, ObjectType, Result, 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

@ -19,7 +19,7 @@ async-trait = "0.1.36"
serde_json = "1.0.56"
futures = "0.3.5"
async-std = "1.6.2"
pin-project-lite = "=0.1.8" # https://github.com/http-rs/async-sse/issues/10
pin-project-lite = "0.1.9"
[dev-dependencies]
smol = { version = "0.1.18", features = ["tokio02"] }

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, Result, Schema, SubscriptionType};
use async_graphql::{Data, ObjectType, Result, 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, InputValueResult, Positioned, Result, ServerResult, Value,
registry, ContainerType, ContextSelectionSet, InputValueResult, Positioned, Result,
ServerResult, Value,
};
use std::borrow::Cow;
@ -97,3 +98,18 @@ impl<T: OutputValueType + Sync> OutputValueType for Result<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, Error, Request, Response, Result, Schema, SubscriptionType};
use crate::{Data, Error, ObjectType, Request, Response, Result, Schema, SubscriptionType};
use futures::Stream;
use pin_project_lite::pin_project;
use serde::{Deserialize, Serialize};

View File

@ -134,8 +134,6 @@ pub mod validators;
#[doc(hidden)]
pub mod registry;
#[doc(hidden)]
pub mod type_mark;
#[doc(hidden)]
pub use async_stream;
@ -155,7 +153,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,
};
@ -174,7 +174,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::*;
/// Define a GraphQL object with methods

View File

@ -7,12 +7,12 @@ use crate::{
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 {
@ -24,7 +24,7 @@ pub trait ObjectType: OutputValueType {
/// If the field was not found returns None.
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<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.
@ -52,7 +52,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<'_>) -> ServerResult<Option<serde_json::Value>> {
T::resolve_field(*self, ctx).await
}
@ -60,8 +60,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,
) -> ServerResult<serde_json::Value> {
@ -85,8 +85,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,
) -> ServerResult<serde_json::Value> {
@ -119,7 +119,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, QueryEnv, Request, Response,
ServerError, SubscriptionType, Type, ID,
BatchRequest, BatchResponse, CacheControl, ContextBase, ObjectType, QueryEnv, Request,
Response, ServerError, 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.
@ -432,8 +432,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 Response::from_errors(vec![ServerError::new(
"Subscriptions are not supported on this transport.",

View File

@ -3,7 +3,7 @@ use crate::{Context, ContextSelectionSet, PathSegment, ServerError, ServerResult
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, OutputValueType, Positioned, Result, ServerResult, Type,
registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned, Result,
ServerResult, 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,
@ -232,8 +232,15 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> ServerResult<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,10 +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, ServerResult, Type,
registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned, ServerResult,
Type,
};
use indexmap::map::IndexMap;
use std::borrow::Cow;
@ -107,7 +107,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,
@ -139,8 +139,14 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> ServerResult<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, OutputValueType, Positioned, ServerError, ServerResult,
Type,
registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned, ServerError,
ServerResult, 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
}
@ -65,4 +64,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, ServerError, ServerResult, SubscriptionType, Type};
use futures::{stream, Stream};
use std::borrow::Cow;
@ -44,5 +43,3 @@ impl SubscriptionType for EmptySubscription {
})))
}
}
impl TypeMarkSubscription for EmptySubscription {}

View File

@ -1,13 +1,14 @@
use crate::parser::types::Field;
use crate::registry::{MetaType, Registry};
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::TypeMarkObject;
use crate::resolver_utils::resolve_container;
use crate::{
CacheControl, Context, ContextSelectionSet, OutputValueType, Positioned, ServerResult,
SimpleObject, Subscription, Type,
CacheControl, ContainerType, Context, ContextSelectionSet, ObjectType, OutputValueType,
Positioned, ServerResult, SimpleObject, Subscription, SubscriptionType, Type,
};
use futures::Stream;
use indexmap::IndexMap;
use std::borrow::Cow;
use std::pin::Pin;
#[doc(hidden)]
pub struct MergedObject<A, B>(pub A, pub B);
@ -57,7 +58,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,
@ -82,11 +83,32 @@ where
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> ServerResult<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
A: SubscriptionType + Send + Sync,
B: SubscriptionType + Send + Sync,
{
fn create_field_stream<'a>(
&'a self,
ctx: &'a Context<'a>,
) -> Option<Pin<Box<dyn Stream<Item = ServerResult<serde_json::Value>> + Send + 'a>>> {
match self.0.create_field_stream(ctx) {
Some(stream) => Some(stream),
None => self.1.create_field_stream(ctx),
}
}
}
#[doc(hidden)]
#[derive(SimpleObject, Default)]

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, OutputValueType, Positioned, ServerError,
ServerResult, SimpleObject, Type,
registry, Any, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned,
ServerError, ServerResult, 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<'_>) -> ServerResult<Option<serde_json::Value>> {
if ctx.item.node.name.node == "__schema" {
if self.disable_introspection {
@ -148,8 +147,8 @@ impl<T: ObjectType + Send + Sync> OutputValueType for QueryRoot<T> {
ctx: &ContextSelectionSet<'_>,
_field: &Positioned<Field>,
) -> ServerResult<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> {}