-
Notifications
You must be signed in to change notification settings - Fork 329
fix: Return root when parts of a query with deferred fragment #2188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8b8c8b9
994dac2
84e9d83
5f993b9
597fbc8
62a3fb7
73c24fb
405803c
02bdb78
0364c60
0563c78
f903ee5
ecb2dcb
93a7ec2
9b222bf
606dcbd
cdf1b03
3a1bc19
e794955
223bc97
20eeefe
b545775
643b547
7160516
ad1d075
0d0d385
2cd855c
1b679ee
ba258f9
6f928aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| --- | ||
| source: apollo-router/src/services/supergraph_service.rs | ||
| expression: stream.next_response().await.unwrap() | ||
| --- | ||
| { | ||
| "hasNext": false, | ||
| "incremental": [ | ||
| { | ||
| "data": { | ||
| "name": null | ||
| }, | ||
| "path": [ | ||
| "currentUser", | ||
| "activeOrganization", | ||
| "suborga", | ||
| 0 | ||
| ] | ||
| }, | ||
| { | ||
| "data": { | ||
| "name": "A" | ||
| }, | ||
| "path": [ | ||
| "currentUser", | ||
| "activeOrganization", | ||
| "suborga", | ||
| 1 | ||
| ] | ||
| }, | ||
| { | ||
| "data": { | ||
| "name": null | ||
| }, | ||
| "path": [ | ||
| "currentUser", | ||
| "activeOrganization", | ||
| "suborga", | ||
| 2 | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| --- | ||
| source: apollo-router/src/services/supergraph_service.rs | ||
| expression: res | ||
| --- | ||
| { | ||
| "data": { | ||
| "__typename": "Query", | ||
| "currentUser": { | ||
| "activeOrganization": { | ||
| "id": "0", | ||
| "suborga": [ | ||
| { | ||
| "id": "1" | ||
| }, | ||
| { | ||
| "id": "2" | ||
| }, | ||
| { | ||
| "id": "3" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| }, | ||
| "hasNext": true | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -106,7 +106,7 @@ impl Query { | |
| ) -> Vec<Path> { | ||
| let data = std::mem::take(&mut response.data); | ||
| if let Some(Value::Object(mut input)) = data { | ||
| let operation = self.operation(operation_name); | ||
| let original_operation = self.operation(operation_name); | ||
| if is_deferred { | ||
| if let Some(subselection) = &response.subselection { | ||
| // Get subselection from hashmap | ||
|
|
@@ -123,6 +123,19 @@ impl Query { | |
| errors: Vec::new(), | ||
| nullified: Vec::new(), | ||
| }; | ||
| // Detect if root __typename is asked in the original query (the qp doesn't put root __typename in subselections) | ||
| // cf https://github.com/apollographql/router/issues/1677 | ||
| let operation_kind_if_root_typename = | ||
bnjjj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| original_operation.and_then(|op| { | ||
| op.selection_set | ||
| .iter() | ||
| .any(|f| f.is_typename_field()) | ||
| .then(|| *op.kind()) | ||
| }); | ||
| if let Some(operation_kind) = operation_kind_if_root_typename { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should check that the defer fragment is at the root, right? if you have
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes Check the tests. I added a similar test |
||
| output.insert(TYPENAME, operation_kind.as_str().into()); | ||
| } | ||
|
|
||
| response.data = Some( | ||
| match self.apply_root_selection_set( | ||
| operation, | ||
|
|
@@ -151,7 +164,7 @@ impl Query { | |
| response.data = Some(Value::Object(Object::default())); | ||
| return vec![]; | ||
| } | ||
| } else if let Some(operation) = operation { | ||
| } else if let Some(operation) = original_operation { | ||
| let mut output = Object::default(); | ||
|
|
||
| let all_variables = if operation.variables.is_empty() { | ||
|
|
@@ -211,9 +224,8 @@ impl Query { | |
| schema: &Schema, | ||
| configuration: &Configuration, | ||
| ) -> Result<Self, SpecError> { | ||
| let string = query.into(); | ||
|
|
||
| let parser = apollo_parser::Parser::new(string.as_str()) | ||
| let query = query.into(); | ||
| let parser = apollo_parser::Parser::new(query.as_str()) | ||
| .recursion_limit(configuration.server.experimental_parser_recursion_limit); | ||
| let tree = parser.parse(); | ||
|
|
||
|
|
@@ -248,7 +260,7 @@ impl Query { | |
| .collect::<Result<Vec<_>, SpecError>>()?; | ||
|
|
||
| Ok(Query { | ||
| string, | ||
| string: query, | ||
| fragments, | ||
| operations, | ||
| subselections: HashMap::new(), | ||
|
|
@@ -1099,7 +1111,7 @@ impl Operation { | |
| && self | ||
| .selection_set | ||
| .get(0) | ||
| .map(|s| matches!(s, Selection::Field {name, ..} if name.as_str() == TYPENAME)) | ||
| .map(|s| s.is_typename_field()) | ||
| .unwrap_or_default() | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.