Skip to content

Commit 98373aa

Browse files
authored
Merge pull request #65 from tomhoule/release-0.2.0
Improve docs, examples, error struct and release 0.2
2 parents 8cf0694 + 87b0acd commit 98373aa

File tree

12 files changed

+122
-35
lines changed

12 files changed

+122
-35
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## Unreleased
99

10+
## [0.2.0] - 2018-07-22
11+
1012
### Added
1113

1214
- 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).
1315
- 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).
16+
- 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).
1417

1518
### Fixed
1619

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "graphql_client"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Tom Houlé <[email protected]>"]
55
description = "Typed GraphQL requests and responses"
66
repository = "https://github.com/tomhoule/graphql-client"
@@ -11,7 +11,7 @@ categories = ["network-programming", "web-programming", "wasm"]
1111
[dependencies]
1212
failure = "0.1"
1313
quote = "0.3"
14-
graphql_query_derive = {path = "./graphql_query_derive", version = "0.1.0"}
14+
graphql_query_derive = {path = "./graphql_query_derive", version = "0.2.0"}
1515
graphql-parser = "0.2.0"
1616
serde = "1.0"
1717
serde_derive = "1.0"

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# graphql_client
22

33
[![Build Status](https://travis-ci.org/tomhoule/graphql-client.svg?branch=master)](https://travis-ci.org/tomhoule/graphql-client)
4-
[![docs](https://docs.rs/graphql_client/badge.svg)](https://docs.rs/graphql_client/0.1.0/graphql_client/)
4+
[![docs](https://docs.rs/graphql_client/badge.svg)](https://docs.rs/graphql_client/0.2.0/graphql_client/)
55
[![crates.io](https://img.shields.io/crates/v/graphql_client.svg)](https://crates.io/crates/graphql_client)
66

77
A typed GraphQL client library for Rust.
@@ -11,6 +11,8 @@ A typed GraphQL client library for Rust.
1111
- Precise types for query variables and responses
1212
- Supports GraphQL fragments, objects, unions, inputs, enums, custom scalars and input objects
1313
- Works in the browser (WebAssembly)
14+
- Subscriptions support (serialization-deserialization only at the moment)
15+
- Copies documentation from the GraphQL schema to the generated Rust code
1416

1517
## Getting started
1618

examples/call_from_js/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ lto = "thin"
1010
crate-type = ["cdylib"]
1111

1212
[dependencies]
13-
graphql_client = { path = "../..", version = "0.1.0" }
14-
wasm-bindgen = "0.2.11"
13+
graphql_client = { path = "../..", version = "0.2.0" }
14+
wasm-bindgen = "0.2.12"
1515
serde = "1.0.67"
1616
serde_derive = "1.0.67"
1717
serde_json = "1.0.22"

examples/call_from_js/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
1+
#![feature(wasm_custom_section, wasm_import_module, use_extern_macros)]
22

33
#[macro_use]
44
extern crate graphql_client;
@@ -18,7 +18,10 @@ use wasm_bindgen::prelude::*;
1818
use graphql_client::*;
1919

2020
#[derive(GraphQLQuery)]
21-
#[graphql(schema_path = "schema.json", query_path = "src/puppy_smiles.graphql")]
21+
#[graphql(
22+
schema_path = "schema.json",
23+
query_path = "src/puppy_smiles.graphql"
24+
)]
2225
struct PuppySmiles;
2326

2427
#[wasm_bindgen]

examples/github/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ prettytable-rs = "0.7.0"
1414
structopt = "0.2.10"
1515
dotenv = "0.13.0"
1616
envy = "0.3.2"
17+
log = "0.4.3"
18+
env_logger = "0.5.10"

examples/github/src/main.rs

+14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ extern crate envy;
44
extern crate failure;
55
#[macro_use]
66
extern crate graphql_client;
7+
#[macro_use]
8+
extern crate log;
9+
extern crate env_logger;
710
extern crate reqwest;
811
extern crate serde;
912
extern crate serde_json;
@@ -45,6 +48,7 @@ fn parse_repo_name(repo_name: &str) -> Result<(&str, &str), failure::Error> {
4548

4649
fn main() -> Result<(), failure::Error> {
4750
dotenv::dotenv().ok();
51+
env_logger::init();
4852

4953
let config: Env = envy::from_env()?;
5054

@@ -70,6 +74,16 @@ fn main() -> Result<(), failure::Error> {
7074
.send()?;
7175

7276
let response_body: GraphQLResponse<query1::ResponseData> = res.json()?;
77+
info!("{:?}", response_body);
78+
79+
if let Some(errors) = response_body.errors {
80+
println!("there are errors:");
81+
82+
for error in &errors {
83+
println!("{:?}", error);
84+
}
85+
}
86+
7387
let response_data: query1::ResponseData = response_body.data.expect("missing response data");
7488

7589
let stars: Option<i64> = response_data

graphql_client_cli/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "graphql_client_cli"
33
description = "The CLI for graphql-client (WIP)"
4-
version = "0.1.0"
4+
version = "0.2.0"
55
authors = ["Tom Houlé <[email protected]>"]
66
license = "Apache-2.0 OR MIT"
77

@@ -12,7 +12,7 @@ path = "src/main.rs"
1212
[dependencies]
1313
failure = "0.1"
1414
reqwest = "0.8"
15-
graphql_client = { version = "0.1.0", path = ".." }
15+
graphql_client = { version = "0.2.0", path = ".." }
1616
structopt = "0.2"
1717
serde = "1.0"
1818
serde_derive = "1.0"

graphql_query_derive/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "graphql_query_derive"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Tom Houlé <[email protected]>"]
55
description = "Utility crate for graphql_client"
66
license = "Apache-2.0 OR MIT"
@@ -13,7 +13,7 @@ proc-macro = true
1313
failure = "0.1"
1414
quote = "^0.6"
1515
syn = "0.14"
16-
proc-macro2 = { version = "0.4" }
16+
proc-macro2 = { version = "0.4", features = [] }
1717
serde = "1.0"
1818
serde_derive = "1.0"
1919
serde_json = "1.0"

graphql_query_derive/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ mod inputs;
2424
mod interfaces;
2525
mod introspection_response;
2626
mod objects;
27-
mod operations;
2827
mod query;
2928
mod scalars;
3029
mod schema;

graphql_query_derive/src/operations.rs

-21
This file was deleted.

src/lib.rs

+87-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
//! The top-level documentation resides on the [project README](https://github.com/tomhoule/graphql-client) at the moment.
2+
//!
3+
//! The main interface to this library is the custom derive that generates modules from a GraphQL query and schema.
24
35
extern crate serde;
46
#[macro_use]
57
extern crate serde_derive;
68
#[macro_use]
79
extern crate graphql_query_derive;
810

11+
#[cfg(test)]
12+
#[macro_use]
13+
extern crate serde_json;
14+
915
#[doc(hidden)]
1016
pub use graphql_query_derive::*;
1117

@@ -27,16 +33,95 @@ where
2733
pub query: &'static str,
2834
}
2935

30-
#[derive(Debug, Serialize, Deserialize)]
36+
#[derive(Debug, Serialize, Deserialize, PartialEq)]
37+
pub struct Location {
38+
line: i32,
39+
column: i32,
40+
}
41+
42+
#[derive(Debug, Serialize, Deserialize, PartialEq)]
43+
#[serde(untagged)]
44+
pub enum PathFragment {
45+
Key(String),
46+
Index(i32),
47+
}
48+
49+
/// An element in the top-level `errors` array of a response body.
50+
///
51+
/// This tries to be as close to the spec as possible.
52+
///
53+
/// Spec: [https://github.com/facebook/graphql/blob/master/spec/Section%207%20--%20Response.md]
54+
#[derive(Debug, Serialize, Deserialize, PartialEq)]
3155
pub struct GraphQLError {
32-
pub path: String,
56+
pub message: String,
57+
pub locations: Option<Vec<Location>>,
58+
pub path: Option<Vec<PathFragment>>,
3359
}
3460

3561
/// The generic shape taken by the responses of GraphQL APIs.
3662
///
3763
/// This will generally be used with the `ResponseData` struct from a derived module.
64+
///
65+
/// Spec: [https://github.com/facebook/graphql/blob/master/spec/Section%207%20--%20Response.md]
3866
#[derive(Debug, Serialize, Deserialize)]
3967
pub struct GraphQLResponse<Data> {
4068
pub data: Option<Data>,
4169
pub errors: Option<Vec<GraphQLError>>,
4270
}
71+
72+
#[cfg(test)]
73+
mod tests {
74+
use super::*;
75+
76+
#[test]
77+
fn graphql_error_works_with_just_message() {
78+
let err = json!({
79+
"message": "I accidentally your whole query"
80+
});
81+
82+
let deserialized_error: GraphQLError = serde_json::from_value(err).unwrap();
83+
84+
assert_eq!(
85+
deserialized_error,
86+
GraphQLError {
87+
message: "I accidentally your whole query".to_string(),
88+
locations: None,
89+
path: None,
90+
}
91+
)
92+
}
93+
94+
#[test]
95+
fn full_graphql_error_deserialization() {
96+
let err = json!({
97+
"message": "I accidentally your whole query",
98+
"locations": [{ "line": 3, "column": 13}, {"line": 56, "column": 1}],
99+
"path": ["home", "alone", 3, "rating"]
100+
});
101+
102+
let deserialized_error: GraphQLError = serde_json::from_value(err).unwrap();
103+
104+
assert_eq!(
105+
deserialized_error,
106+
GraphQLError {
107+
message: "I accidentally your whole query".to_string(),
108+
locations: Some(vec![
109+
Location {
110+
line: 3,
111+
column: 13,
112+
},
113+
Location {
114+
line: 56,
115+
column: 1,
116+
},
117+
]),
118+
path: Some(vec![
119+
PathFragment::Key("home".to_owned()),
120+
PathFragment::Key("alone".to_owned()),
121+
PathFragment::Index(3),
122+
PathFragment::Key("rating".to_owned()),
123+
]),
124+
}
125+
)
126+
}
127+
}

0 commit comments

Comments
 (0)