`#[grapql(validator(list))]` no longer applies to `max_items` and `min_items`.
This commit is contained in:
parent
05907cad31
commit
4a265ed29d
|
@ -4,7 +4,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.0.7] 2021-11-23
|
||||
## [3.0.8] 2021-11-30
|
||||
|
||||
- `#[graphql(validator(list))]` no longer applies to `max_items` and `min_items`.
|
||||
- Implement `InputValue`/`OutputValue` for `serde_json::Value`.
|
||||
|
||||
## [3.0.7] 2021-11-23
|
||||
|
||||
- Fix error extensions cause stack overflow. [#719](https://github.com/async-graphql/async-graphql/issues/719)
|
||||
|
||||
|
|
|
@ -71,115 +71,143 @@ impl Validators {
|
|||
ty: TokenStream,
|
||||
map_err: Option<TokenStream>,
|
||||
) -> Result<TokenStream> {
|
||||
let mut list_validators = Vec::new();
|
||||
let mut elem_validators = Vec::new();
|
||||
let mut codes = Vec::new();
|
||||
|
||||
if let Some(n) = &self.multiple_of {
|
||||
codes.push(quote! {
|
||||
#crate_name::validators::multiple_of(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.maximum {
|
||||
codes.push(quote! {
|
||||
#crate_name::validators::maximum(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.minimum {
|
||||
codes.push(quote! {
|
||||
#crate_name::validators::minimum(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.max_length {
|
||||
codes.push(quote! {
|
||||
#crate_name::validators::max_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.min_length {
|
||||
codes.push(quote! {
|
||||
#crate_name::validators::min_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.max_items {
|
||||
codes.push(quote! {
|
||||
list_validators.push(quote! {
|
||||
#crate_name::validators::max_items(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.min_items {
|
||||
codes.push(quote! {
|
||||
list_validators.push(quote! {
|
||||
#crate_name::validators::min_items(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.multiple_of {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::multiple_of(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.maximum {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::maximum(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.minimum {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::minimum(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.max_length {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::max_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.min_length {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::min_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.chars_max_length {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::chars_max_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(n) = &self.chars_min_length {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::chars_min_length(__raw_value, #n)
|
||||
});
|
||||
}
|
||||
|
||||
if self.email {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::email(__raw_value)
|
||||
});
|
||||
}
|
||||
|
||||
if self.url {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::url(__raw_value)
|
||||
});
|
||||
}
|
||||
|
||||
if self.ip {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::ip(__raw_value)
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(re) = &self.regex {
|
||||
codes.push(quote! {
|
||||
elem_validators.push(quote! {
|
||||
#crate_name::validators::regex(__raw_value, #re)
|
||||
});
|
||||
}
|
||||
|
||||
if !list_validators.is_empty() {
|
||||
codes.push(quote! {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(#value) {
|
||||
#(#list_validators #map_err ?;)*
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !elem_validators.is_empty() {
|
||||
if self.list {
|
||||
codes.push(quote! {
|
||||
for __item in #value {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(__item) {
|
||||
#(#elem_validators #map_err ?;)*
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
codes.push(quote! {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(#value) {
|
||||
#(#elem_validators #map_err ?;)*
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for s in &self.custom {
|
||||
let __create_custom_validator: Expr =
|
||||
syn::parse_str(s).map_err(|err| Error::new(s.span(), err.to_string()))?;
|
||||
codes.push(quote! {
|
||||
#crate_name::CustomValidator::check(&(#__create_custom_validator), __raw_value)
|
||||
.map_err(|err_msg| #crate_name::InputValueError::<#ty>::custom(err_msg))
|
||||
});
|
||||
|
||||
if self.list {
|
||||
codes.push(quote! {
|
||||
let __custom_validator = #__create_custom_validator;
|
||||
for __item in #value {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(__item) {
|
||||
#crate_name::CustomValidator::check(&__custom_validator, __raw_value)
|
||||
.map_err(|err_msg| #crate_name::InputValueError::<#ty>::custom(err_msg)) #map_err ?;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
codes.push(quote! {
|
||||
let __custom_validator = #__create_custom_validator;
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(#value) {
|
||||
#crate_name::CustomValidator::check(&__custom_validator, __raw_value)
|
||||
.map_err(|err_msg| #crate_name::InputValueError::<#ty>::custom(err_msg)) #map_err ?;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if codes.is_empty() {
|
||||
return Ok(quote!());
|
||||
}
|
||||
|
||||
let codes = codes.into_iter().map(|s| quote!(#s #map_err ?));
|
||||
|
||||
if self.list {
|
||||
Ok(quote! {
|
||||
for __item in #value {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(__item) {
|
||||
#(#codes;)*
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Ok(quote! {
|
||||
if let ::std::option::Option::Some(__raw_value) = #crate_name::InputType::as_raw_value(#value) {
|
||||
#(#codes;)*
|
||||
}
|
||||
})
|
||||
}
|
||||
Ok(quote!(#(#codes)*))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -605,3 +605,61 @@ pub async fn test_validate_wrapper_types() {
|
|||
}]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_list_both_max_items_and_max_length() {
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn value(
|
||||
&self,
|
||||
#[graphql(validator(list, max_length = 3, max_items = 2))] values: Vec<String>,
|
||||
) -> String {
|
||||
values.into_iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute(r#"{ value(values: ["a", "b", "cdef"])}"#)
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap_err(),
|
||||
vec![ServerError {
|
||||
message: r#"Failed to parse "[String!]": the value length is 3, must be less than or equal to 2"#.to_string(),
|
||||
source: None,
|
||||
locations: vec![Pos { column: 17, line: 1}],
|
||||
path: vec![PathSegment::Field("value".to_string())],
|
||||
extensions: None
|
||||
}]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute(r#"{ value(values: ["a", "cdef"])}"#)
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap_err(),
|
||||
vec![ServerError {
|
||||
message: r#"Failed to parse "String": the string length is 4, must be less than or equal to 3"#.to_string(),
|
||||
source: None,
|
||||
locations: vec![Pos { column: 17, line: 1}],
|
||||
path: vec![PathSegment::Field("value".to_string())],
|
||||
extensions: None
|
||||
}]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute(r#"{ value(values: ["a", "b"])}"#)
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap()
|
||||
.data,
|
||||
value!({
|
||||
"value": "ab"
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue