Refactor GraphQLType::resolve to return Result<>
This unifies the output type of all resolvers. Required for future step of making the output a associated type.
This commit is contained in:
parent
6fcdd32c84
commit
ad16093b88
8 changed files with 40 additions and 36 deletions
|
@ -361,7 +361,7 @@ where
|
|||
where
|
||||
T: GraphQLType<S, Context = CtxT>,
|
||||
{
|
||||
Ok(value.resolve(info, self.current_selection_set, self))
|
||||
value.resolve(info, self.current_selection_set, self)
|
||||
}
|
||||
|
||||
/// Resolve a single arbitrary value into an `ExecutionResult`
|
||||
|
|
|
@ -107,8 +107,8 @@ macro_rules! graphql_scalar {
|
|||
_: &$crate::Executor<
|
||||
Self::Context,
|
||||
$crate::__juniper_insert_generic!($($scalar)+)
|
||||
>) -> $crate::Value<$crate::__juniper_insert_generic!($($scalar)+)> {
|
||||
$resolve_body
|
||||
>) -> $crate::ExecutionResult<$crate::__juniper_insert_generic!($($scalar)+)> {
|
||||
Ok($resolve_body)
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -59,16 +59,17 @@ where
|
|||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
use crate::{types::base::resolve_selection_set_into, value::Object};
|
||||
if let Some(selection_set) = selection_set {
|
||||
let mut result = Object::with_capacity(selection_set.len());
|
||||
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||
Value::Object(result)
|
||||
Ok(Value::Object(result))
|
||||
} else {
|
||||
Value::null()
|
||||
Ok(Value::null())
|
||||
}
|
||||
} else {
|
||||
// TODO: this panic seems useless, investigate why it is here.
|
||||
panic!("resolve() must be implemented by non-object output types");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ struct Database { users: HashMap<String, User> }
|
|||
|
||||
impl Context for Database {}
|
||||
|
||||
impl GraphQLType for User
|
||||
impl GraphQLType<DefaultScalarValue> for User
|
||||
{
|
||||
type Context = Database;
|
||||
type TypeInfo = ();
|
||||
|
@ -298,7 +298,7 @@ where
|
|||
executor: &Executor<Self::Context, S>,
|
||||
) -> ExecutionResult<S> {
|
||||
if Self::name(info).unwrap() == type_name {
|
||||
Ok(self.resolve(info, selection_set, executor))
|
||||
self.resolve(info, selection_set, executor)
|
||||
} else {
|
||||
panic!("resolve_into_type must be implemented by unions and interfaces");
|
||||
}
|
||||
|
@ -318,23 +318,26 @@ where
|
|||
/// 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.
|
||||
/// including those through fragment expansion.
|
||||
///
|
||||
/// Since the GraphQL spec specificies that errors during field processing
|
||||
/// should result in a null-value, this might return Ok(Null) in case of
|
||||
/// failure. Errors are recorded internally.
|
||||
fn resolve(
|
||||
&self,
|
||||
info: &Self::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<Self::Context, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
if let Some(selection_set) = selection_set {
|
||||
let mut result = Object::with_capacity(selection_set.len());
|
||||
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||
let out = if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||
Value::Object(result)
|
||||
} else {
|
||||
Value::null()
|
||||
}
|
||||
};
|
||||
Ok(out)
|
||||
} else {
|
||||
panic!("resolve() must be implemented by non-object output types");
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
|||
ast::{FromInputValue, InputValue, Selection, ToInputValue},
|
||||
schema::meta::MetaType,
|
||||
value::{ScalarValue, Value},
|
||||
executor::ExecutionResult,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -33,10 +34,10 @@ where
|
|||
info: &T::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
match *self {
|
||||
Some(ref obj) => executor.resolve_into_value(info, obj),
|
||||
None => Value::null(),
|
||||
Some(ref obj) => executor.resolve(info, obj),
|
||||
None => Ok(Value::null()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +95,7 @@ where
|
|||
info: &T::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
resolve_into_list(executor, info, self.iter())
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +162,7 @@ where
|
|||
info: &T::TypeInfo,
|
||||
_: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
resolve_into_list(executor, info, self.iter())
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +181,7 @@ fn resolve_into_list<S, T, I>(
|
|||
executor: &Executor<T::Context, S>,
|
||||
info: &T::TypeInfo,
|
||||
iter: I,
|
||||
) -> Value<S>
|
||||
) -> ExecutionResult<S>
|
||||
where
|
||||
S: ScalarValue,
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
|
@ -191,19 +192,17 @@ where
|
|||
.list_contents()
|
||||
.expect("Current type is not a list type")
|
||||
.is_non_null();
|
||||
|
||||
let mut result = Vec::with_capacity(iter.len());
|
||||
|
||||
for o in iter {
|
||||
let value = executor.resolve_into_value(info, &o);
|
||||
if stop_on_null && value.is_null() {
|
||||
return value;
|
||||
match executor.resolve(info, &o) {
|
||||
Ok(value) if stop_on_null && value.is_null() => { return Ok(value) },
|
||||
Ok(value) => { result.push(value) },
|
||||
Err(e) => { return Err(e) },
|
||||
}
|
||||
|
||||
result.push(value);
|
||||
}
|
||||
|
||||
Value::list(result)
|
||||
Ok(Value::list(result))
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
|
|
|
@ -52,7 +52,7 @@ where
|
|||
info: &T::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ where
|
|||
info: &T::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<CtxT, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ where
|
|||
info: &T::TypeInfo,
|
||||
selection_set: Option<&[Selection<S>]>,
|
||||
executor: &Executor<T::Context, S>,
|
||||
) -> Value<S> {
|
||||
) -> ExecutionResult<S> {
|
||||
(**self).resolve(info, selection_set, executor)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};
|
|||
|
||||
use crate::{
|
||||
ast::{InputValue, Selection, ToInputValue},
|
||||
executor::{Executor, Registry},
|
||||
executor::{Executor, Registry, ExecutionResult},
|
||||
parser::{LexerError, ParseError, ScalarToken, Token},
|
||||
schema::meta::MetaType,
|
||||
types::base::GraphQLType,
|
||||
|
@ -189,8 +189,8 @@ where
|
|||
_: &(),
|
||||
_: Option<&[Selection<S>]>,
|
||||
_: &Executor<Self::Context, S>,
|
||||
) -> Value<S> {
|
||||
Value::scalar(String::from(*self))
|
||||
) -> ExecutionResult<S> {
|
||||
Ok(Value::scalar(String::from(*self)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -257,10 +257,11 @@ pub fn impl_enum(ast: &syn::DeriveInput, is_internal: bool) -> TokenStream {
|
|||
_: &(),
|
||||
_: Option<&[#juniper_path::Selection<__S>]>,
|
||||
_: &#juniper_path::Executor<Self::Context, __S>
|
||||
) -> #juniper_path::Value<__S> {
|
||||
match self {
|
||||
) -> #juniper_path::ExecutionResult<__S> {
|
||||
let v = match self {
|
||||
#resolves
|
||||
}
|
||||
};
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue