Trait juniper::GraphQLType
[−]
[src]
pub trait GraphQLType: Sized { type Context; fn name() -> Option<&'static str>; fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r>; fn resolve_field(
&self,
field_name: &str,
arguments: &Arguments,
executor: &Executor<Self::Context>
) -> ExecutionResult { ... } fn resolve_into_type(
&self,
type_name: &str,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> ExecutionResult { ... } fn concrete_type_name(&self, context: &Self::Context) -> String { ... } fn resolve(
&self,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> Value { ... } }
Primary trait used to expose Rust types in a GraphQL schema
All of the convenience macros ultimately expand into an implementation of this trait for the given type. The macros remove duplicated definitions of fields and arguments, and add type checks on all resolve functions automatically. This can all be done manually.
GraphQLType
provides some convenience methods for you, in the form of
optional trait methods. The name
and meta
methods are mandatory, but
other than that, it depends on what type you're exposing:
- Scalars, enums, lists and non null wrappers only require
resolve
, - Interfaces and objects require
resolve_field
orresolve
if you want to implement custom resolution logic (probably not), - Interfaces and unions require
resolve_into_type
andconcrete_type_name
. - Input objects do not require anything
Example
Manually deriving an object is straightforward but tedious. This is the
equivalent of the User
object as shown in the example in the documentation
root:
use juniper::{GraphQLType, Registry, FieldResult, Context, Arguments, Executor, ExecutionResult}; use juniper::meta::MetaType; struct User { id: String, name: String, friend_ids: Vec<String> } struct Database { users: HashMap<String, User> } impl Context for Database {} impl GraphQLType for User { type Context = Database; fn name() -> Option<&'static str> { Some("User") } fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { // First, we need to define all fields and their types on this type. // // If we need arguments, want to implement interfaces, or want to add // documentation strings, we can do it here. let fields = &[ registry.field::<&String>("id"), registry.field::<&String>("name"), registry.field::<Vec<&User>>("friends"), ]; registry.build_object_type::<User>(fields).into_meta() } fn resolve_field( &self, field_name: &str, args: &Arguments, executor: &Executor<Database> ) -> ExecutionResult { // 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*` // actually matches the one that you defined in `meta()` above. let database = executor.context(); match field_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 // resolve based on the query. The executor instance keeps track // of its current position in the query. "friends" => executor.resolve( &self.friend_ids.iter() .filter_map(|id| database.users.get(id)) .collect::<Vec<_>>() ), // We can only reach this panic in two cases; either a mismatch // between the defined schema in `meta()` above, or a validation // in this library failed because of a bug. // // In either of those two cases, the only reasonable way out is // to panic the thread. _ => panic!("Field {} not found on type User", field_name), } } }
Associated Types
type Context
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.
Required Methods
fn name() -> Option<&'static str>
The name of the GraphQL type to expose.
This function will be called multiple times during schema construction. It must not perform any calculation and always return the same value.
fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r>
The meta type representing this GraphQL type.
Provided Methods
fn resolve_field(
&self,
field_name: &str,
arguments: &Arguments,
executor: &Executor<Self::Context>
) -> ExecutionResult
&self,
field_name: &str,
arguments: &Arguments,
executor: &Executor<Self::Context>
) -> ExecutionResult
Resolve the value of a single field on this type.
The arguments object contain all specified arguments, with default values substituted for the ones not provided by the query.
The executor can be used to drive selections into sub-objects.
The default implementation panics.
fn resolve_into_type(
&self,
type_name: &str,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> ExecutionResult
&self,
type_name: &str,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> ExecutionResult
Resolve this interface or union into a concrete type
Try to resolve the current type into the type name provided. If the
type matches, pass the instance along to executor.resolve
.
The default implementation panics.
fn concrete_type_name(&self, context: &Self::Context) -> String
Return the concrete type name for this instance/union.
The default implementation panics.
fn resolve(
&self,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> Value
&self,
selection_set: Option<&[Selection]>,
executor: &Executor<Self::Context>
) -> Value
Resolve the provided selection set against the current object.
For non-object types, the selection set will be None
and the value
of the object should simply be returned.
For objects, all fields in the selection set should be resolved.
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.
Implementors
impl GraphQLType for ID
impl GraphQLType for String
impl<'a> GraphQLType for &'a str
impl GraphQLType for bool
impl GraphQLType for i32
impl GraphQLType for f64
impl GraphQLType for ()
impl<T> GraphQLType for EmptyMutation<T>
impl<T, CtxT> GraphQLType for Box<T> where
T: GraphQLType<Context = CtxT>,impl<'a, T, CtxT> GraphQLType for &'a T where
T: GraphQLType<Context = CtxT>,impl<T, CtxT> GraphQLType for Option<T> where
T: GraphQLType<Context = CtxT>,impl<T, CtxT> GraphQLType for Vec<T> where
T: GraphQLType<Context = CtxT>,impl<'a, T, CtxT> GraphQLType for &'a [T] where
T: GraphQLType<Context = CtxT>,impl<'a, CtxT, QueryT, MutationT> GraphQLType for RootNode<'a, QueryT, MutationT> where
QueryT: GraphQLType<Context = CtxT>,
MutationT: GraphQLType<Context = CtxT>,impl<'a> GraphQLType for Field<'a>
impl<'a> GraphQLType for Argument<'a>
impl GraphQLType for EnumValue
impl GraphQLType for TypeKind