Move context type parameter to associated type of GraphQLType
This commit is contained in:
parent
885fe8b09b
commit
6b8f4c9562
36 changed files with 469 additions and 283 deletions
|
@ -9,7 +9,7 @@ use std::env;
|
|||
use mount::Mount;
|
||||
use logger::Logger;
|
||||
use iron::prelude::*;
|
||||
use juniper::FieldResult;
|
||||
use juniper::EmptyMutation;
|
||||
use juniper::iron_handlers::{GraphQLHandler, GraphiQLHandler};
|
||||
use juniper::tests::model::Database;
|
||||
|
||||
|
@ -20,7 +20,11 @@ fn context_factory(_: &mut Request) -> Database {
|
|||
fn main() {
|
||||
let mut mount = Mount::new();
|
||||
|
||||
let graphql_endpoint = GraphQLHandler::new(context_factory, Database::new(), ());
|
||||
let graphql_endpoint = GraphQLHandler::new(
|
||||
context_factory,
|
||||
Database::new(),
|
||||
EmptyMutation::<Database>::new(),
|
||||
);
|
||||
let graphiql_endpoint = GraphiQLHandler::new("/graphql");
|
||||
|
||||
mount.mount("/", graphiql_endpoint);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use ::GraphQLError;
|
||||
|
@ -20,10 +19,9 @@ use types::base::GraphQLType;
|
|||
/// The registry gathers metadata for all types in a schema. It provides
|
||||
/// convenience methods to convert types implementing the `GraphQLType` trait
|
||||
/// into `Type` instances and automatically registers them.
|
||||
pub struct Registry<CtxT> {
|
||||
pub struct Registry {
|
||||
/// Currently registered types
|
||||
pub types: HashMap<String, MetaType>,
|
||||
phantom: PhantomData<CtxT>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -80,9 +78,46 @@ impl<T> IntoFieldResult<T> for FieldResult<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Conversion trait for context types
|
||||
///
|
||||
/// This is currently only used for converting arbitrary contexts into
|
||||
/// the empty tuple, but will in the future be used to support general
|
||||
/// context conversion for larger schemas.
|
||||
pub trait FromContext<T> {
|
||||
/// Perform the conversion
|
||||
fn from_context(value: &T) -> &Self;
|
||||
}
|
||||
|
||||
/// Marker trait for types that can act as context objects for GraphQL types.
|
||||
pub trait Context { }
|
||||
|
||||
static NULL_CONTEXT: () = ();
|
||||
|
||||
impl<T> FromContext<T> for () {
|
||||
fn from_context(_: &T) -> &Self {
|
||||
&NULL_CONTEXT
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromContext<T> for T where T: Context {
|
||||
fn from_context(value: &T) -> &Self {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, CtxT> Executor<'a, CtxT> {
|
||||
/// Resolve a single arbitrary value, mapping the context to a new type
|
||||
pub fn resolve_with_ctx<NewCtxT, T: GraphQLType<Context=NewCtxT>>(
|
||||
&self, value: &T
|
||||
) -> ExecutionResult
|
||||
where NewCtxT: FromContext<CtxT>,
|
||||
{
|
||||
self.replaced_context(<NewCtxT as FromContext<CtxT>>::from_context(&self.context))
|
||||
.resolve(value)
|
||||
}
|
||||
|
||||
/// Resolve a single arbitrary value into an `ExecutionResult`
|
||||
pub fn resolve<T: GraphQLType<CtxT>>(&self, value: &T) -> ExecutionResult {
|
||||
pub fn resolve<T: GraphQLType<Context=CtxT>>(&self, value: &T) -> ExecutionResult {
|
||||
Ok(value.resolve(
|
||||
match self.current_selection_set {
|
||||
Some(ref sel) => Some(sel.clone()),
|
||||
|
@ -94,7 +129,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
|||
/// Resolve a single arbitrary value into a return value
|
||||
///
|
||||
/// If the field fails to resolve, `null` will be returned.
|
||||
pub fn resolve_into_value<T: GraphQLType<CtxT>>(&self, value: &T) -> Value {
|
||||
pub fn resolve_into_value<T: GraphQLType<Context=CtxT>>(&self, value: &T) -> Value {
|
||||
match self.resolve(value) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
|
@ -230,13 +265,13 @@ impl ExecutionError {
|
|||
pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>(
|
||||
document: Document,
|
||||
operation_name: Option<&str>,
|
||||
root_node: &RootNode<CtxT, QueryT, MutationT>,
|
||||
root_node: &RootNode<QueryT, MutationT>,
|
||||
variables: &HashMap<String, InputValue>,
|
||||
context: &CtxT
|
||||
)
|
||||
-> Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>
|
||||
where QueryT: GraphQLType<CtxT>,
|
||||
MutationT: GraphQLType<CtxT>
|
||||
where QueryT: GraphQLType<Context=CtxT>,
|
||||
MutationT: GraphQLType<Context=CtxT>
|
||||
{
|
||||
let mut fragments = vec![];
|
||||
let mut operation = None;
|
||||
|
@ -290,12 +325,11 @@ pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>(
|
|||
Ok((value, errors))
|
||||
}
|
||||
|
||||
impl<CtxT> Registry<CtxT> {
|
||||
impl Registry {
|
||||
/// Construct a new registry
|
||||
pub fn new(types: HashMap<String, MetaType>) -> Registry<CtxT> {
|
||||
pub fn new(types: HashMap<String, MetaType>) -> Registry {
|
||||
Registry {
|
||||
types: types,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +337,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
///
|
||||
/// If the registry hasn't seen a type with this name before, it will
|
||||
/// construct its metadata and store it.
|
||||
pub fn get_type<T>(&mut self) -> Type where T: GraphQLType<CtxT> {
|
||||
pub fn get_type<T>(&mut self) -> Type where T: GraphQLType {
|
||||
if let Some(name) = T::name() {
|
||||
if !self.types.contains_key(name) {
|
||||
self.insert_placeholder(name, Type::NonNullNamed(name.to_owned()));
|
||||
|
@ -318,7 +352,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
}
|
||||
|
||||
/// Create a field with the provided name
|
||||
pub fn field<T>(&mut self, name: &str) -> Field where T: GraphQLType<CtxT> {
|
||||
pub fn field<T>(&mut self, name: &str) -> Field where T: GraphQLType {
|
||||
Field {
|
||||
name: name.to_owned(),
|
||||
description: None,
|
||||
|
@ -329,7 +363,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn field_convert<T: IntoFieldResult<I>, I>(&mut self, name: &str) -> Field where I: GraphQLType<CtxT> {
|
||||
pub fn field_convert<T: IntoFieldResult<I>, I>(&mut self, name: &str) -> Field where I: GraphQLType {
|
||||
Field {
|
||||
name: name.to_owned(),
|
||||
description: None,
|
||||
|
@ -340,7 +374,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn field_inside_result<T>(&mut self, name: &str, _: FieldResult<T>) -> Field where T: GraphQLType<CtxT> {
|
||||
pub fn field_inside_result<T>(&mut self, name: &str, _: FieldResult<T>) -> Field where T: GraphQLType {
|
||||
Field {
|
||||
name: name.to_owned(),
|
||||
description: None,
|
||||
|
@ -351,7 +385,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
}
|
||||
|
||||
/// Create an argument with the provided name
|
||||
pub fn arg<T>(&mut self, name: &str) -> Argument where T: GraphQLType<CtxT> + FromInputValue {
|
||||
pub fn arg<T>(&mut self, name: &str) -> Argument where T: GraphQLType + FromInputValue {
|
||||
Argument::new(name, self.get_type::<T>())
|
||||
}
|
||||
|
||||
|
@ -365,7 +399,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
value: &T,
|
||||
)
|
||||
-> Argument
|
||||
where T: GraphQLType<CtxT> + ToInputValue + FromInputValue
|
||||
where T: GraphQLType + ToInputValue + FromInputValue
|
||||
{
|
||||
Argument::new(name, self.get_type::<Option<T>>())
|
||||
.default_value(value.to())
|
||||
|
@ -384,20 +418,20 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// This expects the type to implement `FromInputValue`.
|
||||
pub fn build_scalar_type<T>(&mut self)
|
||||
-> ScalarMeta
|
||||
where T: FromInputValue + GraphQLType<CtxT>
|
||||
where T: FromInputValue + GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Scalar types must be named. Implement name()");
|
||||
ScalarMeta::new::<T>(name)
|
||||
}
|
||||
|
||||
/// Create a list meta type
|
||||
pub fn build_list_type<T: GraphQLType<CtxT>>(&mut self) -> ListMeta {
|
||||
pub fn build_list_type<T: GraphQLType>(&mut self) -> ListMeta {
|
||||
let of_type = self.get_type::<T>();
|
||||
ListMeta::new(of_type)
|
||||
}
|
||||
|
||||
/// Create a nullable meta type
|
||||
pub fn build_nullable_type<T: GraphQLType<CtxT>>(&mut self) -> NullableMeta {
|
||||
pub fn build_nullable_type<T: GraphQLType>(&mut self) -> NullableMeta {
|
||||
let of_type = self.get_type::<T>();
|
||||
NullableMeta::new(of_type)
|
||||
}
|
||||
|
@ -408,7 +442,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// function that needs to be called with the list of fields on the object.
|
||||
pub fn build_object_type<T>(&mut self)
|
||||
-> Box<Fn(&[Field]) -> ObjectMeta>
|
||||
where T: GraphQLType<CtxT>
|
||||
where T: GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Object types must be named. Implement name()");
|
||||
let typename_field = self.field::<String>("__typename");
|
||||
|
@ -423,7 +457,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// Create an enum meta type
|
||||
pub fn build_enum_type<T>(&mut self)
|
||||
-> Box<Fn(&[EnumValue]) -> EnumMeta>
|
||||
where T: FromInputValue + GraphQLType<CtxT>
|
||||
where T: FromInputValue + GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Enum types must be named. Implement name()");
|
||||
|
||||
|
@ -433,7 +467,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// Create an interface meta type builder
|
||||
pub fn build_interface_type<T>(&mut self)
|
||||
-> Box<Fn(&[Field]) -> InterfaceMeta>
|
||||
where T: GraphQLType<CtxT>
|
||||
where T: GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Interface types must be named. Implement name()");
|
||||
let typename_field = self.field::<String>("__typename");
|
||||
|
@ -448,7 +482,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// Create a union meta type builder
|
||||
pub fn build_union_type<T>(&mut self)
|
||||
-> Box<Fn(&[Type]) -> UnionMeta>
|
||||
where T: GraphQLType<CtxT>
|
||||
where T: GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Union types must be named. Implement name()");
|
||||
|
||||
|
@ -458,7 +492,7 @@ impl<CtxT> Registry<CtxT> {
|
|||
/// Create an input object meta type builder
|
||||
pub fn build_input_object_type<T>(&mut self)
|
||||
-> Box<Fn(&[Argument]) -> InputObjectMeta>
|
||||
where T: FromInputValue + GraphQLType<CtxT>
|
||||
where T: FromInputValue + GraphQLType
|
||||
{
|
||||
let name = T::name().expect("Input object types must be named. Implement name()");
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||
use value::Value;
|
||||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct TestType;
|
||||
|
||||
|
@ -19,7 +20,7 @@ graphql_object!(TestType: () |&self| {
|
|||
fn run_variable_query<F>(query: &str, vars: HashMap<String, InputValue>, f: F)
|
||||
where F: Fn(&HashMap<String, Value>) -> ()
|
||||
{
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(query, None, &schema, &vars, &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -6,6 +6,7 @@ use schema::model::RootNode;
|
|||
use ::GraphQLError::ValidationError;
|
||||
use validation::RuleError;
|
||||
use parser::SourcePosition;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Color { Red, Green, Blue }
|
||||
|
@ -30,7 +31,7 @@ graphql_object!(TestType: () |&self| {
|
|||
fn run_variable_query<F>(query: &str, vars: HashMap<String, InputValue>, f: F)
|
||||
where F: Fn(&HashMap<String, Value>) -> ()
|
||||
{
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(query, None, &schema, &vars, &())
|
||||
.expect("Execution failed");
|
||||
|
@ -74,7 +75,7 @@ fn serializes_as_output() {
|
|||
|
||||
#[test]
|
||||
fn does_not_accept_string_literals() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"{ toString(color: "RED") }"#;
|
||||
let vars = vec![
|
||||
|
@ -107,7 +108,7 @@ fn accepts_strings_in_variables() {
|
|||
|
||||
#[test]
|
||||
fn does_not_accept_incorrect_enum_name_in_variables() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($color: Color!) { toString(color: $color) }"#;
|
||||
let vars = vec![
|
||||
|
@ -127,7 +128,7 @@ fn does_not_accept_incorrect_enum_name_in_variables() {
|
|||
|
||||
#[test]
|
||||
fn does_not_accept_incorrect_type_in_variables() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($color: Color!) { toString(color: $color) }"#;
|
||||
let vars = vec![
|
||||
|
|
|
@ -2,6 +2,7 @@ mod field_execution {
|
|||
use value::Value;
|
||||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct DataType;
|
||||
struct DeepDataType;
|
||||
|
@ -33,7 +34,7 @@ mod field_execution {
|
|||
|
||||
#[test]
|
||||
fn test() {
|
||||
let schema = RootNode::new(DataType, ());
|
||||
let schema = RootNode::new(DataType, EmptyMutation::<()>::new());
|
||||
let doc = r"
|
||||
query Example($size: Int) {
|
||||
a,
|
||||
|
@ -109,6 +110,7 @@ mod field_execution {
|
|||
mod merge_parallel_fragments {
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct Type;
|
||||
|
||||
|
@ -121,7 +123,7 @@ mod merge_parallel_fragments {
|
|||
|
||||
#[test]
|
||||
fn test() {
|
||||
let schema = RootNode::new(Type, ());
|
||||
let schema = RootNode::new(Type, EmptyMutation::<()>::new());
|
||||
let doc = r"
|
||||
{ a, ...FragOne, ...FragTwo }
|
||||
fragment FragOne on Type {
|
||||
|
@ -162,6 +164,7 @@ mod merge_parallel_fragments {
|
|||
|
||||
mod threads_context_correctly {
|
||||
use value::Value;
|
||||
use types::scalars::EmptyMutation;
|
||||
use schema::model::RootNode;
|
||||
|
||||
struct Schema;
|
||||
|
@ -172,7 +175,7 @@ mod threads_context_correctly {
|
|||
|
||||
#[test]
|
||||
fn test() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<String>::new());
|
||||
let doc = r"{ a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -197,6 +200,7 @@ mod nulls_out_errors {
|
|||
use schema::model::RootNode;
|
||||
use executor::{ExecutionError, FieldResult};
|
||||
use parser::SourcePosition;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct Schema;
|
||||
|
||||
|
@ -207,7 +211,7 @@ mod nulls_out_errors {
|
|||
|
||||
#[test]
|
||||
fn test() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"{ sync, syncError }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -239,6 +243,7 @@ mod nulls_out_errors {
|
|||
mod named_operations {
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use ::GraphQLError;
|
||||
|
||||
struct Schema;
|
||||
|
@ -249,7 +254,7 @@ mod named_operations {
|
|||
|
||||
#[test]
|
||||
fn uses_inline_operation_if_no_name_provided() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"{ a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -268,7 +273,7 @@ mod named_operations {
|
|||
|
||||
#[test]
|
||||
fn uses_only_named_operation() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"query Example { a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -287,7 +292,7 @@ mod named_operations {
|
|||
|
||||
#[test]
|
||||
fn uses_named_operation_if_name_provided() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"query Example { first: a } query OtherExample { second: a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -306,7 +311,7 @@ mod named_operations {
|
|||
|
||||
#[test]
|
||||
fn error_if_multiple_operations_provided_but_no_name() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"query Example { first: a } query OtherExample { second: a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
@ -319,7 +324,7 @@ mod named_operations {
|
|||
|
||||
#[test]
|
||||
fn error_if_unknown_operation_name_provided() {
|
||||
let schema = RootNode::new(Schema, ());
|
||||
let schema = RootNode::new(Schema, EmptyMutation::<()>::new());
|
||||
let doc = r"query Example { first: a } query OtherExample { second: a }";
|
||||
|
||||
let vars = vec![].into_iter().collect();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod interface {
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
trait Pet {
|
||||
fn name(&self) -> &str;
|
||||
|
@ -71,7 +72,7 @@ mod interface {
|
|||
Box::new(Cat { name: "Garfield".to_owned(), meows: false }),
|
||||
],
|
||||
},
|
||||
());
|
||||
EmptyMutation::<()>::new());
|
||||
let doc = r"
|
||||
{
|
||||
pets {
|
||||
|
@ -118,6 +119,7 @@ mod interface {
|
|||
mod union {
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
trait Pet {
|
||||
fn as_dog(&self) -> Option<&Dog> { None }
|
||||
|
@ -178,7 +180,7 @@ mod union {
|
|||
Box::new(Cat { name: "Garfield".to_owned(), meows: false }),
|
||||
],
|
||||
},
|
||||
());
|
||||
EmptyMutation::<()>::new());
|
||||
let doc = r"
|
||||
{
|
||||
pets {
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
enum Sample {
|
||||
One,
|
||||
|
@ -67,7 +68,7 @@ fn test_execution() {
|
|||
second: sampleScalar(first: 10 second: 20)
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
@ -104,7 +105,7 @@ fn enum_introspection() {
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
@ -182,7 +183,7 @@ fn interface_introspection() {
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
@ -283,7 +284,7 @@ fn object_introspection() {
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
@ -395,7 +396,7 @@ fn scalar_introspection() {
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -6,6 +6,7 @@ use schema::model::RootNode;
|
|||
use ::GraphQLError::ValidationError;
|
||||
use validation::RuleError;
|
||||
use parser::SourcePosition;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TestComplexScalar;
|
||||
|
@ -88,7 +89,7 @@ graphql_object!(TestType: () |&self| {
|
|||
fn run_variable_query<F>(query: &str, vars: HashMap<String, InputValue>, f: F)
|
||||
where F: Fn(&HashMap<String, Value>) -> ()
|
||||
{
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(query, None, &schema, &vars, &())
|
||||
.expect("Execution failed");
|
||||
|
@ -196,7 +197,7 @@ fn variable_runs_from_input_value_on_scalar() {
|
|||
|
||||
#[test]
|
||||
fn variable_error_on_nested_non_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -220,7 +221,7 @@ fn variable_error_on_nested_non_null() {
|
|||
|
||||
#[test]
|
||||
fn variable_error_on_incorrect_type() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -240,7 +241,7 @@ fn variable_error_on_incorrect_type() {
|
|||
|
||||
#[test]
|
||||
fn variable_error_on_omit_non_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -263,7 +264,7 @@ fn variable_error_on_omit_non_null() {
|
|||
|
||||
#[test]
|
||||
fn variable_multiple_errors_with_nesting() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestNestedInputObject) { fieldWithNestedObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -291,7 +292,7 @@ fn variable_multiple_errors_with_nesting() {
|
|||
|
||||
#[test]
|
||||
fn variable_error_on_additional_field() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -377,7 +378,7 @@ fn allow_nullable_inputs_to_be_set_to_value_directly() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_non_nullable_input_to_be_omitted_in_variable() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($value: String!) { fieldWithNonNullableStringInput(input: $value) }"#;
|
||||
let vars = vec![
|
||||
|
@ -396,7 +397,7 @@ fn does_not_allow_non_nullable_input_to_be_omitted_in_variable() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_non_nullable_input_to_be_set_to_null_in_variable() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($value: String!) { fieldWithNonNullableStringInput(input: $value) }"#;
|
||||
let vars = vec![
|
||||
|
@ -489,7 +490,7 @@ fn allow_lists_to_contain_null() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_non_null_lists_to_be_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: [String]!) { nnList(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -572,7 +573,7 @@ fn allow_lists_of_non_null_to_contain_values() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_lists_of_non_null_to_contain_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: [String!]) { listNn(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -596,7 +597,7 @@ fn does_not_allow_lists_of_non_null_to_contain_null() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_non_null_lists_of_non_null_to_contain_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: [String!]!) { nnListNn(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -620,7 +621,7 @@ fn does_not_allow_non_null_lists_of_non_null_to_contain_null() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_non_null_lists_of_non_null_to_be_null() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: [String!]!) { nnListNn(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -656,7 +657,7 @@ fn allow_non_null_lists_of_non_null_to_contain_values() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_invalid_types_to_be_used_as_values() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: TestType!) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
@ -679,7 +680,7 @@ fn does_not_allow_invalid_types_to_be_used_as_values() {
|
|||
|
||||
#[test]
|
||||
fn does_not_allow_unknown_types_to_be_used_as_values() {
|
||||
let schema = RootNode::new(TestType, ());
|
||||
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
|
||||
|
||||
let query = r#"query q($input: UnknownType!) { fieldWithObjectInput(input: $input) }"#;
|
||||
let vars = vec![
|
||||
|
|
|
@ -25,11 +25,11 @@ use ::{InputValue, GraphQLType, RootNode, execute};
|
|||
pub struct GraphQLHandler<CtxFactory, Query, Mutation, CtxT>
|
||||
where CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static,
|
||||
CtxT: 'static,
|
||||
Query: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Query: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
{
|
||||
context_factory: CtxFactory,
|
||||
root_node: RootNode<CtxT, Query, Mutation>,
|
||||
root_node: RootNode<Query, Mutation>,
|
||||
}
|
||||
|
||||
/// Handler that renders GraphiQL - a graphical query editor interface
|
||||
|
@ -41,8 +41,8 @@ impl<CtxFactory, Query, Mutation, CtxT>
|
|||
GraphQLHandler<CtxFactory, Query, Mutation, CtxT>
|
||||
where CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static,
|
||||
CtxT: 'static,
|
||||
Query: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Query: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
{
|
||||
/// Build a new GraphQL handler
|
||||
///
|
||||
|
@ -150,8 +150,8 @@ impl<CtxFactory, Query, Mutation, CtxT>
|
|||
for GraphQLHandler<CtxFactory, Query, Mutation, CtxT>
|
||||
where CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static,
|
||||
CtxT: 'static,
|
||||
Query: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<CtxT> + Send + Sync + 'static,
|
||||
Query: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
Mutation: GraphQLType<Context=CtxT> + Send + Sync + 'static,
|
||||
{
|
||||
fn handle(&self, req: &mut Request) -> IronResult<Response> {
|
||||
match req.method {
|
||||
|
@ -248,6 +248,7 @@ mod tests {
|
|||
use iron::{Handler, Headers};
|
||||
|
||||
use ::tests::model::Database;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
use super::GraphQLHandler;
|
||||
|
||||
|
@ -259,7 +260,7 @@ mod tests {
|
|||
Box::new(GraphQLHandler::new(
|
||||
context_factory,
|
||||
Database::new(),
|
||||
(),
|
||||
EmptyMutation::<Database>::new(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
23
src/lib.rs
23
src/lib.rs
|
@ -33,14 +33,18 @@ existing object types as GraphQL objects:
|
|||
```rust
|
||||
#[macro_use] extern crate juniper;
|
||||
# use std::collections::HashMap;
|
||||
use juniper::FieldResult;
|
||||
use juniper::{Context, FieldResult};
|
||||
|
||||
struct User { id: String, name: String, friend_ids: Vec<String> }
|
||||
struct QueryRoot;
|
||||
struct Database { users: HashMap<String, User> }
|
||||
|
||||
impl Context for Database {}
|
||||
|
||||
// GraphQL objects can access a "context object" during execution. Use this
|
||||
// object to provide e.g. database access to the field accessors.
|
||||
// object to provide e.g. database access to the field accessors. This object
|
||||
// must implement the `Context` trait. If you don't need a context, use the
|
||||
// empty tuple `()` to indicate this.
|
||||
//
|
||||
// In this example, we use the Database struct as our context.
|
||||
graphql_object!(User: Database |&self| {
|
||||
|
@ -105,6 +109,7 @@ extern crate iron;
|
|||
|
||||
use iron::prelude::*;
|
||||
use juniper::iron_handlers::GraphQLHandler;
|
||||
use juniper::{Context, EmptyMutation};
|
||||
|
||||
# use juniper::FieldResult;
|
||||
#
|
||||
|
@ -150,11 +155,14 @@ fn context_factory(_: &mut Request) -> Database {
|
|||
}
|
||||
}
|
||||
|
||||
impl Context for Database {}
|
||||
|
||||
fn main() {
|
||||
// GraphQLHandler takes a context factory function, the root object,
|
||||
// and the mutation object. If we don't have any mutations to expose, we
|
||||
// can use the empty tuple () to indicate absence.
|
||||
let graphql_endpoint = GraphQLHandler::new(context_factory, QueryRoot, ());
|
||||
let graphql_endpoint = GraphQLHandler::new(
|
||||
context_factory, QueryRoot, EmptyMutation::<Database>::new());
|
||||
|
||||
// Start serving the schema at the root on port 8080.
|
||||
Iron::new(graphql_endpoint).http("localhost:8080").unwrap();
|
||||
|
@ -212,10 +220,11 @@ pub use ast::{ToInputValue, FromInputValue, InputValue, Type, Selection};
|
|||
pub use value::Value;
|
||||
pub use types::base::{Arguments, GraphQLType, TypeKind};
|
||||
pub use executor::{
|
||||
Context, FromContext,
|
||||
Executor, Registry, ExecutionResult, ExecutionError, FieldResult, IntoFieldResult,
|
||||
};
|
||||
pub use validation::RuleError;
|
||||
pub use types::scalars::ID;
|
||||
pub use types::scalars::{EmptyMutation, ID};
|
||||
pub use schema::model::RootNode;
|
||||
pub use result_ext::ResultExt;
|
||||
|
||||
|
@ -238,13 +247,13 @@ pub enum GraphQLError<'a> {
|
|||
pub fn execute<'a, CtxT, QueryT, MutationT>(
|
||||
document_source: &'a str,
|
||||
operation_name: Option<&str>,
|
||||
root_node: &RootNode<CtxT, QueryT, MutationT>,
|
||||
root_node: &RootNode<QueryT, MutationT>,
|
||||
variables: &HashMap<String, InputValue>,
|
||||
context: &CtxT,
|
||||
)
|
||||
-> Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>
|
||||
where QueryT: GraphQLType<CtxT>,
|
||||
MutationT: GraphQLType<CtxT>,
|
||||
where QueryT: GraphQLType<Context=CtxT>,
|
||||
MutationT: GraphQLType<Context=CtxT>,
|
||||
{
|
||||
let document = try!(parse_document_source(document_source));
|
||||
|
||||
|
|
|
@ -59,12 +59,14 @@ macro_rules! graphql_enum {
|
|||
( $name:path, $outname:tt, $descr:tt ),
|
||||
[ $( ( $eval:tt, $ename:tt, $edescr:tt, $edepr:tt ) , )* ]
|
||||
) => {
|
||||
impl<CtxT> $crate::GraphQLType<CtxT> for $name {
|
||||
impl $crate::GraphQLType for $name {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some(graphql_enum!(@as_expr, $outname))
|
||||
}
|
||||
|
||||
fn meta(registry: &mut $crate::Registry<CtxT>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
graphql_enum!(
|
||||
@maybe_apply, $descr, description,
|
||||
registry.build_enum_type::<$name>()(&[
|
||||
|
@ -81,7 +83,7 @@ macro_rules! graphql_enum {
|
|||
.into_meta()
|
||||
}
|
||||
|
||||
fn resolve(&self, _: Option<Vec<$crate::Selection>>, _: &$crate::Executor<CtxT>) -> $crate::Value {
|
||||
fn resolve(&self, _: Option<Vec<$crate::Selection>>, _: &$crate::Executor<Self::Context>) -> $crate::Value {
|
||||
match self {
|
||||
$(
|
||||
&graphql_enum!(@as_pattern, $eval) =>
|
||||
|
|
|
@ -77,7 +77,8 @@ macro_rules! __graphql__build_field_matches {
|
|||
$body
|
||||
})();
|
||||
|
||||
return ($crate::IntoFieldResult::into(result)).and_then(|r| $executorvar.resolve(&r))
|
||||
return ($crate::IntoFieldResult::into(result)).and_then(
|
||||
|r| $executorvar.resolve_with_ctx(&r))
|
||||
}
|
||||
)*
|
||||
panic!("Field {} not found on type {}", $fieldvar, $outname);
|
||||
|
|
|
@ -148,12 +148,14 @@ macro_rules! graphql_input_object {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> $crate::GraphQLType<CtxT> for $name {
|
||||
impl $crate::GraphQLType for $name {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some($outname)
|
||||
}
|
||||
|
||||
fn meta(registry: &mut $crate::Registry<CtxT>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
graphql_input_object!(
|
||||
@maybe_apply, $descr, description,
|
||||
registry.build_input_object_type::<$name>()(
|
||||
|
|
|
@ -192,7 +192,7 @@ macro_rules! graphql_interface {
|
|||
|
||||
$(
|
||||
if let Some(_) = $resolver as Option<$srctype> {
|
||||
return (<$srctype as $crate::GraphQLType<$ctxttype>>::name()).unwrap().to_owned();
|
||||
return (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned();
|
||||
}
|
||||
)*
|
||||
|
||||
|
@ -208,7 +208,7 @@ macro_rules! graphql_interface {
|
|||
let $ctxtvar = &$execarg.context();
|
||||
|
||||
$(
|
||||
if $typenamearg == (<$srctype as $crate::GraphQLType<$ctxttype>>::name()).unwrap().to_owned() {
|
||||
if $typenamearg == (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned() {
|
||||
return $execarg.resolve(&$resolver);
|
||||
}
|
||||
)*
|
||||
|
@ -227,14 +227,16 @@ macro_rules! graphql_interface {
|
|||
$( $items:tt )*
|
||||
}
|
||||
) => {
|
||||
graphql_interface!(@as_item, impl<$($lifetime)*> $crate::GraphQLType<$ctxt> for $name {
|
||||
graphql_interface!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name {
|
||||
type Context = $ctxt;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some($outname)
|
||||
}
|
||||
|
||||
#[allow(unused_assignments)]
|
||||
#[allow(unused_mut)]
|
||||
fn meta(registry: &mut $crate::Registry<$ctxt>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
let mut fields = Vec::new();
|
||||
let mut description = None;
|
||||
graphql_interface!(@ gather_meta, (registry, fields, description), $($items)*);
|
||||
|
@ -249,14 +251,14 @@ macro_rules! graphql_interface {
|
|||
|
||||
#[allow(unused_variables)]
|
||||
#[allow(unused_mut)]
|
||||
fn resolve_field(&$mainself, field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor<$ctxt>) -> $crate::ExecutionResult {
|
||||
fn resolve_field(&$mainself, field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor<Self::Context>) -> $crate::ExecutionResult {
|
||||
__graphql__build_field_matches!(
|
||||
($outname, $mainself, field, args, executor),
|
||||
(),
|
||||
$($items)*);
|
||||
}
|
||||
|
||||
fn concrete_type_name(&$mainself, context: &$ctxt) -> String {
|
||||
fn concrete_type_name(&$mainself, context: &Self::Context) -> String {
|
||||
graphql_interface!(
|
||||
@ concrete_type_name,
|
||||
($outname, context, $ctxt),
|
||||
|
@ -267,7 +269,7 @@ macro_rules! graphql_interface {
|
|||
&$mainself,
|
||||
type_name: &str,
|
||||
_: Option<Vec<$crate::Selection>>,
|
||||
executor: &$crate::Executor<$ctxt>,
|
||||
executor: &$crate::Executor<Self::Context>,
|
||||
)
|
||||
-> $crate::ExecutionResult
|
||||
{
|
||||
|
|
|
@ -348,14 +348,16 @@ macro_rules! graphql_object {
|
|||
( $($lifetime:tt)* );
|
||||
$name:ty; $ctxt:ty; $outname:expr; $mainself:ident; $($items:tt)*
|
||||
) => {
|
||||
graphql_object!(@as_item, impl<$($lifetime)*> $crate::GraphQLType<$ctxt> for $name {
|
||||
graphql_object!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name {
|
||||
type Context = $ctxt;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some($outname)
|
||||
}
|
||||
|
||||
#[allow(unused_assignments)]
|
||||
#[allow(unused_mut)]
|
||||
fn meta(registry: &mut $crate::Registry<$ctxt>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
let mut fields = Vec::new();
|
||||
let mut description = None;
|
||||
let mut interfaces: Option<Vec<$crate::Type>> = None;
|
||||
|
@ -382,7 +384,7 @@ macro_rules! graphql_object {
|
|||
&$mainself,
|
||||
field: &str,
|
||||
args: &$crate::Arguments,
|
||||
executor: &$crate::Executor<$ctxt>
|
||||
executor: &$crate::Executor<Self::Context>
|
||||
)
|
||||
-> $crate::ExecutionResult
|
||||
{
|
||||
|
|
|
@ -61,12 +61,14 @@ macro_rules! graphql_scalar {
|
|||
( $fiv_arg:ident, $fiv_result:ty, $fiv_body:block )
|
||||
)
|
||||
) => {
|
||||
impl<CtxT> $crate::GraphQLType<CtxT> for $name {
|
||||
impl $crate::GraphQLType for $name {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some($outname)
|
||||
}
|
||||
|
||||
fn meta(registry: &mut $crate::Registry<CtxT>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
graphql_scalar!(
|
||||
@maybe_apply, $descr, description,
|
||||
registry.build_scalar_type::<Self>())
|
||||
|
@ -76,7 +78,7 @@ macro_rules! graphql_scalar {
|
|||
fn resolve(
|
||||
&$resolve_selfvar,
|
||||
_: Option<Vec<$crate::Selection>>,
|
||||
_: &$crate::Executor<CtxT>) -> $crate::Value {
|
||||
_: &$crate::Executor<Self::Context>) -> $crate::Value {
|
||||
$resolve_body
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct Root;
|
||||
|
||||
|
@ -87,7 +88,7 @@ fn run_args_info_query<F>(field_name: &str, f: F)
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
|
||||
enum DefaultName { Foo, Bar }
|
||||
|
@ -67,7 +68,7 @@ graphql_object!(Root: () |&self| {
|
|||
});
|
||||
|
||||
fn run_type_info_query<F>(doc: &str, f: F) where F: Fn((&HashMap<String, Value>, &Vec<Value>)) -> () {
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -4,6 +4,7 @@ use value::Value;
|
|||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
use executor::FieldResult;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct Interface;
|
||||
struct Root;
|
||||
|
@ -71,7 +72,7 @@ fn run_field_info_query<F>(type_name: &str, field_name: &str, f: F)
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
let vars = vec![
|
||||
("typeName".to_owned(), InputValue::string(type_name)),
|
||||
].into_iter().collect();
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||
use ast::{InputValue, FromInputValue};
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct Root;
|
||||
|
||||
|
@ -62,7 +63,7 @@ graphql_object!(Root: () |&self| {
|
|||
});
|
||||
|
||||
fn run_type_info_query<F>(doc: &str, f: F) where F: Fn(&HashMap<String, Value>, &Vec<Value>) -> () {
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||
use ast::InputValue;
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
/*
|
||||
|
||||
|
@ -142,7 +143,7 @@ fn run_type_info_query<F>(type_name: &str, f: F)
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
let vars = vec![
|
||||
("typeName".to_owned(), InputValue::string(type_name)),
|
||||
].into_iter().collect();
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||
use ast::InputValue;
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
/*
|
||||
|
||||
|
@ -130,7 +131,7 @@ fn run_type_info_query<F>(type_name: &str, f: F)
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
let vars = vec![
|
||||
("typeName".to_owned(), InputValue::string(type_name)),
|
||||
].into_iter().collect();
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
struct DefaultName(i64);
|
||||
struct OtherOrder(i64);
|
||||
|
@ -69,7 +70,7 @@ graphql_object!(Root: () |&self| {
|
|||
});
|
||||
|
||||
fn run_type_info_query<F>(doc: &str, f: F) where F: Fn(&HashMap<String, Value>) -> () {
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
|
||||
let (result, errs) = ::execute(doc, None, &schema, &HashMap::new(), &())
|
||||
.expect("Execution failed");
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||
use ast::InputValue;
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
/*
|
||||
|
||||
|
@ -109,7 +110,7 @@ fn run_type_info_query<F>(type_name: &str, f: F)
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let schema = RootNode::new(Root {}, ());
|
||||
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
|
||||
let vars = vec![
|
||||
("typeName".to_owned(), InputValue::string(type_name)),
|
||||
].into_iter().collect();
|
||||
|
|
|
@ -62,7 +62,7 @@ macro_rules! graphql_union {
|
|||
|
||||
$(
|
||||
if let Some(_) = $resolver as Option<$srctype> {
|
||||
return (<$srctype as $crate::GraphQLType<$ctxttype>>::name()).unwrap().to_owned();
|
||||
return (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned();
|
||||
}
|
||||
)*
|
||||
|
||||
|
@ -79,7 +79,7 @@ macro_rules! graphql_union {
|
|||
let $ctxtvar = &$execarg.context();
|
||||
|
||||
$(
|
||||
if $typenamearg == (<$srctype as $crate::GraphQLType<$ctxttype>>::name()).unwrap().to_owned() {
|
||||
if $typenamearg == (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned() {
|
||||
return $execarg.resolve(&$resolver);
|
||||
}
|
||||
)*
|
||||
|
@ -105,14 +105,16 @@ macro_rules! graphql_union {
|
|||
$( $items:tt )*
|
||||
}
|
||||
) => {
|
||||
graphql_union!(@as_item, impl<$($lifetime)*> $crate::GraphQLType<$ctxt> for $name {
|
||||
graphql_union!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name {
|
||||
type Context = $ctxt;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some($outname)
|
||||
}
|
||||
|
||||
#[allow(unused_assignments)]
|
||||
#[allow(unused_mut)]
|
||||
fn meta(registry: &mut $crate::Registry<$ctxt>) -> $crate::meta::MetaType {
|
||||
fn meta(registry: &mut $crate::Registry) -> $crate::meta::MetaType {
|
||||
let mut types;
|
||||
let mut description = None;
|
||||
graphql_union!(@ gather_meta, (registry, types, description), $($items)*);
|
||||
|
@ -125,7 +127,7 @@ macro_rules! graphql_union {
|
|||
mt.into_meta()
|
||||
}
|
||||
|
||||
fn concrete_type_name(&$mainself, context: &$ctxt) -> String {
|
||||
fn concrete_type_name(&$mainself, context: &Self::Context) -> String {
|
||||
graphql_union!(
|
||||
@ concrete_type_name,
|
||||
($outname, context, $ctxt),
|
||||
|
@ -136,7 +138,7 @@ macro_rules! graphql_union {
|
|||
&$mainself,
|
||||
type_name: &str,
|
||||
_: Option<Vec<$crate::Selection>>,
|
||||
executor: &$crate::Executor<$ctxt>,
|
||||
executor: &$crate::Executor<Self::Context>,
|
||||
)
|
||||
-> $crate::ExecutionResult
|
||||
{
|
||||
|
|
|
@ -1,37 +1,24 @@
|
|||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::fmt;
|
||||
|
||||
use types::base::{GraphQLType};
|
||||
use executor::Registry;
|
||||
use executor::{Registry, Context};
|
||||
use ast::Type;
|
||||
use schema::meta::{MetaType, ObjectMeta, PlaceholderMeta, UnionMeta, InterfaceMeta, Argument};
|
||||
|
||||
/// Root query node of a schema
|
||||
///
|
||||
/// This brings the mutatino and query types together, and provides the
|
||||
/// This brings the mutation and query types together, and provides the
|
||||
/// predefined metadata fields.
|
||||
pub struct RootNode<InnerT, QueryT, MutationT=()> {
|
||||
pub struct RootNode<QueryT, MutationT> {
|
||||
#[doc(hidden)]
|
||||
pub query_type: QueryT,
|
||||
#[doc(hidden)]
|
||||
pub mutation_type: MutationT,
|
||||
#[doc(hidden)]
|
||||
pub schema: SchemaType,
|
||||
phantom_wrapped: PhantomData<InnerT>,
|
||||
}
|
||||
|
||||
// RootNode implements Send + Sync if both the mutation type and query
|
||||
// type implements them. SchemaType also needs to implement them.
|
||||
//
|
||||
// InnerT does _not_ need to implement Send + Sync because it does not
|
||||
// actually appear in the struct.
|
||||
unsafe impl<InnerT, QueryT, MutationT> Send for RootNode<InnerT, QueryT, MutationT>
|
||||
where QueryT: Send, MutationT: Send, SchemaType: Send { }
|
||||
|
||||
unsafe impl<InnerT, QueryT, MutationT> Sync for RootNode<InnerT, QueryT, MutationT>
|
||||
where QueryT: Sync, MutationT: Sync, SchemaType: Sync { }
|
||||
|
||||
/// Metadata for a schema
|
||||
pub struct SchemaType {
|
||||
types: HashMap<String, MetaType>,
|
||||
|
@ -40,6 +27,8 @@ pub struct SchemaType {
|
|||
directives: HashMap<String, DirectiveType>,
|
||||
}
|
||||
|
||||
impl Context for SchemaType {}
|
||||
|
||||
pub enum TypeType<'a> {
|
||||
Concrete(&'a MetaType),
|
||||
NonNull(Box<TypeType<'a>>),
|
||||
|
@ -63,82 +52,72 @@ pub enum DirectiveLocation {
|
|||
InlineFragment,
|
||||
}
|
||||
|
||||
impl<InnerT, QueryT, MutationT> RootNode<InnerT, QueryT, MutationT>
|
||||
where QueryT: GraphQLType<InnerT>,
|
||||
MutationT: GraphQLType<InnerT>,
|
||||
impl<QueryT, MutationT> RootNode<QueryT, MutationT>
|
||||
where QueryT: GraphQLType,
|
||||
MutationT: GraphQLType,
|
||||
{
|
||||
/// Construct a new root node from query and mutation nodes
|
||||
///
|
||||
/// If the schema should not support mutations, you can pass in `()` to
|
||||
/// remove the mutation type from the schema.
|
||||
pub fn new(query_obj: QueryT, mutation_obj: MutationT) -> RootNode<InnerT, QueryT, MutationT> {
|
||||
/// If the schema should not support mutations, use the
|
||||
/// `new` constructor instead.
|
||||
pub fn new(query_obj: QueryT, mutation_obj: MutationT) -> RootNode<QueryT, MutationT> {
|
||||
RootNode {
|
||||
query_type: query_obj,
|
||||
mutation_type: mutation_obj,
|
||||
schema: SchemaType::new::<InnerT, QueryT, MutationT>(),
|
||||
phantom_wrapped: PhantomData,
|
||||
schema: SchemaType::new::<QueryT, MutationT>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemaType {
|
||||
pub fn new<CtxT, QueryT, MutationT>() -> SchemaType
|
||||
where QueryT: GraphQLType<CtxT>,
|
||||
MutationT: GraphQLType<CtxT>,
|
||||
pub fn new<QueryT, MutationT>() -> SchemaType
|
||||
where QueryT: GraphQLType,
|
||||
MutationT: GraphQLType,
|
||||
{
|
||||
let mut types = HashMap::new();
|
||||
let mut directives = HashMap::new();
|
||||
let query_type_name: String;
|
||||
let mutation_type_name: String;
|
||||
|
||||
{
|
||||
let mut registry = Registry::<CtxT>::new(types);
|
||||
query_type_name = registry.get_type::<QueryT>().innermost_name().to_owned();
|
||||
mutation_type_name = registry.get_type::<MutationT>().innermost_name().to_owned();
|
||||
types = registry.types;
|
||||
}
|
||||
let mut registry = Registry::new(HashMap::new());
|
||||
query_type_name = registry.get_type::<QueryT>().innermost_name().to_owned();
|
||||
mutation_type_name = registry.get_type::<MutationT>().innermost_name().to_owned();
|
||||
|
||||
{
|
||||
let mut registry = Registry::<SchemaType>::new(types);
|
||||
registry.get_type::<SchemaType>();
|
||||
directives.insert(
|
||||
"skip".to_owned(),
|
||||
DirectiveType::new_skip(&mut registry));
|
||||
directives.insert(
|
||||
"include".to_owned(),
|
||||
DirectiveType::new_include(&mut registry));
|
||||
registry.get_type::<SchemaType>();
|
||||
directives.insert(
|
||||
"skip".to_owned(),
|
||||
DirectiveType::new_skip(&mut registry));
|
||||
directives.insert(
|
||||
"include".to_owned(),
|
||||
DirectiveType::new_include(&mut registry));
|
||||
|
||||
let mut meta_fields = vec![
|
||||
registry.field::<SchemaType>("__schema"),
|
||||
registry.field::<TypeType>("__type")
|
||||
.argument(registry.arg::<String>("name")),
|
||||
];
|
||||
let mut meta_fields = vec![
|
||||
registry.field::<SchemaType>("__schema"),
|
||||
registry.field::<TypeType>("__type")
|
||||
.argument(registry.arg::<String>("name")),
|
||||
];
|
||||
|
||||
if let Some(root_type) = registry.types.get_mut(&query_type_name) {
|
||||
if let &mut MetaType::Object(ObjectMeta { ref mut fields, .. }) = root_type {
|
||||
fields.append(&mut meta_fields);
|
||||
}
|
||||
else {
|
||||
panic!("Root type is not an object");
|
||||
}
|
||||
if let Some(root_type) = registry.types.get_mut(&query_type_name) {
|
||||
if let &mut MetaType::Object(ObjectMeta { ref mut fields, .. }) = root_type {
|
||||
fields.append(&mut meta_fields);
|
||||
}
|
||||
else {
|
||||
panic!("Root type not found");
|
||||
panic!("Root type is not an object");
|
||||
}
|
||||
|
||||
types = registry.types;
|
||||
}
|
||||
else {
|
||||
panic!("Root type not found");
|
||||
}
|
||||
|
||||
for meta_type in types.values() {
|
||||
for meta_type in registry.types.values() {
|
||||
if let MetaType::Placeholder(PlaceholderMeta { ref of_type }) = *meta_type {
|
||||
panic!("Type {:?} is still a placeholder type", of_type);
|
||||
}
|
||||
}
|
||||
|
||||
SchemaType {
|
||||
types: types,
|
||||
types: registry.types,
|
||||
query_type_name: query_type_name,
|
||||
mutation_type_name: if &mutation_type_name != "__Unit" { Some(mutation_type_name) } else { None },
|
||||
mutation_type_name: if &mutation_type_name != "__EmptyMutation" { Some(mutation_type_name) } else { None },
|
||||
directives: directives,
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +284,7 @@ impl DirectiveType {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_skip<CtxT>(registry: &mut Registry<CtxT>) -> DirectiveType {
|
||||
fn new_skip(registry: &mut Registry) -> DirectiveType {
|
||||
Self::new(
|
||||
"skip",
|
||||
&[
|
||||
|
@ -318,7 +297,7 @@ impl DirectiveType {
|
|||
])
|
||||
}
|
||||
|
||||
fn new_include<CtxT>(registry: &mut Registry<CtxT>) -> DirectiveType {
|
||||
fn new_include(registry: &mut Registry) -> DirectiveType {
|
||||
Self::new(
|
||||
"include",
|
||||
&[
|
||||
|
|
|
@ -7,15 +7,17 @@ use schema::meta::{MetaType, ObjectMeta, EnumMeta, InputObjectMeta, UnionMeta, I
|
|||
Field, Argument, EnumValue};
|
||||
use schema::model::{RootNode, SchemaType, TypeType, DirectiveType, DirectiveLocation};
|
||||
|
||||
impl<CtxT, QueryT, MutationT> GraphQLType<CtxT> for RootNode<CtxT, QueryT, MutationT>
|
||||
where QueryT: GraphQLType<CtxT>,
|
||||
MutationT: GraphQLType<CtxT>
|
||||
impl<CtxT, QueryT, MutationT> GraphQLType for RootNode<QueryT, MutationT>
|
||||
where QueryT: GraphQLType<Context=CtxT>,
|
||||
MutationT: GraphQLType<Context=CtxT>
|
||||
{
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
QueryT::name()
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
QueryT::meta(registry)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet};
|
|||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use tests::model::Database;
|
||||
use types::scalars::EmptyMutation;
|
||||
|
||||
#[test]
|
||||
fn test_query_type_name() {
|
||||
|
@ -15,7 +16,7 @@ fn test_query_type_name() {
|
|||
}
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -38,7 +39,7 @@ fn test_specific_type_name() {
|
|||
}
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -61,7 +62,7 @@ fn test_specific_object_type_name_and_kind() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -85,7 +86,7 @@ fn test_specific_interface_type_name_and_kind() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -109,7 +110,7 @@ fn test_documentation() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -135,7 +136,7 @@ fn test_possible_types() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
let result = ::execute(doc, None, &schema, &HashMap::new(), &database);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||
use ast::InputValue;
|
||||
use value::Value;
|
||||
use schema::model::RootNode;
|
||||
use types::scalars::EmptyMutation;
|
||||
use tests::model::Database;
|
||||
|
||||
#[test]
|
||||
|
@ -14,7 +15,7 @@ fn test_hero_name() {
|
|||
}
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -39,7 +40,7 @@ fn test_hero_name_and_friends() {
|
|||
}
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -80,7 +81,7 @@ fn test_hero_name_and_friends_and_friends_of_friends() {
|
|||
}
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -162,7 +163,7 @@ fn test_hero_name_and_friends_and_friends_of_friends() {
|
|||
fn test_query_name() {
|
||||
let doc = r#"{ human(id: "1000") { name } }"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -178,7 +179,7 @@ fn test_query_name() {
|
|||
fn test_query_alias_single() {
|
||||
let doc = r#"{ luke: human(id: "1000") { name } }"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -198,7 +199,7 @@ fn test_query_alias_multiple() {
|
|||
leia: human(id: "1003") { name }
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -226,7 +227,7 @@ fn test_query_alias_multiple_with_fragment() {
|
|||
homePlanet
|
||||
}"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -247,7 +248,7 @@ fn test_query_alias_multiple_with_fragment() {
|
|||
fn test_query_name_variable() {
|
||||
let doc = r#"query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } }"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
let vars = vec![
|
||||
("someId".to_owned(), InputValue::string("1000")),
|
||||
|
@ -267,7 +268,7 @@ fn test_query_name_variable() {
|
|||
fn test_query_name_invalid_variable() {
|
||||
let doc = r#"query FetchSomeIDQuery($someId: String!) { human(id: $someId) { name } }"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
let vars = vec![
|
||||
("someId".to_owned(), InputValue::string("some invalid id")),
|
||||
|
@ -285,7 +286,7 @@ fn test_query_name_invalid_variable() {
|
|||
fn test_query_friends_names() {
|
||||
let doc = r#"{ human(id: "1000") { friends { name } } }"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -325,7 +326,7 @@ fn test_query_inline_fragments_droid() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
@ -350,7 +351,7 @@ fn test_query_inline_fragments_human() {
|
|||
}
|
||||
"#;
|
||||
let database = Database::new();
|
||||
let schema = RootNode::new(&database, ());
|
||||
let schema = RootNode::new(&database, EmptyMutation::<Database>::new());
|
||||
|
||||
assert_eq!(
|
||||
::execute(doc, None, &schema, &HashMap::new(), &database),
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use tests::model::{Character, Human, Droid, Database, Episode};
|
||||
use executor::Context;
|
||||
|
||||
impl Context for Database {}
|
||||
|
||||
graphql_enum!(Episode {
|
||||
Episode::NewHope => "NEW_HOPE",
|
||||
|
|
|
@ -135,7 +135,7 @@ equivalent of the `User` object as shown in the example in the documentation
|
|||
root:
|
||||
|
||||
```rust
|
||||
use juniper::{GraphQLType, Registry, FieldResult,
|
||||
use juniper::{GraphQLType, Registry, FieldResult, Context,
|
||||
Arguments, Executor, ExecutionResult};
|
||||
use juniper::meta::MetaType;
|
||||
# use std::collections::HashMap;
|
||||
|
@ -143,15 +143,19 @@ use juniper::meta::MetaType;
|
|||
struct User { id: String, name: String, friend_ids: Vec<String> }
|
||||
struct Database { users: HashMap<String, User> }
|
||||
|
||||
impl GraphQLType<Database> for User {
|
||||
impl Context for Database {}
|
||||
|
||||
impl GraphQLType for User {
|
||||
type Context = Database;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("User")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<Database>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
// First, we need to define all fields and their types on this type.
|
||||
//
|
||||
// If need arguments, want to implement interfaces, or want to add
|
||||
// If we need arguments, want to implement interfaces, or want to add
|
||||
// documentation strings, we can do it here.
|
||||
registry.build_object_type::<User>()(&[
|
||||
registry.field::<&String>("id"),
|
||||
|
@ -171,12 +175,15 @@ impl GraphQLType<Database> for User {
|
|||
{
|
||||
// Next, we need to match the queried field name. All arms of this
|
||||
// match statement return `ExecutionResult`, which makes it hard to
|
||||
// statically verify that the type you pass on to `executor.resolve`
|
||||
// statically verify that the type you pass on to `executor.resolve*`
|
||||
// actually matches the one that you defined in `meta()` above.
|
||||
let database = executor.context();
|
||||
match field_name {
|
||||
"id" => executor.resolve(&self.id),
|
||||
"name" => executor.resolve(&self.name),
|
||||
// Because scalars are defined with another `Context` associated
|
||||
// type, you must use resolve_with_ctx here to make the executor
|
||||
// perform automatic type conversion of its argument.
|
||||
"id" => executor.resolve_with_ctx(&self.id),
|
||||
"name" => executor.resolve_with_ctx(&self.name),
|
||||
|
||||
// You pass a vector of User objects to `executor.resolve`, and it
|
||||
// will determine which fields of the sub-objects to actually
|
||||
|
@ -201,7 +208,14 @@ impl GraphQLType<Database> for User {
|
|||
```
|
||||
|
||||
*/
|
||||
pub trait GraphQLType<CtxT>: Sized {
|
||||
pub trait GraphQLType: Sized {
|
||||
/// The expected context type for this GraphQL type
|
||||
///
|
||||
/// The context is threaded through query execution to all affected nodes,
|
||||
/// and can be used to hold common data, e.g. database connections or
|
||||
/// request session information.
|
||||
type Context;
|
||||
|
||||
/// The name of the GraphQL type to expose.
|
||||
///
|
||||
/// This function will be called multiple times during schema construction.
|
||||
|
@ -210,7 +224,7 @@ pub trait GraphQLType<CtxT>: Sized {
|
|||
fn name() -> Option<&'static str>;
|
||||
|
||||
/// The meta type representing this GraphQL type.
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType;
|
||||
fn meta(registry: &mut Registry) -> MetaType;
|
||||
|
||||
/// Resolve the value of a single field on this type.
|
||||
///
|
||||
|
@ -221,7 +235,7 @@ pub trait GraphQLType<CtxT>: Sized {
|
|||
///
|
||||
/// The default implementation panics.
|
||||
#[allow(unused_variables)]
|
||||
fn resolve_field(&self, field_name: &str, arguments: &Arguments, executor: &Executor<CtxT>)
|
||||
fn resolve_field(&self, field_name: &str, arguments: &Arguments, executor: &Executor<Self::Context>)
|
||||
-> ExecutionResult
|
||||
{
|
||||
panic!("resolve_field must be implemented by object types");
|
||||
|
@ -234,7 +248,7 @@ pub trait GraphQLType<CtxT>: Sized {
|
|||
///
|
||||
/// The default implementation panics.
|
||||
#[allow(unused_variables)]
|
||||
fn resolve_into_type(&self, type_name: &str, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> ExecutionResult {
|
||||
fn resolve_into_type(&self, type_name: &str, selection_set: Option<Vec<Selection>>, executor: &Executor<Self::Context>) -> ExecutionResult {
|
||||
if Self::name().unwrap() == type_name {
|
||||
Ok(self.resolve(selection_set, executor))
|
||||
} else {
|
||||
|
@ -246,7 +260,7 @@ pub trait GraphQLType<CtxT>: Sized {
|
|||
///
|
||||
/// The default implementation panics.
|
||||
#[allow(unused_variables)]
|
||||
fn concrete_type_name(&self, context: &CtxT) -> String {
|
||||
fn concrete_type_name(&self, context: &Self::Context) -> String {
|
||||
panic!("concrete_type_name must be implemented by unions and interfaces");
|
||||
}
|
||||
|
||||
|
@ -260,7 +274,7 @@ pub trait GraphQLType<CtxT>: Sized {
|
|||
/// The default implementation uses `resolve_field` to resolve all fields,
|
||||
/// including those through fragment expansion, for object types. For
|
||||
/// non-object types, this method panics.
|
||||
fn resolve(&self, selection_set: Option<Vec<Selection>>, executor: &Executor<CtxT>) -> Value {
|
||||
fn resolve(&self, selection_set: Option<Vec<Selection>>, executor: &Executor<Self::Context>) -> Value {
|
||||
if let Some(selection_set) = selection_set {
|
||||
let mut result = HashMap::new();
|
||||
resolve_selection_set_into(self, selection_set, executor, &mut result);
|
||||
|
@ -277,7 +291,7 @@ fn resolve_selection_set_into<T, CtxT>(
|
|||
selection_set: Vec<Selection>,
|
||||
executor: &Executor<CtxT>,
|
||||
result: &mut HashMap<String, Value>)
|
||||
where T: GraphQLType<CtxT>
|
||||
where T: GraphQLType<Context=CtxT>
|
||||
{
|
||||
let meta_type = executor.schema()
|
||||
.concrete_type_by_name(T::name().expect("Resolving named type's selection set"))
|
||||
|
|
|
@ -5,12 +5,14 @@ use schema::meta::MetaType;
|
|||
use executor::{Executor, Registry, IntoFieldResult, FieldResult};
|
||||
use types::base::{GraphQLType};
|
||||
|
||||
impl<T, CtxT> GraphQLType<CtxT> for Option<T> where T: GraphQLType<CtxT> {
|
||||
impl<T, CtxT> GraphQLType for Option<T> where T: GraphQLType<Context=CtxT> {
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_nullable_type::<T>().into_meta()
|
||||
}
|
||||
|
||||
|
@ -50,12 +52,14 @@ impl<T> IntoFieldResult<Option<T>> for Option<T> {
|
|||
}
|
||||
|
||||
|
||||
impl<T, CtxT> GraphQLType<CtxT> for Vec<T> where T: GraphQLType<CtxT> {
|
||||
impl<T, CtxT> GraphQLType for Vec<T> where T: GraphQLType<Context=CtxT> {
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_list_type::<T>().into_meta()
|
||||
}
|
||||
|
||||
|
@ -102,12 +106,14 @@ impl<T> IntoFieldResult<Vec<T>> for Vec<T> {
|
|||
}
|
||||
|
||||
|
||||
impl<'a, T, CtxT> GraphQLType<CtxT> for &'a [T] where T: GraphQLType<CtxT> {
|
||||
impl<'a, T, CtxT> GraphQLType for &'a [T] where T: GraphQLType<Context=CtxT> {
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_list_type::<T>().into_meta()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,14 @@ use schema::meta::MetaType;
|
|||
use executor::{Executor, Registry, ExecutionResult, IntoFieldResult, FieldResult};
|
||||
use types::base::{Arguments, GraphQLType};
|
||||
|
||||
impl<T, CtxT> GraphQLType<CtxT> for Box<T> where T: GraphQLType<CtxT> {
|
||||
impl<T, CtxT> GraphQLType for Box<T> where T: GraphQLType<Context=CtxT> {
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
T::name()
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
T::meta(registry)
|
||||
}
|
||||
|
||||
|
@ -49,12 +51,14 @@ impl<T> IntoFieldResult<Box<T>> for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T, CtxT> GraphQLType<CtxT> for &'a T where T: GraphQLType<CtxT> {
|
||||
impl<'a, T, CtxT> GraphQLType for &'a T where T: GraphQLType<Context=CtxT> {
|
||||
type Context = CtxT;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
T::name()
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
T::meta(registry)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use ast::{InputValue, Selection, FromInputValue, ToInputValue};
|
||||
use value::Value;
|
||||
|
||||
|
@ -40,16 +42,18 @@ graphql_scalar!(String as "String" {
|
|||
});
|
||||
|
||||
|
||||
impl<'a, CtxT> GraphQLType<CtxT> for &'a str {
|
||||
impl<'a> GraphQLType for &'a str {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("String")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_scalar_type::<String>().into_meta()
|
||||
}
|
||||
|
||||
fn resolve(&self, _: Option<Vec<Selection>>, _: &Executor<CtxT>) -> Value {
|
||||
fn resolve(&self, _: Option<Vec<Selection>>, _: &Executor<Self::Context>) -> Value {
|
||||
Value::string(self)
|
||||
}
|
||||
}
|
||||
|
@ -111,12 +115,14 @@ graphql_scalar!(f64 as "Float" {
|
|||
});
|
||||
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for () {
|
||||
impl GraphQLType for () {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("__Unit")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_scalar_type::<Self>().into_meta()
|
||||
}
|
||||
}
|
||||
|
@ -132,3 +138,39 @@ impl IntoFieldResult<()> for () {
|
|||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Utility type to define read-only schemas
|
||||
///
|
||||
/// If you instantiate `RootNode` with this as the mutation, no mutation will be
|
||||
/// generated for the schema.
|
||||
pub struct EmptyMutation<T> {
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> EmptyMutation<T> {
|
||||
/// Construct a new empty mutation
|
||||
pub fn new() -> EmptyMutation<T> {
|
||||
EmptyMutation {
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> GraphQLType for EmptyMutation<T> {
|
||||
type Context = T;
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("__EmptyMutation")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[]).into_meta()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoFieldResult<EmptyMutation<T>> for EmptyMutation<T> {
|
||||
fn into(self) -> FieldResult<EmptyMutation<T>> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1164,12 +1164,14 @@ mod tests {
|
|||
struct Node;
|
||||
struct QueryRoot;
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for SomeBox {
|
||||
impl GraphQLType for SomeBox {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("SomeBox")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<Option<SomeBox>>("deepBox"),
|
||||
registry.field::<Option<String>>("unrelatedField"),
|
||||
|
@ -1178,12 +1180,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for StringBox {
|
||||
impl GraphQLType for StringBox {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("StringBox")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("scalar"),
|
||||
registry.field::<Option<StringBox>>("deepBox"),
|
||||
|
@ -1199,12 +1203,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for IntBox {
|
||||
impl GraphQLType for IntBox {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("IntBox")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<i64>>("scalar"),
|
||||
registry.field::<Option<IntBox>>("deepBox"),
|
||||
|
@ -1220,12 +1226,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for NonNullStringBox1 {
|
||||
impl GraphQLType for NonNullStringBox1 {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("NonNullStringBox1")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<String>("scalar"),
|
||||
])
|
||||
|
@ -1233,12 +1241,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for NonNullStringBox1Impl {
|
||||
impl GraphQLType for NonNullStringBox1Impl {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("NonNullStringBox1Impl")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<String>("scalar"),
|
||||
registry.field::<Option<SomeBox>>("deepBox"),
|
||||
|
@ -1252,12 +1262,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for NonNullStringBox2 {
|
||||
impl GraphQLType for NonNullStringBox2 {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("NonNullStringBox2")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<String>("scalar"),
|
||||
])
|
||||
|
@ -1265,12 +1277,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for NonNullStringBox2Impl {
|
||||
impl GraphQLType for NonNullStringBox2Impl {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("NonNullStringBox2Impl")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<String>("scalar"),
|
||||
registry.field::<Option<SomeBox>>("deepBox"),
|
||||
|
@ -1284,12 +1298,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Node {
|
||||
impl GraphQLType for Node {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Node")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<ID>>("id"),
|
||||
registry.field::<Option<String>>("name"),
|
||||
|
@ -1298,12 +1314,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Edge {
|
||||
impl GraphQLType for Edge {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Edge")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<Node>>("node"),
|
||||
])
|
||||
|
@ -1311,12 +1329,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Connection {
|
||||
impl GraphQLType for Connection {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Connection")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<Vec<Option<Edge>>>>("edges"),
|
||||
])
|
||||
|
@ -1324,12 +1344,14 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for QueryRoot {
|
||||
impl GraphQLType for QueryRoot {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("QueryRoot")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.get_type::<IntBox>();
|
||||
registry.get_type::<StringBox>();
|
||||
registry.get_type::<NonNullStringBox1Impl>();
|
||||
|
|
|
@ -2,7 +2,7 @@ use parser::parse_document_source;
|
|||
use ast::{FromInputValue, InputValue};
|
||||
use types::base::GraphQLType;
|
||||
use executor::Registry;
|
||||
use types::scalars::ID;
|
||||
use types::scalars::{EmptyMutation, ID};
|
||||
use schema::model::{DirectiveType, DirectiveLocation, RootNode};
|
||||
use schema::meta::{EnumValue, MetaType};
|
||||
use validation::{Visitor, RuleError, ValidatorContext, MultiVisitor, visit};
|
||||
|
@ -51,12 +51,14 @@ struct ComplexInput {
|
|||
string_list_field: Option<Vec<Option<String>>>,
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Being {
|
||||
impl GraphQLType for Being {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Being")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -65,12 +67,14 @@ impl<CtxT> GraphQLType<CtxT> for Being {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Pet {
|
||||
impl GraphQLType for Pet {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Pet")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -79,12 +83,14 @@ impl<CtxT> GraphQLType<CtxT> for Pet {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Canine {
|
||||
impl GraphQLType for Canine {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Canine")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -93,12 +99,14 @@ impl<CtxT> GraphQLType<CtxT> for Canine {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for DogCommand {
|
||||
impl GraphQLType for DogCommand {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("DogCommand")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_enum_type::<Self>()(&[
|
||||
EnumValue::new("SIT"),
|
||||
EnumValue::new("HEEL"),
|
||||
|
@ -119,12 +127,14 @@ impl FromInputValue for DogCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Dog {
|
||||
impl GraphQLType for Dog {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Dog")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -148,12 +158,14 @@ impl<CtxT> GraphQLType<CtxT> for Dog {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for FurColor {
|
||||
impl GraphQLType for FurColor {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("FurColor")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_enum_type::<Self>()(&[
|
||||
EnumValue::new("BROWN"),
|
||||
EnumValue::new("BLACK"),
|
||||
|
@ -176,12 +188,14 @@ impl FromInputValue for FurColor {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Cat {
|
||||
impl GraphQLType for Cat {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Cat")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -198,12 +212,14 @@ impl<CtxT> GraphQLType<CtxT> for Cat {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for CatOrDog {
|
||||
impl GraphQLType for CatOrDog {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("CatOrDog")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_union_type::<Self>()(&[
|
||||
registry.get_type::<Cat>(),
|
||||
registry.get_type::<Dog>(),
|
||||
|
@ -212,12 +228,14 @@ impl<CtxT> GraphQLType<CtxT> for CatOrDog {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Intelligent {
|
||||
impl GraphQLType for Intelligent {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Intelligent")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_interface_type::<Self>()(&[
|
||||
registry.field::<Option<i64>>("iq"),
|
||||
])
|
||||
|
@ -225,12 +243,14 @@ impl<CtxT> GraphQLType<CtxT> for Intelligent {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Human {
|
||||
impl GraphQLType for Human {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Human")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -246,12 +266,14 @@ impl<CtxT> GraphQLType<CtxT> for Human {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for Alien {
|
||||
impl GraphQLType for Alien {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("Alien")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("name")
|
||||
.argument(registry.arg::<Option<bool>>("surname")),
|
||||
|
@ -266,12 +288,14 @@ impl<CtxT> GraphQLType<CtxT> for Alien {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for DogOrHuman {
|
||||
impl GraphQLType for DogOrHuman {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("DogOrHuman")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_union_type::<Self>()(&[
|
||||
registry.get_type::<Dog>(),
|
||||
registry.get_type::<Human>(),
|
||||
|
@ -280,12 +304,14 @@ impl<CtxT> GraphQLType<CtxT> for DogOrHuman {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for HumanOrAlien {
|
||||
impl GraphQLType for HumanOrAlien {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("HumanOrAlien")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_union_type::<Self>()(&[
|
||||
registry.get_type::<Human>(),
|
||||
registry.get_type::<Alien>(),
|
||||
|
@ -294,12 +320,14 @@ impl<CtxT> GraphQLType<CtxT> for HumanOrAlien {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for ComplexInput {
|
||||
impl GraphQLType for ComplexInput {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("ComplexInput")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_input_object_type::<Self>()(&[
|
||||
registry.arg::<bool>("requiredField"),
|
||||
registry.arg::<Option<i64>>("intField"),
|
||||
|
@ -331,12 +359,14 @@ impl FromInputValue for ComplexInput {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for ComplicatedArgs {
|
||||
impl GraphQLType for ComplicatedArgs {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("ComplicatedArgs")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<String>>("intArgField")
|
||||
.argument(registry.arg::<Option<i64>>("intArg")),
|
||||
|
@ -372,12 +402,14 @@ impl<CtxT> GraphQLType<CtxT> for ComplicatedArgs {
|
|||
}
|
||||
}
|
||||
|
||||
impl<CtxT> GraphQLType<CtxT> for QueryRoot {
|
||||
impl GraphQLType for QueryRoot {
|
||||
type Context = ();
|
||||
|
||||
fn name() -> Option<&'static str> {
|
||||
Some("QueryRoot")
|
||||
}
|
||||
|
||||
fn meta(registry: &mut Registry<CtxT>) -> MetaType {
|
||||
fn meta(registry: &mut Registry) -> MetaType {
|
||||
registry.build_object_type::<Self>()(&[
|
||||
registry.field::<Option<Human>>("human")
|
||||
.argument(registry.arg::<Option<ID>>("id")),
|
||||
|
@ -396,11 +428,11 @@ impl<CtxT> GraphQLType<CtxT> for QueryRoot {
|
|||
|
||||
pub fn validate<'a, R, V, F>(r: R, q: &str, factory: F)
|
||||
-> Vec<RuleError>
|
||||
where R: GraphQLType<()>,
|
||||
where R: GraphQLType,
|
||||
V: Visitor<'a> + 'a,
|
||||
F: Fn() -> V
|
||||
{
|
||||
let mut root = RootNode::<(), R, ()>::new(r, ());
|
||||
let mut root = RootNode::new(r, EmptyMutation::<()>::new());
|
||||
|
||||
root.schema.add_directive(DirectiveType::new("onQuery", &[DirectiveLocation::Query], &[]));
|
||||
root.schema.add_directive(DirectiveType::new("onMutation", &[DirectiveLocation::Mutation], &[]));
|
||||
|
@ -429,7 +461,7 @@ pub fn expect_passes_rule<'a, V, F>(factory: F, q: &str)
|
|||
}
|
||||
|
||||
pub fn expect_passes_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &str)
|
||||
where R: GraphQLType<()>,
|
||||
where R: GraphQLType,
|
||||
V: Visitor<'a> + 'a,
|
||||
F: Fn() -> V
|
||||
{
|
||||
|
@ -449,7 +481,7 @@ pub fn expect_fails_rule<'a, V, F>(factory: F, q: &str, expected_errors: &[RuleE
|
|||
}
|
||||
|
||||
pub fn expect_fails_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &str, expected_errors: &[RuleError])
|
||||
where R: GraphQLType<()>,
|
||||
where R: GraphQLType,
|
||||
V: Visitor<'a> + 'a,
|
||||
F: Fn() -> V
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue