From bb670b953679f2a4a17aba541c2013d8eead9661 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Thu, 20 Nov 2025 14:53:56 +0300 Subject: [PATCH 1/5] enhance(query-planner): avoid extra `query` prefix for anonymous queries --- .changeset/extra-query-avoid.md | 16 ++ .../src/ast/normalization/mod.rs | 154 +++++++++--------- lib/query-planner/src/ast/operation.rs | 15 ++ lib/query-planner/src/tests/alias.rs | 26 +-- lib/query-planner/src/tests/arguments.rs | 18 +- .../src/tests/interface_object.rs | 2 +- .../tests/interface_object_with_requires.rs | 12 +- .../src/tests/object_entities.rs | 8 +- .../src/tests/override_requires.rs | 12 +- lib/query-planner/src/tests/overrides.rs | 6 +- lib/query-planner/src/tests/provides.rs | 6 +- lib/query-planner/src/tests/requires.rs | 16 +- .../src/tests/requires_provides.rs | 2 +- .../src/tests/requires_requires.rs | 16 +- lib/query-planner/src/tests/root_types.rs | 6 +- 15 files changed, 173 insertions(+), 142 deletions(-) create mode 100644 .changeset/extra-query-avoid.md diff --git a/.changeset/extra-query-avoid.md b/.changeset/extra-query-avoid.md new file mode 100644 index 000000000..fbd081b3f --- /dev/null +++ b/.changeset/extra-query-avoid.md @@ -0,0 +1,16 @@ +--- +hive-router-query-planner: patch +--- + +# Avoid extra `query` prefix for anonymous queries + +When there is no variable definitions and no operation name, GraphQL queries can be sent without the `query` prefix. For example, instead of sending: + +```diff +- query { ++ { + user(id: "1") { + name + } +} +``` \ No newline at end of file diff --git a/lib/query-planner/src/ast/normalization/mod.rs b/lib/query-planner/src/ast/normalization/mod.rs index bbc5081a1..d4861923e 100644 --- a/lib/query-planner/src/ast/normalization/mod.rs +++ b/lib/query-planner/src/ast/normalization/mod.rs @@ -135,16 +135,16 @@ mod tests { .unwrap() .to_string() ), - @r#" - query { - a: __typename - words - __typename - __schema { - __typename - } - } - "# + @r" + { + a: __typename + words + __typename + __schema { + __typename + } + } + " ); } @@ -179,11 +179,11 @@ mod tests { .to_string() ), @r#" - query { - words(sep: ",") - foo: words(len: 10, sep: ".") - } - "# + { + words(sep: ",") + foo: words(len: 10, sep: ".") + } + "# ); } @@ -261,14 +261,14 @@ mod tests { .unwrap() .to_string() ), - @r#" - query { - words - c: words(len: 1) - b: words - a: words - } - "# + @r" + { + words + c: words(len: 1) + b: words + a: words + } + " ); } @@ -386,7 +386,7 @@ mod tests { .to_string() ), @r" - query { + { products { ... on Toaster { t1 @@ -529,12 +529,12 @@ mod tests { insta::assert_snapshot!( pretty_query(r.to_string()), - @r###" - query { + @r#" + { one: words(len: 10, sep: ".") two: words(len: 10, sep: ".") } - "### + "# ); } @@ -697,7 +697,7 @@ mod tests { .to_string() ), @r" - query { + { userFromA { profile { displayName @@ -792,7 +792,7 @@ mod tests { .to_string() ), @r" - query { + { products { id ... on Book { @@ -841,13 +841,13 @@ mod tests { .to_string() ), @r" - query { - anotherUsers { - id - name - username - } - } + { + anotherUsers { + id + name + username + } + } ", ); } @@ -885,19 +885,19 @@ mod tests { .to_string() ), @r" - query { - userFromA { - profile { - ... on AdminAccount { - accountType - } - ... on GuestAccount { - accountType + { + userFromA { + profile { + ... on AdminAccount { + accountType + } + ... on GuestAccount { + accountType + } } } } - } - ", + ", ); } @@ -940,20 +940,20 @@ mod tests { .to_string() ), @r" - query { - userFromA { - profile { - ... on AdminAccount { - accountType - } - ... on GuestAccount { - accountType - guestToken + { + userFromA { + profile { + ... on AdminAccount { + accountType + } + ... on GuestAccount { + accountType + guestToken + } } } } - } - ", + ", ); } @@ -1185,7 +1185,7 @@ mod tests { .to_string() ), @r" - query { + { results { __typename ... on MultipleColor { @@ -1265,27 +1265,27 @@ mod tests { .to_string() ), @r" - query { - results { - __typename - ... on MultipleColor { - id - name - colorOptions { - id - color - } - } - ... on SingleColor { - id - name - colorOption { - id - color - } - } + { + results { + __typename + ... on MultipleColor { + id + name + colorOptions { + id + color } } + ... on SingleColor { + id + name + colorOption { + id + color + } + } + } + } " ); } diff --git a/lib/query-planner/src/ast/operation.rs b/lib/query-planner/src/ast/operation.rs index 0584be4e2..fa83ef211 100644 --- a/lib/query-planner/src/ast/operation.rs +++ b/lib/query-planner/src/ast/operation.rs @@ -129,6 +129,21 @@ impl PrettyDisplay for SubgraphFetchOperation { impl Display for OperationDefinition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if (self.operation_kind.is_none() + || self + .operation_kind + .as_ref() + .is_none_or(|k| matches!(k, OperationKind::Query))) + && (self.name.is_none() || self.name.as_ref().is_none_or(|n| n.is_empty())) + && (self.variable_definitions.is_none() + || self + .variable_definitions + .as_ref() + .is_none_or(|v| v.is_empty())) + { + // Short form for anonymous query + return self.selection_set.fmt(f); + } if let Some(operation_kind) = &self.operation_kind { write!(f, "{}", operation_kind)?; } diff --git a/lib/query-planner/src/tests/alias.rs b/lib/query-planner/src/tests/alias.rs index a36c3c537..25d42f6c1 100644 --- a/lib/query-planner/src/tests/alias.rs +++ b/lib/query-planner/src/tests/alias.rs @@ -138,14 +138,14 @@ fn conflict_list_type_in_interface() -> Result<(), Box> { }, "###); - insta::assert_snapshot!(format!("{}", sonic_rs::to_string_pretty(&query_plan).unwrap_or_default()), @r###" + insta::assert_snapshot!(format!("{}", sonic_rs::to_string_pretty(&query_plan).unwrap_or_default()), @r#" { "kind": "QueryPlan", "node": { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{i{__typename ...on TypeA{strField} ...on TypeB{_internal_qp_alias_0: strField}}}", + "operation": "{i{__typename ...on TypeA{strField} ...on TypeB{_internal_qp_alias_0: strField}}}", "outputRewrites": [ { "KeyRenamer": { @@ -166,7 +166,7 @@ fn conflict_list_type_in_interface() -> Result<(), Box> { ] } } - "###); + "#); Ok(()) } @@ -212,14 +212,14 @@ fn multiple_mismtaches_same_level() -> Result<(), Box> { }, "###); - insta::assert_snapshot!(format!("{}", sonic_rs::to_string_pretty(&query_plan).unwrap_or_default()), @r###" + insta::assert_snapshot!(format!("{}", sonic_rs::to_string_pretty(&query_plan).unwrap_or_default()), @r#" { "kind": "QueryPlan", "node": { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{i{__typename ...on TypeA{strField strField2} ...on TypeB{_internal_qp_alias_0: strField _internal_qp_alias_1: strField2}}}", + "operation": "{i{__typename ...on TypeA{strField strField2} ...on TypeB{_internal_qp_alias_0: strField _internal_qp_alias_1: strField2}}}", "outputRewrites": [ { "KeyRenamer": { @@ -256,7 +256,7 @@ fn multiple_mismtaches_same_level() -> Result<(), Box> { ] } } - "###); + "#); Ok(()) } @@ -426,7 +426,7 @@ fn simple_mismatch_between_union_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{accounts{__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}}", + "operation": "{accounts{__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}}", "outputRewrites": [ { "KeyRenamer": { @@ -450,7 +450,7 @@ fn simple_mismatch_between_union_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{users{__typename id}}" + "operation": "{users{__typename id}}" } ] }, @@ -616,7 +616,7 @@ fn nested_internal_mismatch_between_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{accounts{__typename ...on User{id name similarAccounts{...a}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}\n", + "operation": "{accounts{__typename ...on User{id name similarAccounts{...a}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}\n", "outputRewrites": [ { "KeyRenamer": { @@ -684,7 +684,7 @@ fn nested_internal_mismatch_between_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{users{__typename id}}" + "operation": "{users{__typename id}}" } ] }, @@ -905,7 +905,7 @@ fn deeply_nested_internal_mismatch_between_fields() -> Result<(), Box "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{accounts{__typename ...on User{id name similarAccounts{...a}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{id name similarAccounts{...b}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...b}}}\nfragment b on Account {__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}\n", + "operation": "{accounts{__typename ...on User{id name similarAccounts{...a}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{id name similarAccounts{...b}} ...on Admin{_internal_qp_alias_0: id name similarAccounts{...b}}}\nfragment b on Account {__typename ...on User{id name} ...on Admin{_internal_qp_alias_0: id name}}\n", "outputRewrites": [ { "KeyRenamer": { @@ -1085,7 +1085,7 @@ fn deeply_nested_internal_mismatch_between_fields() -> Result<(), Box "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{users{__typename id}}" + "operation": "{users{__typename id}}" } ] }, @@ -1249,7 +1249,7 @@ fn deeply_nested_no_conflicts() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{accounts{__typename ...on User{name similarAccounts{...a}} ...on Admin{name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{name similarAccounts{...b}} ...on Admin{name similarAccounts{...b}}}\nfragment b on Account {__typename ...on User{name} ...on Admin{name}}\n" + "operation": "{accounts{__typename ...on User{name similarAccounts{...a}} ...on Admin{name similarAccounts{...a}}}}\n\nfragment a on Account {__typename ...on User{name similarAccounts{...b}} ...on Admin{name similarAccounts{...b}}}\nfragment b on Account {__typename ...on User{name} ...on Admin{name}}\n" } } "#); diff --git a/lib/query-planner/src/tests/arguments.rs b/lib/query-planner/src/tests/arguments.rs index 7308c41d1..a46a56c0f 100644 --- a/lib/query-planner/src/tests/arguments.rs +++ b/lib/query-planner/src/tests/arguments.rs @@ -97,7 +97,7 @@ fn fed_audit_requires_with_argument_conflict() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{products{__typename upc name price(currency: \"USD\") weight _internal_qp_alias_0: price(currency: \"EUR\") category{averagePrice(currency: \"USD\")}}}" + "operation": "{products{__typename upc name price(currency: \"USD\") weight _internal_qp_alias_0: price(currency: \"EUR\") category{averagePrice(currency: \"USD\")}}}" }, { "kind": "Parallel", @@ -306,7 +306,7 @@ fn requires_arguments_deeply_nested_requires() -> Result<(), Box> { "kind": "Fetch", "serviceName": "c", "operationKind": "query", - "operation": "query{feed{__typename id}}" + "operation": "{feed{__typename id}}" }, { "kind": "Flatten", @@ -528,7 +528,7 @@ fn requires_arguments_deeply_nested_requires_with_variable() -> Result<(), Box Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{test{id __typename}}" + "operation": "{test{id __typename}}" }, { "kind": "Flatten", @@ -1195,7 +1195,7 @@ fn multiple_plain_field_and_requires_with_args_that_conflicts() -> Result<(), Bo "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{test{__typename id}}" + "operation": "{test{__typename id}}" }, { "kind": "Flatten", @@ -1388,7 +1388,7 @@ fn multiple_plain_field_and_requires_with_args_that_does_not_conflicts_should_me "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{test{__typename id}}" + "operation": "{test{__typename id}}" }, { "kind": "Flatten", @@ -1535,7 +1535,7 @@ fn simple_requires_arguments() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{test{id __typename}}" + "operation": "{test{id __typename}}" }, { "kind": "Flatten", @@ -1749,7 +1749,7 @@ fn arguments_in_different_levels() -> Result<(), Box> { "kind": "Fetch", "serviceName": "spotify", "operationKind": "query", - "operation": "query{album(id: \"5\"){albumType name genres tracks(limit: 5, offset: 10){edges{node{name}}}}}" + "operation": "{album(id: \"5\"){albumType name genres tracks(limit: 5, offset: 10){edges{node{name}}}}}" } } "#); diff --git a/lib/query-planner/src/tests/interface_object.rs b/lib/query-planner/src/tests/interface_object.rs index f01096dc1..40cbf9426 100644 --- a/lib/query-planner/src/tests/interface_object.rs +++ b/lib/query-planner/src/tests/interface_object.rs @@ -404,7 +404,7 @@ fn interface_object_with_inline_fragment_resolving_remote_interface_field( "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{anotherUsers{__typename id}}" + "operation": "{anotherUsers{__typename id}}" }, { "kind": "Flatten", diff --git a/lib/query-planner/src/tests/interface_object_with_requires.rs b/lib/query-planner/src/tests/interface_object_with_requires.rs index 256fed593..e74911c13 100644 --- a/lib/query-planner/src/tests/interface_object_with_requires.rs +++ b/lib/query-planner/src/tests/interface_object_with_requires.rs @@ -79,7 +79,7 @@ fn interface_object_requiring_interface_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{anotherUsers{__typename id}}" + "operation": "{anotherUsers{__typename id}}" }, { "kind": "Flatten", @@ -246,7 +246,7 @@ fn interface_field_from_remote_graph_with_requires() -> Result<(), Box Result<(), Box "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{anotherUsers{__typename id}}" + "operation": "{anotherUsers{__typename id}}" }, { "kind": "Flatten", @@ -480,7 +480,7 @@ fn inline_fragment_on_local_type_behind_interface() -> Result<(), Box "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{users{__typename ...on User{age}}}" + "operation": "{users{__typename ...on User{age}}}" } } "#); @@ -575,7 +575,7 @@ fn interface_object_field_with_requires_and_inline_fragment() -> Result<(), Box< "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{anotherUsers{__typename id}}" + "operation": "{anotherUsers{__typename id}}" }, { "kind": "Flatten", @@ -754,7 +754,7 @@ fn interface_field_from_remote_graph_with_requires_and_inline_fragment( "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{users{__typename ...on User{__typename age id name} id name}}", + "operation": "{users{__typename ...on User{__typename age id name} id name}}", "inputRewrites": [ { "ValueSetter": { diff --git a/lib/query-planner/src/tests/object_entities.rs b/lib/query-planner/src/tests/object_entities.rs index a4faa6253..04631ab3e 100644 --- a/lib/query-planner/src/tests/object_entities.rs +++ b/lib/query-planner/src/tests/object_entities.rs @@ -79,7 +79,7 @@ fn testing() -> Result<(), Box> { "kind": "Fetch", "serviceName": "store", "operationKind": "query", - "operation": "query{products{__typename id}}" + "operation": "{products{__typename id}}" }, { "kind": "Flatten", @@ -213,7 +213,7 @@ fn parent_entity_call() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{products{__typename id pid}}" + "operation": "{products{__typename id pid}}" }, { "kind": "Flatten", @@ -356,7 +356,7 @@ fn parent_entity_call_complex() -> Result<(), Box> { "kind": "Fetch", "serviceName": "d", "operationKind": "query", - "operation": "query{productFromD(id: \"1\"){__typename id name}}" + "operation": "{productFromD(id: \"1\"){__typename id name}}" }, { "kind": "Parallel", @@ -551,7 +551,7 @@ fn complex_entity_call() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{topProducts{products{__typename id category{tag id}}}}" + "operation": "{topProducts{products{__typename id category{tag id}}}}" }, { "kind": "Flatten", diff --git a/lib/query-planner/src/tests/override_requires.rs b/lib/query-planner/src/tests/override_requires.rs index 8fed080dc..bef779378 100644 --- a/lib/query-planner/src/tests/override_requires.rs +++ b/lib/query-planner/src/tests/override_requires.rs @@ -211,19 +211,19 @@ fn override_with_requires_many() -> Result<(), Box> { "kind": "Fetch", "serviceName": "c", "operationKind": "query", - "operation": "query{userInC{__typename id}}" + "operation": "{userInC{__typename id}}" }, { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{userInB{__typename id name}}" + "operation": "{userInB{__typename id name}}" }, { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{userInA{__typename id}}" + "operation": "{userInA{__typename id}}" } ] }, @@ -579,7 +579,7 @@ fn override_with_requires_cname_in_c() -> Result<(), Box> { "kind": "Fetch", "serviceName": "c", "operationKind": "query", - "operation": "query{userInC{id __typename}}" + "operation": "{userInC{id __typename}}" }, { "kind": "Flatten", @@ -723,7 +723,7 @@ fn override_with_requires_cname_in_a() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{userInA{__typename id}}" + "operation": "{userInA{__typename id}}" }, { "kind": "Flatten", @@ -867,7 +867,7 @@ fn override_with_requires_aname_in_a() -> Result<(), Box> { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{userInA{id __typename}}" + "operation": "{userInA{id __typename}}" }, { "kind": "Flatten", diff --git a/lib/query-planner/src/tests/overrides.rs b/lib/query-planner/src/tests/overrides.rs index 4434cef1b..65d81dd58 100644 --- a/lib/query-planner/src/tests/overrides.rs +++ b/lib/query-planner/src/tests/overrides.rs @@ -39,7 +39,7 @@ fn single_simple_overrides() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{feed{createdAt}}" + "operation": "{feed{createdAt}}" } } "#); @@ -116,13 +116,13 @@ fn two_fields_simple_overrides() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{bFeed{createdAt}}" + "operation": "{bFeed{createdAt}}" }, { "kind": "Fetch", "serviceName": "a", "operationKind": "query", - "operation": "query{aFeed{__typename id}}" + "operation": "{aFeed{__typename id}}" } ] }, diff --git a/lib/query-planner/src/tests/provides.rs b/lib/query-planner/src/tests/provides.rs index ca7c2d709..1cd7ec3c8 100644 --- a/lib/query-planner/src/tests/provides.rs +++ b/lib/query-planner/src/tests/provides.rs @@ -65,7 +65,7 @@ fn simple_provides() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc}}" + "operation": "{products{__typename upc}}" }, { "kind": "Flatten", @@ -145,7 +145,7 @@ fn nested_provides() -> Result<(), Box> { "kind": "Fetch", "serviceName": "category", "operationKind": "query", - "operation": "query{products{id categories{id name}}}" + "operation": "{products{id categories{id name}}}" } } "#); @@ -201,7 +201,7 @@ fn provides_on_union() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{media{__typename ...on Book{title id} ...on Movie{id}}}" + "operation": "{media{__typename ...on Book{title id} ...on Movie{id}}}" } } "#); diff --git a/lib/query-planner/src/tests/requires.rs b/lib/query-planner/src/tests/requires.rs index cefcdae4d..bf87853cf 100644 --- a/lib/query-planner/src/tests/requires.rs +++ b/lib/query-planner/src/tests/requires.rs @@ -95,7 +95,7 @@ fn two_same_service_calls_with_args_conflicts() -> Result<(), Box> { "kind": "Fetch", "serviceName": "inventory", "operationKind": "query", - "operation": "query{products{upc __typename}}" + "operation": "{products{upc __typename}}" }, { "kind": "Flatten", @@ -282,7 +282,7 @@ fn two_same_service_calls() -> Result<(), Box> { "kind": "Fetch", "serviceName": "inventory", "operationKind": "query", - "operation": "query{products{upc __typename}}" + "operation": "{products{upc __typename}}" }, { "kind": "Flatten", @@ -414,7 +414,7 @@ fn simplest_requires() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc price}}" + "operation": "{products{__typename upc price}}" }, { "kind": "Flatten", @@ -517,7 +517,7 @@ fn simplest_requires_with_local_sibling() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc price}}" + "operation": "{products{__typename upc price}}" }, { "kind": "Flatten", @@ -618,7 +618,7 @@ fn simple_requires() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc price weight}}" + "operation": "{products{__typename upc price weight}}" }, { "kind": "Flatten", @@ -727,7 +727,7 @@ fn two_fields_same_subgraph_same_requirement() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc price weight}}" + "operation": "{products{__typename upc price weight}}" }, { "kind": "Flatten", @@ -838,7 +838,7 @@ fn simple_requires_with_child() -> Result<(), Box> { "kind": "Fetch", "serviceName": "products", "operationKind": "query", - "operation": "query{products{__typename upc price weight}}" + "operation": "{products{__typename upc price weight}}" }, { "kind": "Flatten", @@ -970,7 +970,7 @@ fn keys_mashup() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{b{id a{__typename id compositeId{two three}}}}" + "operation": "{b{id a{__typename id compositeId{two three}}}}" }, { "kind": "Flatten", diff --git a/lib/query-planner/src/tests/requires_provides.rs b/lib/query-planner/src/tests/requires_provides.rs index cbc6cbb82..e32c1fc2b 100644 --- a/lib/query-planner/src/tests/requires_provides.rs +++ b/lib/query-planner/src/tests/requires_provides.rs @@ -93,7 +93,7 @@ fn simple_requires_provides() -> Result<(), Box> { "kind": "Fetch", "serviceName": "accounts", "operationKind": "query", - "operation": "query{me{__typename id}}" + "operation": "{me{__typename id}}" }, { "kind": "Flatten", diff --git a/lib/query-planner/src/tests/requires_requires.rs b/lib/query-planner/src/tests/requires_requires.rs index 413842bf4..529bc543c 100644 --- a/lib/query-planner/src/tests/requires_requires.rs +++ b/lib/query-planner/src/tests/requires_requires.rs @@ -77,7 +77,7 @@ fn one() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Flatten", @@ -229,7 +229,7 @@ fn one_with_one_local() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Flatten", @@ -381,7 +381,7 @@ fn two_fields_with_the_same_requirements() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Flatten", @@ -545,7 +545,7 @@ fn one_more() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id}}" + "operation": "{product{__typename id}}" }, { "kind": "Flatten", @@ -741,7 +741,7 @@ fn another_two_fields_with_the_same_requirements() -> Result<(), Box> "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id}}" + "operation": "{product{__typename id}}" }, { "kind": "Flatten", @@ -957,7 +957,7 @@ fn two_fields() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Parallel", @@ -1216,7 +1216,7 @@ fn two_fields_same_requirement_different_order() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Parallel", @@ -1484,7 +1484,7 @@ fn many() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{product{__typename id hasDiscount}}" + "operation": "{product{__typename id hasDiscount}}" }, { "kind": "Parallel", diff --git a/lib/query-planner/src/tests/root_types.rs b/lib/query-planner/src/tests/root_types.rs index 7de0267a3..a560a4d26 100644 --- a/lib/query-planner/src/tests/root_types.rs +++ b/lib/query-planner/src/tests/root_types.rs @@ -80,19 +80,19 @@ fn shared_root() -> Result<(), Box> { "kind": "Fetch", "serviceName": "price", "operationKind": "query", - "operation": "query{product{price{id amount currency}}}" + "operation": "{product{price{id amount currency}}}" }, { "kind": "Fetch", "serviceName": "category", "operationKind": "query", - "operation": "query{product{category{id name} id}}" + "operation": "{product{category{id name} id}}" }, { "kind": "Fetch", "serviceName": "name", "operationKind": "query", - "operation": "query{product{name{id brand model}}}" + "operation": "{product{name{id brand model}}}" } ] } From c5cc4125b138f8b70e7f2990d4f310027e29d051 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Thu, 20 Nov 2025 14:57:59 +0300 Subject: [PATCH 2/5] Apply suggestions --- lib/query-planner/src/ast/operation.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/query-planner/src/ast/operation.rs b/lib/query-planner/src/ast/operation.rs index fa83ef211..622c4b4e3 100644 --- a/lib/query-planner/src/ast/operation.rs +++ b/lib/query-planner/src/ast/operation.rs @@ -129,17 +129,12 @@ impl PrettyDisplay for SubgraphFetchOperation { impl Display for OperationDefinition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if (self.operation_kind.is_none() - || self - .operation_kind - .as_ref() - .is_none_or(|k| matches!(k, OperationKind::Query))) - && (self.name.is_none() || self.name.as_ref().is_none_or(|n| n.is_empty())) - && (self.variable_definitions.is_none() - || self - .variable_definitions - .as_ref() - .is_none_or(|v| v.is_empty())) + if self + .operation_kind + .as_ref() + .is_none_or(|k| matches!(k, OperationKind::Query)) + && self.name.as_deref().is_none_or(str::is_empty) + && self.variable_definitions.as_ref().is_none_or(Vec::is_empty) { // Short form for anonymous query return self.selection_set.fmt(f); From 3f3263ec40d07c6d8b49f38e299907a84660b221 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Thu, 20 Nov 2025 14:59:38 +0300 Subject: [PATCH 3/5] Improve style guide --- .changeset/extra-query-avoid.md | 2 ++ .gemini/styleguide.md | 1 + 2 files changed, 3 insertions(+) diff --git a/.changeset/extra-query-avoid.md b/.changeset/extra-query-avoid.md index fbd081b3f..ff2a6988e 100644 --- a/.changeset/extra-query-avoid.md +++ b/.changeset/extra-query-avoid.md @@ -1,5 +1,7 @@ --- hive-router-query-planner: patch +router: patch +node-addon: patch --- # Avoid extra `query` prefix for anonymous queries diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md index ef61cdb79..1bf1e1156 100644 --- a/.gemini/styleguide.md +++ b/.gemini/styleguide.md @@ -86,5 +86,6 @@ async fn handle(user: &User, req: &Request) -> Result { We are using `knope` with changesets for declaring changes. If you detect a new file in a PR under `.changeset/` directory, please confirm the following rules: - Every new `changesets` file that touches `query-planner` must have a `router` changeset - either in the same changeset or a separate changeset. +- Every new `changesets` file that touches `query-planner` must have a `node-addon` changeset - either in the same changeset or a separate changeset. - Every new `changesets` file that touches `executor` must have a `query-planner` changeset - either in the same changeset or a separate changeset. - If a PR touches `config` crate and adds/changes to the `HiveRouterConfig` struct, it must have a `router` changeset that contains a YAML example on how the configuration needs to be used. From 2c88229afa8b9864134a13c33cd50eab2bb0db32 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Thu, 20 Nov 2025 15:04:23 +0300 Subject: [PATCH 4/5] More snapshots --- lib/query-planner/src/ast/normalization/mod.rs | 4 ++-- lib/query-planner/src/tests/provides.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/query-planner/src/ast/normalization/mod.rs b/lib/query-planner/src/ast/normalization/mod.rs index d4861923e..8b36751a9 100644 --- a/lib/query-planner/src/ast/normalization/mod.rs +++ b/lib/query-planner/src/ast/normalization/mod.rs @@ -432,7 +432,7 @@ mod tests { .to_string() ), @r" - query { + { products { ... on Oven { id @@ -744,7 +744,7 @@ mod tests { .to_string() ), @r" - query { + { userFromA { profile { displayName diff --git a/lib/query-planner/src/tests/provides.rs b/lib/query-planner/src/tests/provides.rs index 1cd7ec3c8..ceac26623 100644 --- a/lib/query-planner/src/tests/provides.rs +++ b/lib/query-planner/src/tests/provides.rs @@ -273,7 +273,7 @@ fn provides_on_union() -> Result<(), Box> { "kind": "Fetch", "serviceName": "b", "operationKind": "query", - "operation": "query{media{__typename ...on Book{title id} ...on Movie{__typename id}}}" + "operation": "{media{__typename ...on Book{title id} ...on Movie{__typename id}}}" }, { "kind": "Flatten", From 728f3239e8a4cce5da05ed0f29d3a0c2cbde8d2d Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Thu, 20 Nov 2025 18:42:08 +0300 Subject: [PATCH 5/5] Final snapshot --- lib/query-planner/src/ast/normalization/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/query-planner/src/ast/normalization/mod.rs b/lib/query-planner/src/ast/normalization/mod.rs index 8b36751a9..55cb5daf2 100644 --- a/lib/query-planner/src/ast/normalization/mod.rs +++ b/lib/query-planner/src/ast/normalization/mod.rs @@ -477,7 +477,7 @@ mod tests { .to_string() ), @r" - query { + { toasters { id ... on Toaster {