diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 39eca0f634..80c99147c1 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -25,10 +25,25 @@ fn create_related_fields( 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.name(), visited), - ); + if let Some(modify) = &field.modify { + if let Some(modified_name) = &modify.name { + map.insert( + modified_name.clone(), + ( + name.clone(), + create_related_fields(config, field.type_of.name(), visited), + ), + ); + } + } else { + map.insert( + name.clone(), + ( + name.clone(), + create_related_fields(config, field.type_of.name(), visited), + ), + ); + } } } } else if let Some(union_) = config.find_union(type_name) { diff --git a/src/core/ir/eval_context.rs b/src/core/ir/eval_context.rs index 1a79f561bb..c733882f85 100644 --- a/src/core/ir/eval_context.rs +++ b/src/core/ir/eval_context.rs @@ -130,9 +130,9 @@ fn format_selection_set<'a>( let set = selection_set .filter_map(|field| { // add to set only related fields that should be resolved with current resolver - related_fields - .get(field.name()) - .map(|related_fields| format_selection_field(field, related_fields)) + related_fields.get(field.name()).map(|related_fields| { + format_selection_field(field, &related_fields.0, &related_fields.1) + }) }) .collect::>(); @@ -143,8 +143,11 @@ fn format_selection_set<'a>( Some(format!("{{ {} }}", set.join(" "))) } -fn format_selection_field(field: &SelectionField, related_fields: &RelatedFields) -> String { - let name = field.name(); +fn format_selection_field( + field: &SelectionField, + name: &str, + related_fields: &RelatedFields, +) -> String { let arguments = format_selection_field_arguments(field); let selection_set = format_selection_set(field.selection_set(), related_fields); diff --git a/src/core/ir/mod.rs b/src/core/ir/mod.rs index 71e7748573..4540424848 100644 --- a/src/core/ir/mod.rs +++ b/src/core/ir/mod.rs @@ -21,10 +21,10 @@ pub use resolver_context_like::{ /// resolver i.e. fields that don't have their own resolver and are resolved by /// the ancestor #[derive(Debug, Default, Clone)] -pub struct RelatedFields(pub HashMap); +pub struct RelatedFields(pub HashMap); impl Deref for RelatedFields { - type Target = HashMap; + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.0 diff --git a/tests/core/snapshots/graphql-conformance-018.md_0.snap b/tests/core/snapshots/graphql-conformance-018.md_0.snap new file mode 100644 index 0000000000..67b166b416 --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-018.md_0.snap @@ -0,0 +1,18 @@ +--- +source: tests/core/spec.rs +expression: response +--- +{ + "status": 200, + "headers": { + "content-type": "application/json" + }, + "body": { + "data": { + "user": { + "city": "Globe", + "newName": "Tailcall" + } + } + } +} diff --git a/tests/core/snapshots/graphql-conformance-018.md_client.snap b/tests/core/snapshots/graphql-conformance-018.md_client.snap new file mode 100644 index 0000000000..21e04a64ac --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-018.md_client.snap @@ -0,0 +1,17 @@ +--- +source: tests/core/spec.rs +expression: formatted +--- +type Query { + user(id: ID!): User! +} + +type User { + city: String + id: ID! + newName: String! +} + +schema { + query: Query +} diff --git a/tests/core/snapshots/graphql-conformance-018.md_merged.snap b/tests/core/snapshots/graphql-conformance-018.md_merged.snap new file mode 100644 index 0000000000..6dad406ac9 --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-018.md_merged.snap @@ -0,0 +1,19 @@ +--- +source: tests/core/spec.rs +expression: formatter +--- +schema + @server(hostname: "0.0.0.0", port: 8001, queryValidation: false) + @upstream(baseURL: "http://upstream/graphql", httpCache: 42) { + query: Query +} + +type Query { + user(id: ID!): User! @graphQL(args: [{key: "id", value: "{{.args.id}}"}], name: "user") +} + +type User { + city: String + id: ID! + name: String! @modify(name: "newName") +} diff --git a/tests/execution/graphql-conformance-018.md b/tests/execution/graphql-conformance-018.md new file mode 100644 index 0000000000..f5ea02a66f --- /dev/null +++ b/tests/execution/graphql-conformance-018.md @@ -0,0 +1,47 @@ +# Basic queries with field modify check + +```graphql @config +schema + @server(port: 8001, queryValidation: false, hostname: "0.0.0.0") + @upstream(baseURL: "http://upstream/graphql", httpCache: 42) { + query: Query +} + +type Query { + user(id: ID!): User! @graphQL(name: "user", args: [{key: "id", value: "{{.args.id}}"}]) +} + +type User { + id: ID! + name: String! @modify(name: "newName") + city: String +} +``` + +```yml @mock +- request: + method: POST + url: http://upstream/graphql + textBody: '{ "query": "query { user(id: 4) { city name } }" }' + expectedHits: 1 + response: + status: 200 + body: + data: + user: + city: Globe + name: Tailcall +``` + +```yml @test +- method: POST + url: http://localhost:8080/graphql + body: + query: | + query getUser { + user(id: 4) { + city + newName + } + } +```