Add some type detection to make the defined schema conform to the GraphQL specification. #282

This commit is contained in:
Sunli 2020-09-27 15:32:55 +08:00
parent edf1420a44
commit 0d6771a199
17 changed files with 51 additions and 0 deletions

View File

@ -39,6 +39,7 @@ serde = { version = "1.0.104", features = ["derive"] }
serde_json = "1.0.48"
spin = "0.5.2"
thiserror = "1.0.11"
static_assertions = "1.1.0"
# Feature optional dependencies
uuid = { version = "0.8.1", optional = true, features = ["v4", "serde"] }

View File

@ -121,6 +121,8 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
Ok(#crate_name::resolver_utils::enum_value(*self).into_json().unwrap())
}
}
impl #crate_name::type_mark::TypeMarkEnum for #ident {}
};
Ok(expanded.into())
}

View File

@ -166,6 +166,8 @@ pub fn generate(object_args: &args::InputObject, input: &DeriveInput) -> Result<
#crate_name::Value::Object(map)
}
}
impl #crate_name::type_mark::TypeMarkInputObject for #ident {}
};
Ok(expanded.into())
}

View File

@ -326,6 +326,8 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
#crate_name::resolver_utils::resolve_object(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkInterface for #ident #generics {}
};
Ok(expanded.into())
}

View File

@ -521,6 +521,8 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
#crate_name::resolver_utils::resolve_object(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkObject for #self_ty #where_clause {}
};
Ok(expanded.into())
}

View File

@ -68,6 +68,8 @@ pub fn generate(scalar_args: &args::Scalar, item_impl: &mut ItemImpl) -> Result<
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

@ -192,6 +192,8 @@ pub fn generate(object_args: &args::Object, input: &DeriveInput) -> Result<Token
#crate_name::resolver_utils::resolve_object(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkObject for #ident #generics #where_clause {}
};
Ok(expanded.into())
}

View File

@ -385,6 +385,8 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
::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

@ -69,6 +69,8 @@ pub fn generate(union_args: &args::Interface, input: &DeriveInput) -> Result<Tok
enum_names.push(enum_name);
type_into_impls.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#p: #crate_name::type_mark::TypeMarkObject);
#[allow(clippy::all, clippy::pedantic)]
impl #generics ::std::convert::From<#p> for #ident #generics {
fn from(obj: #p) -> Self {
@ -149,6 +151,8 @@ pub fn generate(union_args: &args::Interface, input: &DeriveInput) -> Result<Tok
#crate_name::resolver_utils::resolve_object(ctx, self).await
}
}
impl #generics #crate_name::type_mark::TypeMarkEnum for #ident #generics {}
};
Ok(expanded.into())
}

View File

@ -135,6 +135,9 @@ pub mod validators;
#[doc(hidden)]
pub mod registry;
#[doc(hidden)]
pub mod type_mark;
#[doc(hidden)]
pub use async_stream;
#[doc(hidden)]
@ -148,6 +151,8 @@ pub use indexmap;
#[doc(hidden)]
pub use serde_json;
#[doc(hidden)]
pub use static_assertions;
#[doc(hidden)]
pub use subscription::SubscriptionType;
pub use async_graphql_parser as parser;

7
src/type_mark.rs Normal file
View File

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

View File

@ -2,6 +2,7 @@ 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::types::connection::{CursorType, EmptyFields};
use crate::{
registry, Context, ContextSelectionSet, FieldResult, OutputValueType, Positioned, Result, Type,
@ -230,3 +231,5 @@ where
resolve_object(ctx, self).await
}
}
impl<C, T, EC, EE> TypeMarkObject for Connection<C, T, EC, EE> {}

View File

@ -1,6 +1,7 @@
use crate::connection::EmptyFields;
use crate::parser::types::Field;
use crate::resolver_utils::{resolve_object, ObjectType};
use crate::type_mark::TypeMarkObject;
use crate::types::connection::CursorType;
use crate::{registry, Context, ContextSelectionSet, OutputValueType, Positioned, Result, Type};
use indexmap::map::IndexMap;
@ -137,3 +138,5 @@ where
resolve_object(ctx, self).await
}
}
impl<C, T, E> TypeMarkObject for Edge<C, T, E> {}

View File

@ -1,5 +1,6 @@
use crate::parser::types::Field;
use crate::resolver_utils::ObjectType;
use crate::type_mark::TypeMarkObject;
use crate::{
registry, Context, ContextSelectionSet, Error, OutputValueType, Positioned, QueryError, Result,
Type,
@ -67,3 +68,5 @@ impl OutputValueType for EmptyMutation {
})
}
}
impl TypeMarkObject for EmptyMutation {}

View File

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

View File

@ -1,6 +1,7 @@
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::{
CacheControl, Context, ContextSelectionSet, Error, OutputValueType, Positioned, QueryError,
Result, SimpleObject, Subscription, SubscriptionType, Type,
@ -100,6 +101,8 @@ where
}
}
impl<A, B> TypeMarkObject for MergedObject<A, B> {}
impl<A, B> SubscriptionType for MergedObject<A, B>
where
A: SubscriptionType + Send + Sync,
@ -121,6 +124,8 @@ where
}
}
impl<A, B> TypeMarkSubscription for MergedObject<A, B> {}
#[doc(hidden)]
#[derive(SimpleObject, Default)]
#[graphql(internal)]

View File

@ -6,6 +6,7 @@ use crate::{
Result, SimpleObject, Type,
};
use crate::type_mark::TypeMarkObject;
use indexmap::map::IndexMap;
use std::borrow::Cow;
@ -152,3 +153,5 @@ impl<T: ObjectType + Send + Sync> OutputValueType for QueryRoot<T> {
resolve_object(ctx, self).await
}
}
impl<T: ObjectType + Send + Sync> TypeMarkObject for QueryRoot<T> {}