8000 Update metadata generation for Live Query in Relay compiler · facebook/relay@15a19e9 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 15a19e9

Browse files
Xiangxin Sunfacebook-github-bot
Xiangxin Sun
authored andcommitted
Update metadata generation for Live Query in Relay compiler
Reviewed By: tcr Differential Revision: D65232885 fbshipit-source-id: 1293cadedc41785c928d90062345156355005979
1 parent 2f69c02 commit 15a19e9

File tree

9 files changed

+155
-11
lines changed

9 files changed

+155
-11
lines changed

compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-implements-interface-non-interface.expected

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ interface IFoo {
3232
ℹ︎ the other type is defined here
3333

3434
<generated>:1:1
35-
Internal error: Unable to print source, start index (19518) out of range.
35+
Internal error: Unable to print source, start index (19563) out of range.

compiler/crates/relay-lsp/src/completion/test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ fn directive() {
429429
"skip",
430430
"fb_actor_change",
431431
"waterfall",
432+
"live",
432433
],
433434
);
434435
}
@@ -468,6 +469,7 @@ fn directive_on_scalar_field() {
468469
"skip",
469470
"fb_actor_change",
470471
"waterfall",
472+
"live",
471473
],
472474
);
473475
}
@@ -756,6 +758,7 @@ fn empty_directive() {
756758
"skip",
757759
"fb_actor_change",
758760
"waterfall",
761+
"live",
759762
],
760763
);
761764
}

compiler/crates/relay-test-schema/src/testschema.graphql

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ directive @credentials(
1414

1515
directive @live_query(polling_interval: Int, config_id: String) on QUERY
1616

17+
directive @live(config_id: String) on FIELD
18+
1719
directive @customDirective(level: Int!) on FIELD | FRAGMENT_SPREAD
1820

1921
directive @fixme_fat_interface on FIELD

compiler/crates/relay-transforms/src/generate_live_query_metadata.rs

+54-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
use std::str::FromStr;
9+
10+
use ::intern::string_key::StringKey;
811
use common::ArgumentName;
912
use common::Diagnostic;
1013
use common::DiagnosticsResult;
@@ -16,18 +19,21 @@ use graphql_ir::ConstantValue;
1619
use graphql_ir::OperationDefinition;
1720
use graphql_ir::OperationDefinitionName;
1821
use graphql_ir::Program;
22+
use graphql_ir::Selection;
1923
use graphql_ir::Transformed;
2024
use graphql_ir::Transformer;
2125
use graphql_ir::Value;
2226
use graphql_syntax::OperationKind;
2327
use intern::string_key::Intern;
28+
use itertools::Itertools;
2429
use lazy_static::lazy_static;
2530
use thiserror::Error;
2631

2732
use crate::create_metadata_directive;
2833

2934
lazy_static! {
3035
static ref LIVE_QUERY_DIRECTIVE_NAME: DirectiveName = DirectiveName("live_query".intern());
36+
static ref LIVE_DIRECTIVE_NAME: DirectiveName = DirectiveName("live".intern());
3137
static ref LIVE_METADATA_KEY: ArgumentName = ArgumentName("live".intern());
3238
static ref POLLING_INTERVAL_ARG: ArgumentName = ArgumentName("polling_interval".intern());
3339
static ref CONFIG_ID_ARG: ArgumentName = ArgumentName("config_id".intern());
@@ -62,6 +68,7 @@ impl Transformer for GenerateLiveQueryMetadata {
6268
) -> Transformed<OperationDefinition> {
6369
match operation.kind {
6470
OperationKind::Query => {
71+
let mut next_directives = operation.directives.clone();
6572
let live_query_directive = operation.directives.named(*LIVE_QUERY_DIRECTIVE_NAME);
6673
if let Some(live_query_directive) = live_query_directive {
6774
let polling_interval =
@@ -78,10 +85,16 @@ impl Transformer for GenerateLiveQueryMetadata {
7885
return Transformed::Keep;
7986
}
8087

81-
let mut next_directives = operation.directives.clone();
88+
if polling_interval.is_some() && config_id.is_some() {
89+
self.errors.push(Diagnostic::error(
90+
LiveQueryTransformValidationMessage::InvalidConfig {
91+
query_name: operation.name.item,
92+
},
93+
live_query_directive.location,
94+
));
95+
return Transformed::Keep;
96+
}
8297

83-
// I'm porting JS logic here. Not sure if the case where
84-
// polling_interval and config_id both provided handled correctly
8598
if let Some(polling_interval) = polling_interval {
8699
let poll_interval_value = match polling_interval.value.item {
87100
Value::Constant(ConstantValue::Int(value)) => value,
@@ -127,14 +140,41 @@ impl Transformer for GenerateLiveQueryMetadata {
127140
}]),
128141
));
129142
}
130-
131-
Transformed::Replace(OperationDefinition {
132-
directives: next_directives,
133-
..operation.clone()
134-
})
135143
} else {
136-
Transformed::Keep
144+
// Look for `@live` query root fields
145+
let live_directives = operation
146+
.selections
147+
.iter()
148+
.filter(|sel| !matches!(sel, Selection::Condition(_)))
149+
.filter_map(|sel| sel.directives().named(*LIVE_DIRECTIVE_NAME))
150+
.collect::<Vec<_>>();
151+
152+
if live_directives.is_empty() {
153+
return Transformed::Keep;
154+
}
155+
// We allow multiple `@live` selections in a query but don't allow multiple `config_id`s. Because
156+
// it confuses `method` header formation. `config_id` on `@live` is only used for `@live_query`
157+
// use case migration, which translates into exactly 1 `@live` selection.
158+
let config_id = live_directives
159+
.iter()
160+
.filter_map(|dir| dir.arguments.named(*CONFIG_ID_ARG))
161+
.at_most_one()
162+
.unwrap()
163+
.and_then(|arg| arg.value.item.get_string_literal())
164+
.unwrap_or_else(|| StringKey::from_str("").unwrap());
165+
166+
next_directives.push(create_metadata_directive(
167+
*LIVE_METADATA_KEY,
168+
ConstantValue::Object(vec![ConstantArgument {
169+
name: WithLocation::generated(*CONFIG_ID_ARG),
170+
value: WithLocation::generated(ConstantValue::String(config_id)),
171+
}]),
172+
));
137173
}
174+
Transformed::Replace(OperationDefinition {
175+
directives: next_directives,
176+
..operation.clone()
177+
})
138178
}
139179
_ => Transformed::Keep,
140180
}
@@ -149,6 +189,11 @@ enum LiveQueryTransformValidationMessage {
149189
)]
150190
MissingConfig { query_name: OperationDefinitionName },
151191

192+
#[error(
193+
"'polling_interval' and 'config_id' cannot both be present in @live_query for root field {query_name}"
194+
)]
195+
InvalidConfig { query_name: OperationDefinitionName },
196+
152197
#[error(
153198
"Expected the 'polling_interval' argument to @live_query to be a literal number for root field {query_name}"
154199
)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
==================================== INPUT ====================================
2+
query NodeQuery($id: ID!) {
3+
node(id: $id) @live {
4+
id
5+
... on User {
6+
birthdate {
7+
day
8+
month
9+
year
10+
}
11+
}
12+
}
13+
}
14+
==================================== OUTPUT ===================================
15+
query NodeQuery(
16+
$id: ID!
17+
) @__metadata(live: {config_id: ""}) {
18+
node(id: $id) @live {
19+
id
20+
... on User {
21+
birthdate {
22+
day
23+
month
24+
year
25+
}
26+
}
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
query NodeQuery($id: ID!) {
2+
node(id: $id) @live {
3+
id
4+
... on User {
5+
birthdate {
6+
day
7+
month
8+
year
9+
}
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
==================================== INPUT ====================================
2+
query NodeQuery($id: ID!) {
3+
node(id: $id) @live(config_id: "instrumentation_config_id") {
4+
id
5+
... on User {
6+
birthdate {
7+
day
8+
month
9+
year
10+
}
11+
}
12+
}
13+
}
14+
==================================== OUTPUT ===================================
15+
query NodeQuery(
16+
$id: ID!
17+
) @__metadata(live: {config_id: "instrumentation_config_id"}) {
18+
node(id: $id) @live(config_id: "instrumentation_config_id") {
19+
id
20+
... on User {
21+
birthdate {
22+
day
23+
month
24+
year
25+
}
26+
}
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
query NodeQuery($id: ID!) {
2+
node(id: $id) @live(config_id: "instrumentation_config_id") {
3+
id
4+
... on User {
5+
birthdate {
6+
day
7+
month
8+
year
9+
}
10+
}
11+
}
12+
}

compiler/crates/relay-transforms/tests/generate_live_query_metadata_test.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,28 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<bf0ee933ed7d251f881746f03c402397>>
7+
* @generated SignedSource<<c5b485781bb5c70ef55568195c695df1>>
88
*/
99

1010
mod generate_live_query_metadata;
1111

1212
use generate_live_query_metadata::transform_fixture;
1313
use fixture_tests::test_fixture;
1414

15+
#[tokio::test]
16+
async fn live_by_at_live() {
17+
let input = include_str!("generate_live_query_metadata/fixtures/live_by_at_live.graphql");
18+
let expected = include_str!("generate_live_query_metadata/fixtures/live_by_at_live.expected");
19+
test_fixture(transform_fixture, file!(), "live_by_at_live.graphql", "generate_live_query_metadata/fixtures/live_by_at_live.expected", input, expected).await;
20+
}
21+
22+
#[tokio::test]
23+
async fn live_by_at_live_config_id() {
24+
let input = include_str!("generate_live_query_metadata/fixtures/live_by_at_live_config_id.graphql");
25+
let expected = include_str!("generate_live_query_metadata/fixtures/live_by_at_live_config_id.expected");
26+
test_fixture(transform_fixture, file!(), "live_by_at_live_config_id.graphql", "generate_live_query_metadata/fixtures/live_by_at_live_config_id.expected", input, expected).await;
27+
}
28+
1529
#[tokio::test]
1630
async fn live_by_config_id() {
1731
let input = include_str!("generate_live_query_metadata/fixtures/live_by_config_id.graphql");

0 commit comments

Comments
 (0)
0