Trait juniper::GraphQLType
[−]
[src]
pub trait GraphQLType<CtxT>: Sized { fn name() -> Option<&'static str>; fn meta(registry: &mut Registry<CtxT>) -> MetaType; fn resolve_field(&self,
field_name: &str,
arguments: &Arguments,
executor: &mut Executor<CtxT>)
-> ExecutionResult { ... } fn resolve_into_type(&self,
type_name: &str,
selection_set: Option<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> ExecutionResult { ... } fn concrete_type_name(&self, context: &CtxT) -> String { ... } fn resolve(&self,
selection_set: Option<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> 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, Arguments, Executor, ExecutionResult}; 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 { fn name() -> Option<&'static str> { Some("User") } fn meta(registry: &mut Registry<Database>) -> 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 // documentation strings, we can do it here. registry.build_object_type::<User>()(&[ registry.field::<&String>("id"), registry.field::<&String>("name"), registry.field::<Vec<&User>>("friends"), ]) .into_meta() } fn resolve_field( &self, field_name: &str, args: &Arguments, executor: &mut 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 { "id" => executor.resolve(&self.id), "name" => executor.resolve(&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), } } }
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(registry: &mut Registry<CtxT>) -> MetaType
The meta type representing this GraphQL type.
Provided Methods
fn resolve_field(&self,
field_name: &str,
arguments: &Arguments,
executor: &mut Executor<CtxT>)
-> ExecutionResult
field_name: &str,
arguments: &Arguments,
executor: &mut Executor<CtxT>)
-> 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<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> ExecutionResult
type_name: &str,
selection_set: Option<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> 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: &CtxT) -> String
Return the concrete type name for this instance/union.
The default implementation panics.
fn resolve(&self,
selection_set: Option<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> Value
selection_set: Option<Vec<Selection>>,
executor: &mut Executor<CtxT>)
-> 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<CtxT> GraphQLType<CtxT> for ID
impl<CtxT> GraphQLType<CtxT> for String
impl<'a, CtxT> GraphQLType<CtxT> for &'a str
impl<CtxT> GraphQLType<CtxT> for bool
impl<CtxT> GraphQLType<CtxT> for i64
impl<CtxT> GraphQLType<CtxT> for f64
impl<CtxT> GraphQLType<CtxT> for ()
impl<T, CtxT> GraphQLType<CtxT> for Box<T> where T: GraphQLType<CtxT>
impl<'a, T, CtxT> GraphQLType<CtxT> for &'a T where T: GraphQLType<CtxT>
impl<T, CtxT> GraphQLType<CtxT> for Option<T> where T: GraphQLType<CtxT>
impl<T, CtxT> GraphQLType<CtxT> for Vec<T> where T: GraphQLType<CtxT>
impl<'a, T, CtxT> GraphQLType<CtxT> for &'a [T] where T: GraphQLType<CtxT>
impl<CtxT, QueryT, MutationT> GraphQLType<CtxT> for RootNode<CtxT, QueryT, MutationT> where QueryT: GraphQLType<CtxT>, MutationT: GraphQLType<CtxT>
impl GraphQLType<SchemaType> for Field
impl GraphQLType<SchemaType> for Argument
impl GraphQLType<SchemaType> for EnumValue
impl<CtxT> GraphQLType<CtxT> for TypeKind