Update AND, OR, and MapErr logic. Update logic for object input

This commit is contained in:
Rodgers 2021-07-08 23:43:12 +07:00
parent abb59b9e3f
commit 0417f4181a
4 changed files with 78 additions and 59 deletions

View File

@ -68,7 +68,7 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
} }
} }
if let Some(reason) = value.and_then(|value| { if let Some(e) = value.and_then(|value| {
is_valid_input_value( is_valid_input_value(
ctx.registry, ctx.registry,
&arg.ty, &arg.ty,
@ -79,9 +79,10 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
}, },
) )
}) { }) {
ctx.report_error( ctx.report_error_with_extensions(
vec![name.pos], vec![name.pos],
format!("Invalid value for argument {}", reason), format!("Invalid value for argument {}", e.message),
e.extensions,
); );
} }
} }

View File

@ -18,7 +18,7 @@ impl<'a> Visitor<'a> for DefaultValuesOfCorrectType {
"Argument \"{}\" has type \"{}\" and is not nullable, so it can't have a default value", "Argument \"{}\" has type \"{}\" and is not nullable, so it can't have a default value",
variable_definition.node.name, variable_definition.node.var_type, variable_definition.node.name, variable_definition.node.var_type,
)); ));
} else if let Some(reason) = is_valid_input_value( } else if let Some(e) = is_valid_input_value(
ctx.registry, ctx.registry,
&variable_definition.node.var_type.to_string(), &variable_definition.node.var_type.to_string(),
&value.node, &value.node,
@ -27,9 +27,10 @@ impl<'a> Visitor<'a> for DefaultValuesOfCorrectType {
segment: QueryPathSegment::Name(&variable_definition.node.name.node), segment: QueryPathSegment::Name(&variable_definition.node.name.node),
}, },
) { ) {
ctx.report_error( ctx.report_error_with_extensions(
vec![variable_definition.pos], vec![variable_definition.pos],
format!("Invalid default value for argument {}", reason), format!("Invalid default value for argument {}", e.message),
e.extensions,
) )
} }
} }

View File

@ -1,9 +1,11 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::context::QueryPathNode;
use crate::{registry, QueryPathSegment};
use async_graphql_value::{ConstValue, Value}; use async_graphql_value::{ConstValue, Value};
use crate::context::QueryPathNode;
use crate::error::Error;
use crate::{registry, QueryPathSegment};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Scope<'a> { pub enum Scope<'a> {
Operation(Option<&'a str>), Operation(Option<&'a str>),
@ -40,13 +42,12 @@ pub fn is_valid_input_value(
type_name: &str, type_name: &str,
value: &ConstValue, value: &ConstValue,
path_node: QueryPathNode, path_node: QueryPathNode,
) -> Option<String> { ) -> Option<Error> {
match registry::MetaTypeName::create(type_name) { match registry::MetaTypeName::create(type_name) {
registry::MetaTypeName::NonNull(type_name) => match value { registry::MetaTypeName::NonNull(type_name) => match value {
ConstValue::Null => Some(valid_error( ConstValue::Null => {
&path_node, Some(valid_error(&path_node, format!("expected type \"{}\"", type_name)).into())
format!("expected type \"{}\"", type_name), }
)),
_ => is_valid_input_value(registry, type_name, value, path_node), _ => is_valid_input_value(registry, type_name, value, path_node),
}, },
registry::MetaTypeName::List(type_name) => match value { registry::MetaTypeName::List(type_name) => match value {
@ -74,10 +75,10 @@ pub fn is_valid_input_value(
if is_valid(&value) { if is_valid(&value) {
None None
} else { } else {
Some(valid_error( Some(
&path_node, valid_error(&path_node, format!("expected type \"{}\"", type_name))
format!("expected type \"{}\"", type_name), .into(),
)) )
} }
} }
registry::MetaType::Enum { registry::MetaType::Enum {
@ -87,34 +88,39 @@ pub fn is_valid_input_value(
} => match value { } => match value {
ConstValue::Enum(name) => { ConstValue::Enum(name) => {
if !enum_values.contains_key(name.as_str()) { if !enum_values.contains_key(name.as_str()) {
Some(valid_error( Some(
valid_error(
&path_node, &path_node,
format!( format!(
"enumeration type \"{}\" does not contain the value \"{}\"", "enumeration type \"{}\" does not contain the value \"{}\"",
enum_name, name enum_name, name
), ),
)) )
.into(),
)
} else { } else {
None None
} }
} }
ConstValue::String(name) => { ConstValue::String(name) => {
if !enum_values.contains_key(name.as_str()) { if !enum_values.contains_key(name.as_str()) {
Some(valid_error( Some(
valid_error(
&path_node, &path_node,
format!( format!(
"enumeration type \"{}\" does not contain the value \"{}\"", "enumeration type \"{}\" does not contain the value \"{}\"",
enum_name, name enum_name, name
), ),
)) )
.into(),
)
} else { } else {
None None
} }
} }
_ => Some(valid_error( _ => Some(
&path_node, valid_error(&path_node, format!("expected type \"{}\"", type_name)).into(),
format!("expected type \"{}\"", type_name), ),
)),
}, },
registry::MetaType::InputObject { registry::MetaType::InputObject {
input_fields, input_fields,
@ -129,14 +135,15 @@ pub fn is_valid_input_value(
input_names.remove(field.name); input_names.remove(field.name);
if let Some(value) = values.get(field.name) { if let Some(value) = values.get(field.name) {
if let Some(validator) = &field.validator { if let Some(validator) = &field.validator {
if let Err(reason) = validator.is_valid(value) { if let Err(mut e) = validator.is_valid_with_extensions(value) {
return Some(valid_error( e.message = valid_error(
&QueryPathNode { &QueryPathNode {
parent: Some(&path_node), parent: Some(&path_node),
segment: QueryPathSegment::Name(field.name), segment: QueryPathSegment::Name(field.name),
}, },
reason, e.message,
)); );
return Some(e);
} }
} }
@ -154,21 +161,30 @@ pub fn is_valid_input_value(
} else if registry::MetaTypeName::create(&field.ty).is_non_null() } else if registry::MetaTypeName::create(&field.ty).is_non_null()
&& field.default_value.is_none() && field.default_value.is_none()
{ {
return Some(valid_error( return Some(
valid_error(
&path_node, &path_node,
format!( format!(
"field \"{}\" of type \"{}\" is required but not provided", "field \"{}\" of type \"{}\" is required but not provided",
field.name, object_name, field.name, object_name,
), ),
)); )
.into(),
);
} }
} }
if let Some(name) = input_names.iter().next() { if let Some(name) = input_names.iter().next() {
return Some(valid_error( return Some(
valid_error(
&path_node, &path_node,
format!("unknown field \"{}\" of type \"{}\"", name, object_name), format!(
)); "unknown field \"{}\" of type \"{}\"",
name, object_name
),
)
.into(),
);
} }
None None

View File

@ -80,8 +80,7 @@ where
/// ``` /// ```
fn is_valid_with_extensions(&self, value: &Value) -> Result<(), Error> { fn is_valid_with_extensions(&self, value: &Value) -> Result<(), Error> {
// By default, use is_valid method to keep compatible with previous version // By default, use is_valid method to keep compatible with previous version
self.is_valid(value)?; self.is_valid(value).map_err(|reason| Error::new(reason))
Ok(())
} }
} }
@ -98,7 +97,7 @@ pub trait InputValueValidatorExt: InputValueValidator + Sized {
} }
/// Changes the error message /// Changes the error message
fn map_err<F: Fn(String) -> String>(self, f: F) -> MapErr<Self, F> { fn map_err<F: Fn(Error) -> Error>(self, f: F) -> MapErr<Self, F> {
MapErr(self, f) MapErr(self, f)
} }
} }
@ -113,9 +112,10 @@ where
A: InputValueValidator, A: InputValueValidator,
B: InputValueValidator, B: InputValueValidator,
{ {
fn is_valid(&self, value: &Value) -> Result<(), String> { fn is_valid_with_extensions(&self, value: &Value) -> Result<(), Error> {
self.0.is_valid(value)?; // By default, use is_valid method to keep compatible with previous version
self.1.is_valid(value) self.0.is_valid_with_extensions(value)?;
self.1.is_valid_with_extensions(value)
} }
} }
@ -127,9 +127,10 @@ where
A: InputValueValidator, A: InputValueValidator,
B: InputValueValidator, B: InputValueValidator,
{ {
fn is_valid(&self, value: &Value) -> Result<(), String> { fn is_valid_with_extensions(&self, value: &Value) -> Result<(), Error> {
if self.0.is_valid(value).is_err() { // By default, use is_valid method to keep compatible with previous version
self.1.is_valid(value) if self.0.is_valid_with_extensions(value).is_err() {
self.1.is_valid_with_extensions(value)
} else { } else {
Ok(()) Ok(())
} }
@ -142,9 +143,9 @@ pub struct MapErr<I, F>(I, F);
impl<I, F> InputValueValidator for MapErr<I, F> impl<I, F> InputValueValidator for MapErr<I, F>
where where
I: InputValueValidator, I: InputValueValidator,
F: Fn(String) -> String + Send + Sync, F: Fn(Error) -> Error + Send + Sync,
{ {
fn is_valid(&self, value: &Value) -> Result<(), String> { fn is_valid_with_extensions(&self, value: &Value) -> Result<(), Error> {
self.0.is_valid(value).map_err(&self.1) self.0.is_valid_with_extensions(value).map_err(&self.1)
} }
} }