From 68965e5a0c1bfc15eff0890d5777785868e33a6c Mon Sep 17 00:00:00 2001 From: Sunli Date: Fri, 25 Sep 2020 15:26:29 +0800 Subject: [PATCH] Add data_XXX methods to ResolveInfo and remove context field from ResolveInfo. #260 --- src/context.rs | 8 ++++++++ src/extensions/mod.rs | 39 +++++++++++++++++++++++++++++++++++- src/resolver_utils/list.rs | 2 ++ src/resolver_utils/object.rs | 2 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index ebeaa9ef..8b634b80 100644 --- a/src/context.rs +++ b/src/context.rs @@ -90,6 +90,14 @@ impl From for Value { #[derive(Default)] pub struct Data(FnvHashMap>); +impl Deref for Data { + type Target = FnvHashMap>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl Data { /// Insert data. pub fn insert(&mut self, data: D) { diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 7167d85b..15ad4929 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -8,7 +8,7 @@ mod logger; mod tracing; use crate::context::{QueryPathNode, ResolveId}; -use crate::{Result, Variables}; +use crate::{FieldResult, QueryEnv, Result, SchemaEnv, Variables}; #[cfg(feature = "apollo_tracing")] pub use self::apollo_tracing::ApolloTracing; @@ -19,6 +19,7 @@ pub use self::tracing::Tracing; use crate::parser::types::ExecutableDocument; use crate::Error; use serde_json::Value; +use std::any::{Any, TypeId}; pub(crate) type BoxExtension = Box; @@ -39,6 +40,42 @@ pub struct ResolveInfo<'a> { /// Current return type, is qualified name. pub return_type: &'a str, + + pub(crate) schema_env: &'a SchemaEnv, + pub(crate) query_env: &'a QueryEnv, +} + +impl<'a> ResolveInfo<'a> { + /// Gets the global data defined in the `Context` or `Schema`. + /// + /// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained. + /// + /// # Errors + /// + /// Returns a `FieldError` if the specified type data does not exist. + pub fn data(&self) -> FieldResult<&D> { + self.data_opt::() + .ok_or_else(|| format!("Data `{}` does not exist.", std::any::type_name::()).into()) + } + + /// Gets the global data defined in the `Context` or `Schema`. + /// + /// # Panics + /// + /// It will panic if the specified data type does not exist. + pub fn data_unchecked(&self) -> &D { + self.data_opt::() + .unwrap_or_else(|| panic!("Data `{}` does not exist.", std::any::type_name::())) + } + + /// Gets the global data defined in the `Context` or `Schema` or `None` if the specified type data does not exist. + pub fn data_opt(&self) -> Option<&D> { + self.query_env + .ctx_data + .get(&TypeId::of::()) + .or_else(|| self.schema_env.data.get(&TypeId::of::())) + .and_then(|d| d.downcast_ref::()) + } } /// Represents a GraphQL extension diff --git a/src/resolver_utils/list.rs b/src/resolver_utils/list.rs index 2725dd6b..10df98d5 100644 --- a/src/resolver_utils/list.rs +++ b/src/resolver_utils/list.rs @@ -18,6 +18,8 @@ pub async fn resolve_list<'a, T: OutputValueType + Send + Sync + 'a>( path_node: ctx_idx.path_node.as_ref().unwrap(), parent_type: &Vec::::type_name(), return_type: &T::type_name(), + schema_env: ctx.schema_env, + query_env: ctx.query_env, }; ctx_idx diff --git a/src/resolver_utils/object.rs b/src/resolver_utils/object.rs index 6cde5ad9..67662629 100644 --- a/src/resolver_utils/object.rs +++ b/src/resolver_utils/object.rs @@ -194,6 +194,8 @@ impl<'a> Fields<'a> { }) } }, + schema_env: ctx.schema_env, + query_env: ctx.query_env, }; ctx_field