Skip to content

Commit 073fc19

Browse files
fix: remove duplicate and fix __typename in Interface and Union (#3318)
1 parent 42bcfa3 commit 073fc19

18 files changed

+236
-70
lines changed

src/core/blueprint/index.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,14 @@ impl Index {
8787
if type_name == type_or_interface {
8888
return true;
8989
}
90-
9190
if let Some((Definition::Object(obj), _)) = self.map.get(type_name) {
92-
obj.implements.contains(type_or_interface)
91+
if obj.implements.contains(type_or_interface) {
92+
true
93+
} else if let Some((Definition::Union(union), _)) = self.map.get(type_or_interface) {
94+
union.types.contains(type_name)
95+
} else {
96+
false
97+
}
9398
} else {
9499
false
95100
}

src/core/jit/builder.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{HashMap, HashSet};
22
use std::ops::Deref;
33
use std::sync::Arc;
44

@@ -135,10 +135,22 @@ impl<'a> Builder<'a> {
135135
fragments: &HashMap<&str, &FragmentDefinition>,
136136
) -> Vec<Field<Value>> {
137137
let mut fields = vec![];
138+
let mut fragments_fields = vec![];
139+
let mut visited = HashSet::new();
138140

139141
for selection in &selection.items {
140142
match &selection.node {
141143
Selection::Field(Positioned { node: gql_field, .. }) => {
144+
let field_name = gql_field.name.node.as_str();
145+
let output_name = gql_field
146+
.alias
147+
.as_ref()
148+
.map(|a| a.node.as_str())
149+
.unwrap_or(field_name);
150+
if visited.contains(output_name) {
151+
continue;
152+
}
153+
visited.insert(output_name);
142154
let conditions = self.include(&gql_field.directives);
143155

144156
// Skip fields based on GraphQL's skip/include conditions
@@ -163,7 +175,6 @@ impl<'a> Builder<'a> {
163175
}
164176

165177
let (include, skip) = conditions.into_variable_tuple();
166-
let field_name = gql_field.name.node.as_str();
167178
let request_args = gql_field
168179
.arguments
169180
.iter()
@@ -229,11 +240,7 @@ impl<'a> Builder<'a> {
229240
selection: child_fields,
230241
parent_fragment,
231242
name: field_name.to_string(),
232-
output_name: gql_field
233-
.alias
234-
.as_ref()
235-
.map(|a| a.node.to_string())
236-
.unwrap_or(field_name.to_owned()),
243+
output_name: output_name.to_string(),
237244
ir,
238245
is_enum: self.index.type_is_enum(type_of.name()),
239246
type_of,
@@ -251,10 +258,10 @@ impl<'a> Builder<'a> {
251258
let typename_field = Field {
252259
id: FieldId::new(self.field_id.next()),
253260
name: field_name.to_string(),
254-
output_name: field_name.to_string(),
261+
output_name: output_name.to_string(),
255262
ir: None,
256263
type_of: Type::Named { name: "String".to_owned(), non_null: true },
257-
type_condition: None,
264+
type_condition: Some(type_condition.to_string()),
258265
skip,
259266
include,
260267
args: Vec::new(),
@@ -273,7 +280,7 @@ impl<'a> Builder<'a> {
273280
if let Some(fragment) =
274281
fragments.get(fragment_spread.fragment_name.node.as_str())
275282
{
276-
fields.extend(self.iter(
283+
fragments_fields.extend(self.iter(
277284
Some(fragment.type_condition.node.on.node.as_str()),
278285
&fragment.selection_set.node,
279286
fragment.type_condition.node.on.node.as_str(),
@@ -287,7 +294,7 @@ impl<'a> Builder<'a> {
287294
.as_ref()
288295
.map(|cond| cond.node.on.node.as_str())
289296
.unwrap_or(type_condition);
290-
fields.extend(self.iter(
297+
fragments_fields.extend(self.iter(
291298
Some(type_of),
292299
&fragment.selection_set.node,
293300
type_of,
@@ -296,7 +303,13 @@ impl<'a> Builder<'a> {
296303
}
297304
}
298305
}
299-
306+
for field in fragments_fields {
307+
if visited.contains(field.output_name.as_str()) {
308+
continue;
309+
}
310+
fields.push(field);
311+
}
312+
fields.sort_by(|a, b| a.id.cmp(&b.id));
300313
fields
301314
}
302315
#[inline(always)]

src/core/jit/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl ArgId {
150150
}
151151
}
152152

153-
#[derive(Clone, PartialEq, Eq, Hash)]
153+
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
154154
pub struct FieldId(usize);
155155

156156
impl Debug for FieldId {

src/core/jit/transform/graphql.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ fn format_selection_set<'a, A: 'a + Display + JsonLikeOwned>(
7878
let is_this_field_interface = interfaces.contains(field.type_of.name());
7979
let formatted_selection_fields =
8080
format_selection_field(field, &field_name, interfaces, is_this_field_interface);
81-
is_typename_requested = is_typename_requested || field_name == "__typename";
81+
is_typename_requested = is_typename_requested
82+
|| (field_name == "__typename" && field.parent_fragment.is_none());
8283
match &field.parent_fragment {
8384
Some(fragment) if is_parent_interface => {
8485
fragments_fields

tests/core/snapshots/auth-multiple-complex.md_0.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -15,12 +14,8 @@ snapshot_kind: text
1514
"__typename": "Dog",
1615
"bark": "woof"
1716
},
18-
{
19-
"__typename": "Cat"
20-
},
21-
{
22-
"__typename": "Bird"
23-
}
17+
{},
18+
{}
2419
]
2520
}
2621
}

tests/core/snapshots/auth-multiple-complex.md_1.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -11,16 +10,12 @@ snapshot_kind: text
1110
"body": {
1211
"data": {
1312
"animals": [
14-
{
15-
"__typename": "Dog"
16-
},
13+
{},
1714
{
1815
"__typename": "Cat",
1916
"meow": "meow"
2017
},
21-
{
22-
"__typename": "Bird"
23-
}
18+
{}
2419
]
2520
}
2621
}

tests/core/snapshots/auth-multiple-complex.md_2.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -11,12 +10,8 @@ snapshot_kind: text
1110
"body": {
1211
"data": {
1312
"animals": [
14-
{
15-
"__typename": "Dog"
16-
},
17-
{
18-
"__typename": "Cat"
19-
},
13+
{},
14+
{},
2015
{
2116
"__typename": "Bird",
2217
"tweet": "tweet"

tests/core/snapshots/auth-multiple-complex.md_3.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -11,12 +10,8 @@ snapshot_kind: text
1110
"body": {
1211
"data": {
1312
"animals": [
14-
{
15-
"__typename": "Dog"
16-
},
17-
{
18-
"__typename": "Cat"
19-
},
13+
{},
14+
{},
2015
{
2116
"__typename": "Bird",
2217
"tweet": "tweet"

tests/core/snapshots/auth-multiple-complex.md_4.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -15,12 +14,8 @@ snapshot_kind: text
1514
"__typename": "Dog",
1615
"bark": "woof"
1716
},
18-
{
19-
"__typename": "Cat"
20-
},
21-
{
22-
"__typename": "Bird"
23-
}
17+
{},
18+
{}
2419
]
2520
}
2621
}

tests/core/snapshots/auth-multiple-complex.md_5.snap

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
source: tests/core/spec.rs
33
expression: response
4-
snapshot_kind: text
54
---
65
{
76
"status": 200,
@@ -11,16 +10,12 @@ snapshot_kind: text
1110
"body": {
1211
"data": {
1312
"animals": [
14-
{
15-
"__typename": "Dog"
16-
},
13+
{},
1714
{
1815
"__typename": "Cat",
1916
"meow": "meow"
2017
},
21-
{
22-
"__typename": "Bird"
23-
}
18+
{}
2419
]
2520
}
2621
}

0 commit comments

Comments
 (0)