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
juniper/src
juniper_codegen/src
|
@ -361,7 +361,7 @@ where
|
||||||
where
|
where
|
||||||
T: GraphQLType<S, Context = CtxT>,
|
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`
|
/// Resolve a single arbitrary value into an `ExecutionResult`
|
||||||
|
|
|
@ -107,8 +107,8 @@ macro_rules! graphql_scalar {
|
||||||
_: &$crate::Executor<
|
_: &$crate::Executor<
|
||||||
Self::Context,
|
Self::Context,
|
||||||
$crate::__juniper_insert_generic!($($scalar)+)
|
$crate::__juniper_insert_generic!($($scalar)+)
|
||||||
>) -> $crate::Value<$crate::__juniper_insert_generic!($($scalar)+)> {
|
>) -> $crate::ExecutionResult<$crate::__juniper_insert_generic!($($scalar)+)> {
|
||||||
$resolve_body
|
Ok($resolve_body)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -59,16 +59,17 @@ where
|
||||||
info: &Self::TypeInfo,
|
info: &Self::TypeInfo,
|
||||||
selection_set: Option<&[Selection<S>]>,
|
selection_set: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<Self::Context, S>,
|
executor: &Executor<Self::Context, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
use crate::{types::base::resolve_selection_set_into, value::Object};
|
use crate::{types::base::resolve_selection_set_into, value::Object};
|
||||||
if let Some(selection_set) = selection_set {
|
if let Some(selection_set) = selection_set {
|
||||||
let mut result = Object::with_capacity(selection_set.len());
|
let mut result = Object::with_capacity(selection_set.len());
|
||||||
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
|
||||||
Value::Object(result)
|
Ok(Value::Object(result))
|
||||||
} else {
|
} else {
|
||||||
Value::null()
|
Ok(Value::null())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: this panic seems useless, investigate why it is here.
|
||||||
panic!("resolve() must be implemented by non-object output types");
|
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 Context for Database {}
|
||||||
|
|
||||||
impl GraphQLType for User
|
impl GraphQLType<DefaultScalarValue> for User
|
||||||
{
|
{
|
||||||
type Context = Database;
|
type Context = Database;
|
||||||
type TypeInfo = ();
|
type TypeInfo = ();
|
||||||
|
@ -298,7 +298,7 @@ where
|
||||||
executor: &Executor<Self::Context, S>,
|
executor: &Executor<Self::Context, S>,
|
||||||
) -> ExecutionResult<S> {
|
) -> ExecutionResult<S> {
|
||||||
if Self::name(info).unwrap() == type_name {
|
if Self::name(info).unwrap() == type_name {
|
||||||
Ok(self.resolve(info, selection_set, executor))
|
self.resolve(info, selection_set, executor)
|
||||||
} else {
|
} else {
|
||||||
panic!("resolve_into_type must be implemented by unions and interfaces");
|
panic!("resolve_into_type must be implemented by unions and interfaces");
|
||||||
}
|
}
|
||||||
|
@ -318,23 +318,26 @@ where
|
||||||
/// of the object should simply be returned.
|
/// of the object should simply be returned.
|
||||||
///
|
///
|
||||||
/// For objects, all fields in the selection set should be resolved.
|
/// For objects, all fields in the selection set should be resolved.
|
||||||
///
|
|
||||||
/// The default implementation uses `resolve_field` to resolve all fields,
|
/// The default implementation uses `resolve_field` to resolve all fields,
|
||||||
/// including those through fragment expansion, for object types. For
|
/// including those through fragment expansion.
|
||||||
/// non-object types, this method panics.
|
///
|
||||||
|
/// 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(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
info: &Self::TypeInfo,
|
info: &Self::TypeInfo,
|
||||||
selection_set: Option<&[Selection<S>]>,
|
selection_set: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<Self::Context, S>,
|
executor: &Executor<Self::Context, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
if let Some(selection_set) = selection_set {
|
if let Some(selection_set) = selection_set {
|
||||||
let mut result = Object::with_capacity(selection_set.len());
|
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)
|
Value::Object(result)
|
||||||
} else {
|
} else {
|
||||||
Value::null()
|
Value::null()
|
||||||
}
|
};
|
||||||
|
Ok(out)
|
||||||
} else {
|
} else {
|
||||||
panic!("resolve() must be implemented by non-object output types");
|
panic!("resolve() must be implemented by non-object output types");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
ast::{FromInputValue, InputValue, Selection, ToInputValue},
|
ast::{FromInputValue, InputValue, Selection, ToInputValue},
|
||||||
schema::meta::MetaType,
|
schema::meta::MetaType,
|
||||||
value::{ScalarValue, Value},
|
value::{ScalarValue, Value},
|
||||||
|
executor::ExecutionResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -33,10 +34,10 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
_: Option<&[Selection<S>]>,
|
_: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<CtxT, S>,
|
executor: &Executor<CtxT, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
match *self {
|
match *self {
|
||||||
Some(ref obj) => executor.resolve_into_value(info, obj),
|
Some(ref obj) => executor.resolve(info, obj),
|
||||||
None => Value::null(),
|
None => Ok(Value::null()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,7 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
_: Option<&[Selection<S>]>,
|
_: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<CtxT, S>,
|
executor: &Executor<CtxT, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
resolve_into_list(executor, info, self.iter())
|
resolve_into_list(executor, info, self.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +162,7 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
_: Option<&[Selection<S>]>,
|
_: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<CtxT, S>,
|
executor: &Executor<CtxT, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
resolve_into_list(executor, info, self.iter())
|
resolve_into_list(executor, info, self.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +181,7 @@ fn resolve_into_list<S, T, I>(
|
||||||
executor: &Executor<T::Context, S>,
|
executor: &Executor<T::Context, S>,
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
iter: I,
|
iter: I,
|
||||||
) -> Value<S>
|
) -> ExecutionResult<S>
|
||||||
where
|
where
|
||||||
S: ScalarValue,
|
S: ScalarValue,
|
||||||
I: Iterator<Item = T> + ExactSizeIterator,
|
I: Iterator<Item = T> + ExactSizeIterator,
|
||||||
|
@ -191,19 +192,17 @@ where
|
||||||
.list_contents()
|
.list_contents()
|
||||||
.expect("Current type is not a list type")
|
.expect("Current type is not a list type")
|
||||||
.is_non_null();
|
.is_non_null();
|
||||||
|
|
||||||
let mut result = Vec::with_capacity(iter.len());
|
let mut result = Vec::with_capacity(iter.len());
|
||||||
|
|
||||||
for o in iter {
|
for o in iter {
|
||||||
let value = executor.resolve_into_value(info, &o);
|
match executor.resolve(info, &o) {
|
||||||
if stop_on_null && value.is_null() {
|
Ok(value) if stop_on_null && value.is_null() => { return Ok(value) },
|
||||||
return value;
|
Ok(value) => { result.push(value) },
|
||||||
|
Err(e) => { return Err(e) },
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::list(result)
|
Ok(Value::list(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
|
|
|
@ -52,7 +52,7 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
selection_set: Option<&[Selection<S>]>,
|
selection_set: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<CtxT, S>,
|
executor: &Executor<CtxT, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
(**self).resolve(info, selection_set, executor)
|
(**self).resolve(info, selection_set, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
selection_set: Option<&[Selection<S>]>,
|
selection_set: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<CtxT, S>,
|
executor: &Executor<CtxT, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
(**self).resolve(info, selection_set, executor)
|
(**self).resolve(info, selection_set, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ where
|
||||||
info: &T::TypeInfo,
|
info: &T::TypeInfo,
|
||||||
selection_set: Option<&[Selection<S>]>,
|
selection_set: Option<&[Selection<S>]>,
|
||||||
executor: &Executor<T::Context, S>,
|
executor: &Executor<T::Context, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
(**self).resolve(info, selection_set, executor)
|
(**self).resolve(info, selection_set, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{InputValue, Selection, ToInputValue},
|
ast::{InputValue, Selection, ToInputValue},
|
||||||
executor::{Executor, Registry},
|
executor::{Executor, Registry, ExecutionResult},
|
||||||
parser::{LexerError, ParseError, ScalarToken, Token},
|
parser::{LexerError, ParseError, ScalarToken, Token},
|
||||||
schema::meta::MetaType,
|
schema::meta::MetaType,
|
||||||
types::base::GraphQLType,
|
types::base::GraphQLType,
|
||||||
|
@ -189,8 +189,8 @@ where
|
||||||
_: &(),
|
_: &(),
|
||||||
_: Option<&[Selection<S>]>,
|
_: Option<&[Selection<S>]>,
|
||||||
_: &Executor<Self::Context, S>,
|
_: &Executor<Self::Context, S>,
|
||||||
) -> Value<S> {
|
) -> ExecutionResult<S> {
|
||||||
Value::scalar(String::from(*self))
|
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>]>,
|
_: Option<&[#juniper_path::Selection<__S>]>,
|
||||||
_: &#juniper_path::Executor<Self::Context, __S>
|
_: &#juniper_path::Executor<Self::Context, __S>
|
||||||
) -> #juniper_path::Value<__S> {
|
) -> #juniper_path::ExecutionResult<__S> {
|
||||||
match self {
|
let v = match self {
|
||||||
#resolves
|
#resolves
|
||||||
}
|
};
|
||||||
|
Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue