Moved `Variables` from `async_graphql::context::Variables` to
`async_graphql::Variables`.
This commit is contained in:
parent
10c41a7841
commit
4f2ea5ed50
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,8 +4,16 @@ 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).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- Moved `Variables` from `async_graphql::context::Variables` to `async_graphql::Variables`.
|
||||
|
||||
## [2.5.8] - 2021-02-27
|
||||
|
||||
### Added
|
||||
|
||||
- Allow the `deprecation` attribute to have no reason.
|
||||
|
||||
```rust
|
||||
|
@ -27,10 +35,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [2.5.7] - 2021-02-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the problem that the borrowing lifetime returned by the `Context::data` function is too small.
|
||||
|
||||
## [2.5.6] - 2021-02-23
|
||||
|
||||
### Changed
|
||||
|
||||
- When introspection is disabled, introspection related types are no longer registered.
|
||||
|
||||
## [2.5.5] - 2021-02-22
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
//! Query context.
|
||||
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::convert::TryFrom;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_graphql_value::Value as InputValue;
|
||||
use async_graphql_value::{Value as InputValue, Variables};
|
||||
use fnv::FnvHashMap;
|
||||
use http::header::{AsHeaderName, HeaderMap, IntoHeaderName};
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{SerializeSeq, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -25,81 +23,6 @@ use crate::{
|
|||
UploadValue, Value,
|
||||
};
|
||||
|
||||
/// Variables of a query.
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Variables(pub BTreeMap<Name, Value>);
|
||||
|
||||
impl Display for Variables {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("{")?;
|
||||
for (i, (name, value)) in self.0.iter().enumerate() {
|
||||
write!(f, "{}{}: {}", if i == 0 { "" } else { ", " }, name, value)?;
|
||||
}
|
||||
f.write_str("}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Variables {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
Ok(Self(
|
||||
<Option<BTreeMap<Name, Value>>>::deserialize(deserializer)?.unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Variables {
|
||||
/// Get the variables from a GraphQL value.
|
||||
///
|
||||
/// If the value is not a map, then no variables will be returned.
|
||||
#[must_use]
|
||||
pub fn from_value(value: Value) -> Self {
|
||||
match value {
|
||||
Value::Object(obj) => Self(obj),
|
||||
_ => Self::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the values from a JSON value.
|
||||
///
|
||||
/// If the value is not a map or the keys of a map are not valid GraphQL names, then no
|
||||
/// variables will be returned.
|
||||
#[must_use]
|
||||
pub fn from_json(value: serde_json::Value) -> Self {
|
||||
Value::from_json(value)
|
||||
.map(Self::from_value)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Get the variables as a GraphQL value.
|
||||
#[must_use]
|
||||
pub fn into_value(self) -> Value {
|
||||
Value::Object(self.0)
|
||||
}
|
||||
|
||||
pub(crate) fn variable_path(&mut self, path: &str) -> Option<&mut Value> {
|
||||
let mut parts = path.strip_prefix("variables.")?.split('.');
|
||||
|
||||
let initial = self.0.get_mut(parts.next().unwrap())?;
|
||||
|
||||
parts.try_fold(initial, |current, part| match current {
|
||||
Value::List(list) => part
|
||||
.parse::<u32>()
|
||||
.ok()
|
||||
.and_then(|idx| usize::try_from(idx).ok())
|
||||
.and_then(move |idx| list.get_mut(idx)),
|
||||
Value::Object(obj) => obj.get_mut(part),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Variables> for Value {
|
||||
fn from(variables: Variables) -> Self {
|
||||
variables.into_value()
|
||||
}
|
||||
}
|
||||
|
||||
/// Schema/Context data.
|
||||
///
|
||||
/// This is a type map, allowing you to store anything inside it.
|
||||
|
@ -574,7 +497,6 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
.and_then(|def| {
|
||||
self.query_env
|
||||
.variables
|
||||
.0
|
||||
.get(&def.node.name.node)
|
||||
.or_else(|| def.node.default_value())
|
||||
})
|
||||
|
|
|
@ -208,7 +208,7 @@ pub use subscription::SubscriptionType;
|
|||
pub use async_graphql_parser as parser;
|
||||
pub use async_graphql_value::{
|
||||
from_value, to_value, value, ConstValue as Value, DeserializerError, Name, Number,
|
||||
SerializerError,
|
||||
SerializerError, Variables,
|
||||
};
|
||||
pub use base::{
|
||||
Description, InputObjectType, InputType, InterfaceType, ObjectType, OutputType, Type, UnionType,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
@ -79,7 +80,23 @@ impl Request {
|
|||
/// `request.variables["files"][2]["content"]`. If no variable exists at the path this function
|
||||
/// won't do anything.
|
||||
pub fn set_upload(&mut self, var_path: &str, upload: UploadValue) {
|
||||
let variable = match self.variables.variable_path(var_path) {
|
||||
fn variable_path<'a>(variables: &'a mut Variables, path: &str) -> Option<&'a mut Value> {
|
||||
let mut parts = path.strip_prefix("variables.")?.split('.');
|
||||
|
||||
let initial = variables.get_mut(parts.next().unwrap())?;
|
||||
|
||||
parts.try_fold(initial, |current, part| match current {
|
||||
Value::List(list) => part
|
||||
.parse::<u32>()
|
||||
.ok()
|
||||
.and_then(|idx| usize::try_from(idx).ok())
|
||||
.and_then(move |idx| list.get_mut(idx)),
|
||||
Value::Object(obj) => obj.get_mut(part),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
let variable = match variable_path(&mut self.variables, var_path) {
|
||||
Some(variable) => variable,
|
||||
None => return,
|
||||
};
|
||||
|
@ -171,7 +188,7 @@ mod tests {
|
|||
"query": "{ a b c }"
|
||||
}))
|
||||
.unwrap();
|
||||
assert!(request.variables.0.is_empty());
|
||||
assert!(request.variables.is_empty());
|
||||
assert!(request.operation_name.is_none());
|
||||
assert_eq!(request.query, "{ a b c }");
|
||||
}
|
||||
|
@ -183,7 +200,7 @@ mod tests {
|
|||
"operationName": "a"
|
||||
}))
|
||||
.unwrap();
|
||||
assert!(request.variables.0.is_empty());
|
||||
assert!(request.variables.is_empty());
|
||||
assert_eq!(request.operation_name.as_deref(), Some("a"));
|
||||
assert_eq!(request.query, "{ a b c }");
|
||||
}
|
||||
|
@ -219,7 +236,7 @@ mod tests {
|
|||
}))
|
||||
.unwrap();
|
||||
assert!(request.operation_name.is_none());
|
||||
assert!(request.variables.0.is_empty());
|
||||
assert!(request.variables.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -230,7 +247,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
if let BatchRequest::Single(request) = request {
|
||||
assert!(request.variables.0.is_empty());
|
||||
assert!(request.variables.is_empty());
|
||||
assert!(request.operation_name.is_none());
|
||||
assert_eq!(request.query, "{ a b c }");
|
||||
} else {
|
||||
|
@ -251,11 +268,11 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
if let BatchRequest::Batch(requests) = request {
|
||||
assert!(requests[0].variables.0.is_empty());
|
||||
assert!(requests[0].variables.is_empty());
|
||||
assert!(requests[0].operation_name.is_none());
|
||||
assert_eq!(requests[0].query, "{ a b c }");
|
||||
|
||||
assert!(requests[1].variables.0.is_empty());
|
||||
assert!(requests[1].variables.is_empty());
|
||||
assert!(requests[1].operation_name.is_none());
|
||||
assert_eq!(requests[1].query, "{ d e }");
|
||||
} else {
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
|
|||
.clone()
|
||||
.into_const_with(|var_name| {
|
||||
ctx.variables
|
||||
.and_then(|variables| variables.0.get(&var_name))
|
||||
.and_then(|variables| variables.get(&var_name))
|
||||
.map(Clone::clone)
|
||||
.ok_or(())
|
||||
})
|
||||
|
|
|
@ -118,7 +118,6 @@ impl<'a> VisitorContext<'a> {
|
|||
.and_then(|def| {
|
||||
if let Some(variables) = self.variables {
|
||||
variables
|
||||
.0
|
||||
.get(&def.node.name.node)
|
||||
.or_else(|| def.node.default_value())
|
||||
} else {
|
||||
|
|
|
@ -1688,9 +1688,7 @@ pub async fn test_input_validator_variable() {
|
|||
let validator_length = 6;
|
||||
for case in &test_cases {
|
||||
let mut variables = Variables::default();
|
||||
variables
|
||||
.0
|
||||
.insert(Name::new("id"), Value::String(case.to_string()));
|
||||
variables.insert(Name::new("id"), Value::String(case.to_string()));
|
||||
|
||||
let field_query = "query($id: String!) {fieldParameter(id: $id)}";
|
||||
let object_query = "query($id: String!) {inputObject(input: {id: $id})}";
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
mod de;
|
||||
mod macros;
|
||||
mod ser;
|
||||
mod variables;
|
||||
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -22,6 +23,8 @@ pub use de::{from_value, DeserializerError};
|
|||
pub use ser::{to_value, SerializerError};
|
||||
pub use serde_json::Number;
|
||||
|
||||
pub use variables::Variables;
|
||||
|
||||
/// A GraphQL name.
|
||||
///
|
||||
/// [Reference](https://spec.graphql.org/June2018/#Name).
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::{ConstValue, Name};
|
||||
|
||||
/// Variables of a query.
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Variables(BTreeMap<Name, ConstValue>);
|
||||
|
||||
impl Display for Variables {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("{")?;
|
||||
for (i, (name, value)) in self.0.iter().enumerate() {
|
||||
write!(f, "{}{}: {}", if i == 0 { "" } else { ", " }, name, value)?;
|
||||
}
|
||||
f.write_str("}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Variables {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
Ok(Self(
|
||||
<Option<BTreeMap<Name, ConstValue>>>::deserialize(deserializer)?.unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Variables {
|
||||
/// Get the variables from a GraphQL value.
|
||||
///
|
||||
/// If the value is not a map, then no variables will be returned.
|
||||
#[must_use]
|
||||
pub fn from_value(value: ConstValue) -> Self {
|
||||
match value {
|
||||
ConstValue::Object(obj) => Self(obj),
|
||||
_ => Self::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the values from a JSON value.
|
||||
///
|
||||
/// If the value is not a map or the keys of a map are not valid GraphQL names, then no
|
||||
/// variables will be returned.
|
||||
#[must_use]
|
||||
pub fn from_json(value: serde_json::Value) -> Self {
|
||||
ConstValue::from_json(value)
|
||||
.map(Self::from_value)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Get the variables as a GraphQL value.
|
||||
#[must_use]
|
||||
pub fn into_value(self) -> ConstValue {
|
||||
ConstValue::Object(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Variables> for ConstValue {
|
||||
fn from(variables: Variables) -> Self {
|
||||
variables.into_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Variables {
|
||||
type Target = BTreeMap<Name, ConstValue>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Variables {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue