Add directive @ifdef

This commit is contained in:
Sunli 2020-08-06 14:52:54 +08:00
parent efaccb47e0
commit a193a8e51a
6 changed files with 101 additions and 0 deletions

View File

@ -462,6 +462,16 @@ impl<'a, T> ContextBase<'a, T> {
}
}
#[doc(hidden)]
pub fn is_ifdef(&self, directives: &[Positioned<Directive>]) -> bool {
for directive in directives {
if directive.name.node == "ifdef" {
return true;
}
}
false
}
#[doc(hidden)]
pub fn is_skip(&self, directives: &[Positioned<Directive>]) -> Result<bool> {
for directive in directives {

View File

@ -1,5 +1,6 @@
use crate::extensions::{ErrorLogger, Extension, ResolveInfo};
use crate::parser::query::{Selection, TypeCondition};
use crate::registry::MetaType;
use crate::{ContextSelectionSet, Error, ObjectType, QueryError, Result};
use std::future::Future;
use std::pin::Pin;
@ -47,6 +48,16 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
continue;
}
if ctx.is_ifdef(&field.directives) {
if let Some(MetaType::Object { fields, .. }) =
ctx.schema_env.registry.types.get(T::type_name().as_ref())
{
if !fields.contains_key(field.name.as_str()) {
continue;
}
}
}
let ctx_field = ctx.with_field(field);
let field_name = ctx_field.result_name().to_string();

View File

@ -1,6 +1,7 @@
use crate::base::BoxFieldFuture;
use crate::extensions::{ErrorLogger, Extension, ResolveInfo};
use crate::parser::query::{Selection, TypeCondition};
use crate::registry::MetaType;
use crate::{ContextSelectionSet, Error, ObjectType, QueryError, Result};
use futures::{future, TryFutureExt};
@ -63,6 +64,16 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
continue;
}
if ctx.is_ifdef(&field.directives) {
if let Some(MetaType::Object { fields, .. }) =
ctx.schema_env.registry.types.get(T::type_name().as_ref())
{
if !fields.contains_key(field.name.as_str()) {
continue;
}
}
}
futures.push(Box::pin({
let ctx = ctx.clone();
async move {

View File

@ -241,6 +241,13 @@ where
}
});
registry.add_directive(MetaDirective {
name: "ifdef",
description: Some("Directs the executor to query only when the field exists."),
locations: vec![__DirectiveLocation::FIELD],
args: Default::default(),
});
// register scalars
bool::create_type_info(&mut registry);
i32::create_type_info(&mut registry);

View File

@ -21,6 +21,10 @@ impl<'a> Visitor<'a> for FieldsOnCorrectType {
.fields()
.and_then(|fields| fields.get(field.name.as_str()))
.is_none()
&& !field
.directives
.iter()
.any(|directive| directive.node.name.as_str() == "ifdef")
{
ctx.report_error(
vec![field.position()],

View File

@ -61,3 +61,61 @@ pub async fn test_directive_include() {
})
);
}
#[async_std::test]
pub async fn test_directive_ifdef() {
struct QueryRoot;
#[Object]
impl QueryRoot {
pub async fn value1(&self) -> i32 {
10
}
}
struct MutationRoot;
#[Object]
impl MutationRoot {
pub async fn action1(&self) -> i32 {
10
}
}
let schema = Schema::new(QueryRoot, MutationRoot, EmptySubscription);
let resp = schema
.execute(
r#"
{
value1 @ifdef
value2 @ifdef
}
"#,
)
.await
.unwrap();
assert_eq!(
resp.data,
serde_json::json!({
"value1": 10,
})
);
let resp = schema
.execute(
r#"
mutation {
action1 @ifdef
action2 @ifdef
}
"#,
)
.await
.unwrap();
assert_eq!(
resp.data,
serde_json::json!({
"action1": 10,
})
);
}