Allow post-validation FromInputValue errors#987
Conversation
|
cc @ilslv Before continuing this, make sure |
# Conflicts: # juniper/src/ast.rs # juniper_actix/src/lib.rs
|
@tyranron PR is ready for review |
juniper/src/types/containers.rs
Outdated
| NotEnough(usize), | ||
|
|
||
| /// Too many elements. Contains __all__ [`InputValue`] elements. | ||
| TooMuch(Vec<T>), |
There was a problem hiding this comment.
I do think keeping Vec gives no actual use here, while complicates relative unsafe code (and so reasoning) a lot.
| <Vec<i32>>::from_input_value(&V::list(vec![V::scalar(1), V::scalar(2), V::scalar(3)])), | ||
| Ok(vec![1, 2, 3]), | ||
| ); | ||
| // TODO: all examples |
There was a problem hiding this comment.
@ilslv we should provide here a complete test suite. But let's do it in a separate PR after merging this.
juniper/src/schema/meta.rs
Outdated
| T: FromInputValue<S>, | ||
| { | ||
| <T as FromInputValue<S>>::from_input_value(v).is_some() | ||
| T::from_input_value(v).is_ok() |
There was a problem hiding this comment.
We don't actually propagate any errors here, only silence them as we did before. Let's do propagation.
juniper/src/types/scalars.rs
Outdated
| .map(ID), | ||
| _ => None, | ||
| } | ||
| fn from_input_value(v: &InputValue) -> Result<ID, FieldError> { |
There was a problem hiding this comment.
We should be more accurate here and use FieldError<S> to omit redundant scalar conversions.
| } | ||
| } | ||
| None => return Box::pin(::juniper::futures::future::ready( | ||
| Err(::juniper::FieldError::from("This GraphQLType has no name")) |
There was a problem hiding this comment.
@ilslv to DRYing the generated code a bit, let's move such things to helper functions inside juniper crate, and reuse them here.
…nput-value-resolve-errors # Conflicts: # juniper/CHANGELOG.md
# Conflicts: # integration_tests/juniper_tests/src/issue_372.rs # juniper/CHANGELOG.md # juniper/src/validation/rules/fields_on_correct_type.rs # juniper_actix/src/lib.rs
|
@tyranron this PR is ready for review |
| }, | ||
| Ok, | ||
| ) | ||
| })? |
There was a problem hiding this comment.
@ilslv I don't follow the logic here.
It was:
args.get::<#ty>(#name)returnsOption<T>.- If it's
None, then::juniper::FromInputValue::<#scalar>::from_implicit_nullreturnsOption<T>. - If it's
Nonewe panic.
Now it is:
args.get::<#ty>(#name)returnsResult<Option<T>, FieldError>.- If it's
Ok, we check the inneropt. - If it
Somewe map it toSome(Ok(v))and so haveResult<Option<Result<T>, FieldError>, FieldError>.
Why?
It seems the more natural way is:
- Unpack the
Resultearly:args.get::<#ty>(#name)? .transpose()the inner error inOptionand return it with?.
There was a problem hiding this comment.
Oh... understood. .map_or_else doesn't map an inner Option value, but rather maps the whole Option into something.
.ok_or_else will do better here.
There was a problem hiding this comment.
Meh... .ok_or_else() cannot map absense to Result::Ok.
| let e = ::juniper::IntoFieldError::into_field_error(e); | ||
| ::juniper::FieldError::new( | ||
| format!(#err_text, e.message()), | ||
| e.extensions().clone(), |
There was a problem hiding this comment.
This mess is better be replaced with .map_message method on FieldError.
| }, | ||
| Ok, | ||
| ) | ||
| })? |
There was a problem hiding this comment.
Meh... .ok_or_else() cannot map absense to Result::Ok.
Required for #975
Synopsis
At the moment,
FromInputValuefallibility is considered during input operation validation only. Also, the real error is erased, due toOption<T>usage, thus argument absence is unobviously mixed with convertion errors over the code base.Being applicable to most cases, still there are some situations where the error may occur only during resolution after passing the validation (from #975 it's deserializing
json::ValueintoJson<T: Deserialize>). At the moment, we're ending up with runtime panics in such situation, which is not good.Solution
Make
FromInputValuereturningResultwith the actual error preservation. Require this error beIntoFieldErrorconvertible, so it may naturally bubble-up during operation execution.Checklist