Skip to content

Commit db63a99

Browse files
authored
Merge pull request #308 from graphql-rust/schema-graph
Refactor schema representation and code generation
2 parents 5cb21f3 + c902970 commit db63a99

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3684
-3545
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,10 @@ There are a number of breaking changes due to the new features, read the `Added`
258258

259259
### Added
260260

261-
- Copy documentation from the GraphQL schema to the generated types (including their fields) as normal Rust documentation. Documentation will show up in the generated docs as well as IDEs that support expanding derive macros (which does not include the RLS yet).
261+
- Copy documentation from the GraphQL schema to the generated types (including
262+
their fields) as normal Rust documentation. Documentation will show up in the
263+
generated docs as well as IDEs that support expanding derive macros (which
264+
does not include the RLS yet).
262265
- Implement and test deserializing subscription responses. We also try to provide helpful error messages when a subscription query is not valid (i.e. when it has more than one top-level field).
263266
- Support the [new top-level errors shape from the June 2018 spec](https://github.com/facebook/graphql/blob/master/spec/Section%207%20--%20Response.md), except for the `extensions` field (see issue #64).
264267

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ A typed GraphQL client library for Rust.
5959

6060
```rust
6161
use graphql_client::{GraphQLQuery, Response};
62+
use std::error::Error;
6263

6364
#[derive(GraphQLQuery)]
6465
#[graphql(
@@ -68,7 +69,7 @@ A typed GraphQL client library for Rust.
6869
)]
6970
pub struct UnionQuery;
7071

71-
fn perform_my_query(variables: union_query::Variables) -> Result<(), anyhow::Error> {
72+
fn perform_my_query(variables: union_query::Variables) -> Result<(), Box<dyn Error>> {
7273

7374
// this is the important line
7475
let request_body = UnionQuery::build_query(variables);

examples/github/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ authors = ["Tom Houlé <[email protected]>"]
55
edition = "2018"
66

77
[dev-dependencies]
8-
anyhow = "*"
8+
anyhow = "1.0"
99
graphql_client = { path = "../../graphql_client" }
1010
serde = "^1.0"
1111
reqwest = "^0.9"

examples/hasura/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ authors = ["Mark Catley <[email protected]>"]
55
edition = "2018"
66

77
[dev-dependencies]
8-
anyhow = "*"
8+
anyhow = "1.0"
99
graphql_client = { path = "../../graphql_client" }
1010
serde = "1.0"
1111
serde_derive = "1.0"

graphql-introspection-query/src/introspection_response.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'de> Deserialize<'de> for __DirectiveLocation {
7878
}
7979
}
8080

81-
#[derive(Clone, Debug)]
81+
#[derive(Clone, Debug, PartialEq)]
8282
pub enum __TypeKind {
8383
SCALAR,
8484
OBJECT,
@@ -130,11 +130,11 @@ pub struct FullType {
130130
pub kind: Option<__TypeKind>,
131131
pub name: Option<String>,
132132
pub description: Option<String>,
133-
pub fields: Option<Vec<Option<FullTypeFields>>>,
134-
pub input_fields: Option<Vec<Option<FullTypeInputFields>>>,
135-
pub interfaces: Option<Vec<Option<FullTypeInterfaces>>>,
136-
pub enum_values: Option<Vec<Option<FullTypeEnumValues>>>,
137-
pub possible_types: Option<Vec<Option<FullTypePossibleTypes>>>,
133+
pub fields: Option<Vec<FullTypeFields>>,
134+
pub input_fields: Option<Vec<FullTypeInputFields>>,
135+
pub interfaces: Option<Vec<FullTypeInterfaces>>,
136+
pub enum_values: Option<Vec<FullTypeEnumValues>>,
137+
pub possible_types: Option<Vec<FullTypePossibleTypes>>,
138138
}
139139

140140
#[derive(Clone, Debug, Deserialize)]
@@ -196,19 +196,14 @@ pub struct FullTypePossibleTypes {
196196
#[derive(Clone, Debug, Deserialize)]
197197
#[serde(rename_all = "camelCase")]
198198
pub struct InputValue {
199-
pub name: Option<String>,
199+
pub name: String,
200200
pub description: Option<String>,
201201
#[serde(rename = "type")]
202-
pub type_: Option<InputValueType>,
202+
pub type_: InputValueType,
203203
pub default_value: Option<String>,
204204
}
205205

206-
#[derive(Clone, Debug, Deserialize)]
207-
#[serde(rename_all = "camelCase")]
208-
pub struct InputValueType {
209-
#[serde(flatten)]
210-
pub type_ref: TypeRef,
211-
}
206+
type InputValueType = TypeRef;
212207

213208
#[derive(Clone, Debug, Deserialize)]
214209
#[serde(rename_all = "camelCase")]

graphql_client/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ doc_comment::doctest!("../../README.md");
3131
/// ```
3232
/// use graphql_client::*;
3333
/// use serde_json::json;
34+
/// use std::error::Error;
3435
///
3536
/// #[derive(GraphQLQuery)]
3637
/// #[graphql(
@@ -39,7 +40,7 @@ doc_comment::doctest!("../../README.md");
3940
/// )]
4041
/// struct StarWarsQuery;
4142
///
42-
/// fn main() -> Result<(), anyhow::Error> {
43+
/// fn main() -> Result<(), Box<dyn Error>> {
4344
/// use graphql_client::GraphQLQuery;
4445
///
4546
/// let variables = star_wars_query::Variables {
@@ -124,13 +125,14 @@ impl Display for PathFragment {
124125
/// # use serde_json::json;
125126
/// # use serde::Deserialize;
126127
/// # use graphql_client::GraphQLQuery;
128+
/// # use std::error::Error;
127129
/// #
128130
/// # #[derive(Debug, Deserialize, PartialEq)]
129131
/// # struct ResponseData {
130132
/// # something: i32
131133
/// # }
132134
/// #
133-
/// # fn main() -> Result<(), anyhow::Error> {
135+
/// # fn main() -> Result<(), Box<dyn Error>> {
134136
/// use graphql_client::*;
135137
///
136138
/// let body: Response<ResponseData> = serde_json::from_value(json!({
@@ -230,6 +232,7 @@ impl Display for Error {
230232
/// # use serde_json::json;
231233
/// # use serde::Deserialize;
232234
/// # use graphql_client::GraphQLQuery;
235+
/// # use std::error::Error;
233236
/// #
234237
/// # #[derive(Debug, Deserialize, PartialEq)]
235238
/// # struct User {
@@ -247,7 +250,7 @@ impl Display for Error {
247250
/// # dogs: Vec<Dog>,
248251
/// # }
249252
/// #
250-
/// # fn main() -> Result<(), anyhow::Error> {
253+
/// # fn main() -> Result<(), Box<dyn Error>> {
251254
/// use graphql_client::Response;
252255
///
253256
/// let body: Response<ResponseData> = serde_json::from_value(json!({

graphql_client/tests/fragments.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,7 @@ fn fragment_reference() {
2424
let valid_fragment_reference =
2525
serde_json::from_value::<fragment_reference::ResponseData>(valid_response).unwrap();
2626

27-
assert_eq!(
28-
valid_fragment_reference
29-
.fragment_reference
30-
.in_fragment
31-
.unwrap(),
32-
"value"
33-
);
27+
assert_eq!(valid_fragment_reference.in_fragment.unwrap(), "value");
3428
}
3529

3630
#[test]
@@ -42,13 +36,7 @@ fn fragments_with_snake_case_name() {
4236
let valid_fragment_reference =
4337
serde_json::from_value::<snake_case_fragment::ResponseData>(valid_response).unwrap();
4438

45-
assert_eq!(
46-
valid_fragment_reference
47-
.snake_case_fragment
48-
.in_fragment
49-
.unwrap(),
50-
"value"
51-
);
39+
assert_eq!(valid_fragment_reference.in_fragment.unwrap(), "value");
5240
}
5341

5442
#[derive(GraphQLQuery)]
@@ -64,11 +52,9 @@ fn recursive_fragment() {
6452

6553
let _ = RecursiveFragment {
6654
head: Some("ABCD".to_string()),
67-
tail: Some(RecursiveFragmentTail {
68-
recursive_fragment: Box::new(RecursiveFragment {
69-
head: Some("EFGH".to_string()),
70-
tail: None,
71-
}),
72-
}),
55+
tail: Some(Box::new(RecursiveFragment {
56+
head: Some("EFGH".to_string()),
57+
tail: None,
58+
})),
7359
};
7460
}

graphql_client/tests/input_object_variables.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ fn input_object_variables_default() {
3939
msg: default_input_object_variables_query::Variables::default_msg(),
4040
};
4141

42-
let out = serde_json::to_string(&variables).unwrap();
42+
let out = serde_json::to_value(&variables).unwrap();
4343

44-
assert_eq!(
45-
out,
46-
r#"{"msg":{"content":null,"to":{"category":null,"email":"[email protected]","name":null}}}"#,
47-
);
44+
let expected_default = serde_json::json!({
45+
"msg":{"content":null,"to":{"category":null,"email":"[email protected]","name":null}}
46+
});
47+
48+
assert_eq!(out, expected_default);
4849
}
4950

5051
#[derive(GraphQLQuery)]

graphql_client/tests/interfaces/interface_with_type_refining_fragment_query.graphql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fragment Birthday on Person {
1+
fragment BirthdayFragment on Person {
22
birthday
33
}
44

@@ -9,7 +9,7 @@ query QueryOnInterface {
99
... on Dog {
1010
isGoodDog
1111
}
12-
...Birthday
12+
...BirthdayFragment
1313
... on Organization {
1414
industry
1515
}

graphql_client/tests/union_query.rs

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use graphql_client::*;
22

33
const RESPONSE: &str = include_str!("unions/union_query_response.json");
4+
const FRAGMENT_AND_MORE_RESPONSE: &str = include_str!("unions/fragment_and_more_response.json");
45

56
#[derive(GraphQLQuery)]
67
#[graphql(
@@ -18,6 +19,14 @@ pub struct UnionQuery;
1819
)]
1920
pub struct FragmentOnUnion;
2021

22+
#[derive(GraphQLQuery)]
23+
#[graphql(
24+
query_path = "tests/unions/union_query.graphql",
25+
schema_path = "tests/unions/union_schema.graphql",
26+
response_derives = "PartialEq, Debug"
27+
)]
28+
pub struct FragmentAndMoreOnUnion;
29+
2130
#[test]
2231
fn union_query_deserialization() {
2332
let response_data: union_query::ResponseData = serde_json::from_str(RESPONSE).unwrap();
@@ -53,26 +62,63 @@ fn fragment_on_union() {
5362

5463
let expected = fragment_on_union::ResponseData {
5564
names: Some(vec![
56-
fragment_on_union::FragmentOnUnionNames::Person(
57-
fragment_on_union::FragmentOnUnionNamesOnPerson {
58-
first_name: "Audrey".to_string(),
59-
},
60-
),
61-
fragment_on_union::FragmentOnUnionNames::Dog(
62-
fragment_on_union::FragmentOnUnionNamesOnDog {
63-
name: "Laïka".to_string(),
64-
},
65-
),
66-
fragment_on_union::FragmentOnUnionNames::Organization(
67-
fragment_on_union::FragmentOnUnionNamesOnOrganization {
65+
fragment_on_union::NamesFragment::Person(fragment_on_union::NamesFragmentOnPerson {
66+
first_name: "Audrey".to_string(),
67+
}),
68+
fragment_on_union::NamesFragment::Dog(fragment_on_union::NamesFragmentOnDog {
69+
name: "Laïka".to_string(),
70+
}),
71+
fragment_on_union::NamesFragment::Organization(
72+
fragment_on_union::NamesFragmentOnOrganization {
6873
title: "Mozilla".to_string(),
6974
},
7075
),
71-
fragment_on_union::FragmentOnUnionNames::Dog(
72-
fragment_on_union::FragmentOnUnionNamesOnDog {
73-
name: "Norbert".to_string(),
74-
},
75-
),
76+
fragment_on_union::NamesFragment::Dog(fragment_on_union::NamesFragmentOnDog {
77+
name: "Norbert".to_string(),
78+
}),
79+
]),
80+
};
81+
82+
assert_eq!(response_data, expected);
83+
}
84+
85+
#[test]
86+
fn fragment_and_more_on_union() {
87+
use fragment_and_more_on_union::*;
88+
89+
let response_data: fragment_and_more_on_union::ResponseData =
90+
serde_json::from_str(FRAGMENT_AND_MORE_RESPONSE).unwrap();
91+
92+
let expected = fragment_and_more_on_union::ResponseData {
93+
names: Some(vec![
94+
FragmentAndMoreOnUnionNames {
95+
names_fragment: NamesFragment::Person(NamesFragmentOnPerson {
96+
first_name: "Larry".into(),
97+
}),
98+
on: FragmentAndMoreOnUnionNamesOn::Person,
99+
},
100+
FragmentAndMoreOnUnionNames {
101+
names_fragment: NamesFragment::Dog(NamesFragmentOnDog {
102+
name: "Laïka".into(),
103+
}),
104+
on: FragmentAndMoreOnUnionNamesOn::Dog(FragmentAndMoreOnUnionNamesOnDog {
105+
is_good_dog: true,
106+
}),
107+
},
108+
FragmentAndMoreOnUnionNames {
109+
names_fragment: NamesFragment::Organization(NamesFragmentOnOrganization {
110+
title: "Mozilla".into(),
111+
}),
112+
on: FragmentAndMoreOnUnionNamesOn::Organization,
113+
},
114+
FragmentAndMoreOnUnionNames {
115+
names_fragment: NamesFragment::Dog(NamesFragmentOnDog {
116+
name: "Norbert".into(),
117+
}),
118+
on: FragmentAndMoreOnUnionNamesOn::Dog(FragmentAndMoreOnUnionNamesOnDog {
119+
is_good_dog: true,
120+
}),
121+
},
76122
]),
77123
};
78124

0 commit comments

Comments
 (0)