From 89e021bd9d522b87d27dba81eb4e788ea37ba534 Mon Sep 17 00:00:00 2001 From: Sandipsinh Dilipsinh Rathod <62684960+ssddOnTop@users.noreply.github.com> Date: Thu, 25 Jul 2024 21:38:51 +0530 Subject: [PATCH] fix: recursive types on `@graphql` directive (#2528) --- src/core/blueprint/operators/graphql.rs | 21 +++++-- .../related-fields-recursive.md_client.snap | 55 +++++++++++++++++++ .../related-fields-recursive.md_merged.snap | 23 ++++++++ tests/execution/related-fields-recursive.md | 21 +++++++ 4 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/core/snapshots/related-fields-recursive.md_client.snap create mode 100644 tests/core/snapshots/related-fields-recursive.md_merged.snap create mode 100644 tests/execution/related-fields-recursive.md diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 6f057eef8b..74f8282644 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use crate::core::blueprint::FieldDefinition; use crate::core::config::{Config, ConfigModule, Field, GraphQL, GraphQLOperationType, Type}; @@ -9,18 +9,29 @@ use crate::core::ir::RelatedFields; use crate::core::try_fold::TryFold; use crate::core::valid::{Valid, ValidationError, Validator}; -fn create_related_fields(config: &Config, type_name: &str) -> RelatedFields { +fn create_related_fields( + config: &Config, + type_name: &str, + visited: &mut HashSet, +) -> RelatedFields { let mut map = HashMap::new(); + if visited.contains(type_name) { + return RelatedFields(map); + } + visited.insert(type_name.to_string()); if let Some(type_) = config.find_type(type_name) { for (name, field) in &type_.fields { if !field.has_resolver() { - map.insert(name.clone(), create_related_fields(config, &field.type_of)); + map.insert( + name.clone(), + create_related_fields(config, &field.type_of, visited), + ); } } } else if let Some(union_) = config.find_union(type_name) { for type_name in &union_.types { - map.extend(create_related_fields(config, type_name).0); + map.extend(create_related_fields(config, type_name, visited).0); } }; @@ -50,7 +61,7 @@ pub fn compile_graphql( &graphql.name, args, headers, - create_related_fields(config, type_name), + create_related_fields(config, type_name, &mut HashSet::new()), ) .map_err(|e| ValidationError::new(e.to_string())), ) diff --git a/tests/core/snapshots/related-fields-recursive.md_client.snap b/tests/core/snapshots/related-fields-recursive.md_client.snap new file mode 100644 index 0000000000..e3e1a28ec3 --- /dev/null +++ b/tests/core/snapshots/related-fields-recursive.md_client.snap @@ -0,0 +1,55 @@ +--- +source: tests/core/spec.rs +expression: formatted +--- +scalar Bytes + +scalar Date + +scalar Email + +scalar Empty + +scalar Int128 + +scalar Int16 + +scalar Int32 + +scalar Int64 + +scalar Int8 + +scalar JSON + +type NodeA { + name: String + nodeB: NodeB +} + +type NodeB { + name: String + nodeA: NodeA +} + +scalar PhoneNumber + +type Query { + queryNodeA: [NodeA] +} + +scalar UInt128 + +scalar UInt16 + +scalar UInt32 + +scalar UInt64 + +scalar UInt8 + +scalar Url + +schema { + query: Query +} diff --git a/tests/core/snapshots/related-fields-recursive.md_merged.snap b/tests/core/snapshots/related-fields-recursive.md_merged.snap new file mode 100644 index 0000000000..fa15978762 --- /dev/null +++ b/tests/core/snapshots/related-fields-recursive.md_merged.snap @@ -0,0 +1,23 @@ +--- +source: tests/core/spec.rs +expression: formatter +--- +schema @server(hostname: "0.0.0.0", port: 8000) @upstream(baseURL: "http://localhost:8083/graphql") { + query: Query +} + +scalar DateTime + +type NodeA { + name: String + nodeB: NodeB +} + +type NodeB { + name: String + nodeA: NodeA +} + +type Query { + queryNodeA: [NodeA] @graphQL(name: "queryNodeA") +} diff --git a/tests/execution/related-fields-recursive.md b/tests/execution/related-fields-recursive.md new file mode 100644 index 0000000000..7e70e3b702 --- /dev/null +++ b/tests/execution/related-fields-recursive.md @@ -0,0 +1,21 @@ +```graphql @config +scalar DateTime + +schema @server(port: 8000, hostname: "0.0.0.0") @upstream(baseURL: "http://localhost:8083/graphql") { + query: Query +} + +type Query { + queryNodeA: [NodeA] @graphQL(name: "queryNodeA", batch: false) +} + +type NodeA { + name: String + nodeB: NodeB +} + +type NodeB { + name: String + nodeA: NodeA +} +```