Skip to content

Commit 108e49c

Browse files
authored
Merge pull request #6 from tomhoule/unions
Implement a local type for query selections
2 parents 5ddd29e + 8b05463 commit 108e49c

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed

graphql_query_derive/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ mod introspection_response;
2525
mod objects;
2626
mod query;
2727
mod schema;
28+
mod selection;
2829
mod shared;
2930
mod unions;
3031

graphql_query_derive/src/query.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ impl QueryContext {
2727
}
2828
}
2929

30+
/// For testing only. creates an empty QueryContext with an empty Schema.
31+
#[cfg(test)]
32+
pub fn new_empty() -> QueryContext {
33+
QueryContext {
34+
_subscription_root: None,
35+
fragments: BTreeMap::new(),
36+
mutation_root: None,
37+
query_root: None,
38+
schema: Schema::new(),
39+
variables: BTreeMap::new(),
40+
}
41+
}
42+
3043
pub fn maybe_expand_field(
3144
&self,
3245
field: &query::Field,

graphql_query_derive/src/selection.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use graphql_parser::query::SelectionSet;
2+
3+
#[derive(Debug, PartialEq)]
4+
pub struct SelectionField {
5+
name: String,
6+
fields: Selection,
7+
}
8+
9+
#[derive(Debug, PartialEq)]
10+
pub struct SelectionFragmentSpread {
11+
fragment_name: String,
12+
}
13+
14+
#[derive(Debug, PartialEq)]
15+
pub struct SelectionInlineFragment {
16+
on: String,
17+
fields: Selection,
18+
}
19+
20+
#[derive(Debug, PartialEq)]
21+
pub enum SelectionItem {
22+
Field(SelectionField),
23+
FragmentSpread(SelectionFragmentSpread),
24+
InlineFragment(SelectionInlineFragment),
25+
}
26+
27+
#[derive(Debug, PartialEq)]
28+
pub struct Selection(Vec<SelectionItem>);
29+
30+
impl<'a> ::std::convert::From<&'a SelectionSet> for Selection {
31+
fn from(selection_set: &SelectionSet) -> Selection {
32+
use graphql_parser::query::Selection;
33+
34+
let mut items = Vec::new();
35+
36+
for item in selection_set.items.iter() {
37+
let converted = match item {
38+
Selection::Field(f) => SelectionItem::Field(SelectionField {
39+
name: f.name.to_string(),
40+
fields: (&f.selection_set).into(),
41+
}),
42+
Selection::FragmentSpread(spread) => {
43+
SelectionItem::FragmentSpread(SelectionFragmentSpread {
44+
fragment_name: spread.fragment_name.to_string(),
45+
})
46+
}
47+
Selection::InlineFragment(inline) => {
48+
SelectionItem::InlineFragment(SelectionInlineFragment {
49+
on: inline
50+
.type_condition
51+
.clone()
52+
.expect("missing \"on\" clause")
53+
.to_string()
54+
.replace("on ", ""),
55+
fields: (&inline.selection_set).into(),
56+
})
57+
}
58+
};
59+
items.push(converted);
60+
}
61+
62+
Selection(items)
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use super::*;
69+
use graphql_parser;
70+
71+
#[test]
72+
fn selection_from_graphql_parser_selection_set() {
73+
let query = r##"
74+
query {
75+
animal {
76+
isCat
77+
isHorse
78+
...Timestamps
79+
barks
80+
...on Dog {
81+
rating
82+
}
83+
pawsCount
84+
}
85+
}
86+
"##;
87+
let parsed = graphql_parser::parse_query(query).unwrap();
88+
let selection_set: &graphql_parser::query::SelectionSet = parsed
89+
.definitions
90+
.iter()
91+
.filter_map(|def| {
92+
if let graphql_parser::query::Definition::Operation(
93+
graphql_parser::query::OperationDefinition::Query(q),
94+
) = def
95+
{
96+
Some(&q.selection_set)
97+
} else {
98+
None
99+
}
100+
})
101+
.next()
102+
.unwrap();
103+
104+
let selection: Selection = selection_set.into();
105+
106+
assert_eq!(
107+
selection,
108+
Selection(vec![SelectionItem::Field(SelectionField {
109+
name: "animal".to_string(),
110+
fields: Selection(vec![
111+
SelectionItem::Field(SelectionField {
112+
name: "isCat".to_string(),
113+
fields: Selection(Vec::new()),
114+
}),
115+
SelectionItem::Field(SelectionField {
116+
name: "isHorse".to_string(),
117+
fields: Selection(Vec::new()),
118+
}),
119+
SelectionItem::FragmentSpread(SelectionFragmentSpread {
120+
fragment_name: "Timestamps".to_string(),
121+
}),
122+
SelectionItem::Field(SelectionField {
123+
name: "barks".to_string(),
124+
fields: Selection(Vec::new()),
125+
}),
126+
SelectionItem::InlineFragment(SelectionInlineFragment {
127+
on: "Dog".to_string(),
128+
fields: Selection(vec![
129+
SelectionItem::Field(SelectionField {
130+
name: "rating".to_string(),
131+
fields: Selection(Vec::new()),
132+
}),
133+
]),
134+
}),
135+
SelectionItem::Field(SelectionField {
136+
name: "pawsCount".to_string(),
137+
fields: Selection(Vec::new()),
138+
}),
139+
]),
140+
})])
141+
);
142+
}
143+
}

graphql_query_derive/src/unions.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,13 @@ impl GqlUnion {
1616
unimplemented!("union generation")
1717
}
1818
}
19+
20+
#[cfg(test)]
21+
mod tests {
22+
23+
#[test]
24+
fn union_response_for_selection_works() {
25+
// unimplemented!()
26+
}
27+
28+
}

0 commit comments

Comments
 (0)