Skip to content

Commit 4e7fc79

Browse files
committed
Add support for the canonical introspection schema
Fixes graphql-rust#307. Add support for introspection
1 parent 40319d9 commit 4e7fc79

File tree

13 files changed

+2825
-21
lines changed

13 files changed

+2825
-21
lines changed

docs/book/content/SUMMARY.md

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@
22
- [Quickstart](quickstart.md)
33

44
- [Type System](types/index.md)
5-
- [Defining objects](types/objects/defining_objects.md)
6-
- [Complex fields](types/objects/complex_fields.md)
7-
- [Using contexts](types/objects/using_contexts.md)
8-
- [Error handling](types/objects/error_handling.md)
9-
- [Other types](types/other-index.md)
10-
- [Enums](types/enums.md)
11-
- [Interfaces](types/interfaces.md)
12-
- [Input objects](types/input_objects.md)
13-
- [Scalars](types/scalars.md)
14-
- [Unions](types/unions.md)
5+
6+
- [Defining objects](types/objects/defining_objects.md)
7+
- [Complex fields](types/objects/complex_fields.md)
8+
- [Using contexts](types/objects/using_contexts.md)
9+
- [Error handling](types/objects/error_handling.md)
10+
- [Other types](types/other-index.md)
11+
- [Enums](types/enums.md)
12+
- [Interfaces](types/interfaces.md)
13+
- [Input objects](types/input_objects.md)
14+
- [Scalars](types/scalars.md)
15+
- [Unions](types/unions.md)
1516

1617
- [Schemas and mutations](schema/schemas_and_mutations.md)
1718

1819
- [Adding A Server](servers/index.md)
20+
1921
- [Official Server Integrations](servers/official.md) - [Hyper](servers/hyper.md)
2022
- [Warp](servers/warp.md)
2123
- [Rocket](servers/rocket.md)
@@ -24,8 +26,12 @@
2426
- [Third Party Integrations](servers/third-party.md)
2527

2628
- [Advanced Topics](advanced/index.md)
27-
- [Non-struct objects](advanced/non_struct_objects.md)
28-
- [Objects and generics](advanced/objects_and_generics.md)
29-
- [Multiple operations per request](advanced/multiple_ops_per_request.md)
29+
30+
- [Introspection](advanced/introspection.md)
31+
- [Non-struct objects](advanced/non_struct_objects.md)
32+
- [Objects and generics](advanced/objects_and_generics.md)
33+
- [Multiple operations per request](advanced/multiple_ops_per_request.md)
34+
3035
# - [Context switching]
36+
3137
# - [Dynamic type system]

docs/book/content/advanced/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
The chapters below cover some more advanced scenarios.
44

5+
- [Introspection](advanced/introspection.md)
56
- [Non-struct objects](advanced/non_struct_objects.md)
67
- [Objects and generics](advanced/objects_and_generics.md)
78
- [Multiple operations per request](advanced/multiple_ops_per_request.md)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Introspection
2+
3+
GraphQL defines a special built-in top-level field called `__schema`. Querying
4+
for this field allows one to [inspect the schema](https://graphql.org/learn/introspection/)
5+
at runtime to see what queries and mutations the GraphQL server supports.
6+
7+
Because inspection queries are just regular GraphQL queries, Juniper supports
8+
them natively. For example, to get all the names of the types supported one
9+
could execute the following query against Juniper:
10+
11+
```graphql
12+
{
13+
__schema {
14+
types {
15+
name
16+
}
17+
}
18+
}
19+
```
20+
21+
## Schema introspection output as JSON
22+
23+
Many client libraries and tools in the GraphQL ecosystem require a complete
24+
representation of the server schema. Often this representation is in JSON and
25+
referred to as `schema.json`. A complete representation of the schema can be
26+
produced by issuing a specially crafted introspection query.
27+
28+
Juniper provides a convenience function to inspect the entire schema. The
29+
result can then be converted to JSON for use with tools and libraries such as
30+
[graphql-client](https://github.com/graphql-rust/graphql-client):
31+
32+
```rust
33+
# // Only needed due to 2018 edition because the macro is not accessible.
34+
# extern crate juniper;
35+
# extern crate serde_json;
36+
use juniper::{EmptyMutation, FieldResult, IntrospectionFormat};
37+
38+
// Define our schema.
39+
40+
#[derive(juniper::GraphQLObject)]
41+
struct Example {
42+
id: String,
43+
}
44+
45+
struct Context;
46+
impl juniper::Context for Context {}
47+
48+
struct Query;
49+
50+
juniper::graphql_object!(Query: Context |&self| {
51+
field example(&executor, id: String) -> FieldResult<Example> {
52+
unimplemented!()
53+
}
54+
});
55+
56+
type Schema = juniper::RootNode<'static, Query, EmptyMutation<Context>>;
57+
58+
fn main() {
59+
// Create a context object.
60+
let ctx = Context{};
61+
62+
// Run the built-in introspection query.
63+
let (res, _errors) = juniper::introspect(
64+
&Schema::new(Query, EmptyMutation::new()),
65+
&ctx,
66+
IntrospectionFormat::default(),
67+
).unwrap();
68+
69+
// Convert introspection result to json.
70+
let json_result = serde_json::to_string_pretty(&res);
71+
assert!(json_result.is_ok());
72+
}
73+
```

docs/book/content/quickstart.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use juniper::{FieldResult};
3333
# struct DatabasePool;
3434
# impl DatabasePool {
3535
# fn get_connection(&self) -> FieldResult<DatabasePool> { Ok(DatabasePool) }
36-
# fn find_human(&self, id: &str) -> FieldResult<Human> { Err("")? }
37-
# fn insert_human(&self, human: &NewHuman) -> FieldResult<Human> { Err("")? }
36+
# fn find_human(&self, _id: &str) -> FieldResult<Human> { Err("")? }
37+
# fn insert_human(&self, _human: &NewHuman) -> FieldResult<Human> { Err("")? }
3838
# }
3939

4040
#[derive(juniper::GraphQLEnum)]
@@ -114,12 +114,14 @@ juniper::graphql_object!(Mutation: Context |&self| {
114114
// Request queries can be executed against a RootNode.
115115
type Schema = juniper::RootNode<'static, Query, Mutation>;
116116

117-
# fn main() { }
117+
# fn main() {
118+
# let _ = Schema::new(Query, Mutation{});
119+
# }
118120
```
119121

120122
We now have a very simple but functional schema for a GraphQL server!
121123

122-
To actually serve the schema, see the guides for our various [server integrations](./servers/index.md).
124+
To actually serve the schema, see the guides for our various [server integrations](./servers/index.md).
123125

124126
You can also invoke the executor directly to get a result for a query:
125127

@@ -129,6 +131,7 @@ You can invoke `juniper::execute` directly to run a GraphQL query:
129131

130132
```rust
131133
# // Only needed due to 2018 edition because the macro is not accessible.
134+
# #[macro_use]
132135
# extern crate juniper;
133136
use juniper::{FieldResult, Variables, EmptyMutation};
134137

@@ -172,7 +175,7 @@ fn main() {
172175
assert_eq!(
173176
res,
174177
graphql_value!({
175-
"favoriteEpisode": "NEW_HONE",
178+
"favoriteEpisode": "NEW_HOPE",
176179
})
177180
);
178181
}

docs/book/tests/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate skeptic;
22

33
fn main() {
4-
let files = skeptic::markdown_files_of_directory("../content/types");
4+
let files = skeptic::markdown_files_of_directory("../content/");
55
skeptic::generate_doc_tests(&files);
66
}

juniper/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
- The minimum required Rust version is now `1.30.0`.
44
- The `ScalarValue` custom derive has been renamed to `GraphQLScalarValue`.
5+
- Added built-in support for the canonical schema introspection query via
6+
`juniper::introspect()`. [#307](https://github.com/graphql-rust/juniper/issues/307)
57
- Fix introspection query validity
68
The DirectiveLocation::InlineFragment had an invalid literal value,
79
which broke third party tools like apollo cli.
810
- Added GraphQL Playground integration
9-
The DirectiveLocation::InlineFragment had an invalid literal value,
10-
which broke third party tools like apollo cli.
11+
The DirectiveLocation::InlineFragment had an invalid literal value,
12+
which broke third party tools like apollo cli.
1113
- The return type of `value::object::Object::iter/iter_mut` has changed to `impl Iter` [#312](https://github.com/graphql-rust/juniper/pull/312)
1214

1315
# [0.11.1] 2018-12-19

juniper/src/introspection/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// From <https://github.com/graphql/graphql-js/blob/8c96dc8276f2de27b8af9ffbd71a4597d483523f/src/utilities/introspectionQuery.js#L21>s
2+
pub(crate) const INTROSPECTION_QUERY: &str = include_str!("./query.graphql");
3+
pub(crate) const INTROSPECTION_QUERY_WITHOUT_DESCRIPTIONS: &str =
4+
include_str!("./query_without_descriptions.graphql");
5+
6+
/// The desired GraphQL introspection format for the canonical query
7+
/// (<https://github.com/graphql/graphql-js/blob/8c96dc8276f2de27b8af9ffbd71a4597d483523f/src/utilities/introspectionQuery.js#L21>)
8+
pub enum IntrospectionFormat {
9+
/// The canonical GraphQL introspection query.
10+
All,
11+
/// The canonical GraphQL introspection query without descriptions.
12+
WithoutDescriptions,
13+
}
14+
15+
impl Default for IntrospectionFormat {
16+
fn default() -> Self {
17+
IntrospectionFormat::All
18+
}
19+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
query IntrospectionQuery {
2+
__schema {
3+
queryType {
4+
name
5+
}
6+
mutationType {
7+
name
8+
}
9+
subscriptionType {
10+
name
11+
}
12+
types {
13+
...FullType
14+
}
15+
directives {
16+
name
17+
description
18+
locations
19+
args {
20+
...InputValue
21+
}
22+
}
23+
}
24+
}
25+
fragment FullType on __Type {
26+
kind
27+
name
28+
description
29+
fields(includeDeprecated: true) {
30+
name
31+
description
32+
args {
33+
...InputValue
34+
}
35+
type {
36+
...TypeRef
37+
}
38+
isDeprecated
39+
deprecationReason
40+
}
41+
inputFields {
42+
...InputValue
43+
}
44+
interfaces {
45+
...TypeRef
46+
}
47+
enumValues(includeDeprecated: true) {
48+
name
49+
description
50+
isDeprecated
51+
deprecationReason
52+
}
53+
possibleTypes {
54+
...TypeRef
55+
}
56+
}
57+
fragment InputValue on __InputValue {
58+
name
59+
description
60+
type {
61+
...TypeRef
62+
}
63+
defaultValue
64+
}
65+
fragment TypeRef on __Type {
66+
kind
67+
name
68+
ofType {
69+
kind
70+
name
71+
ofType {
72+
kind
73+
name
74+
ofType {
75+
kind
76+
name
77+
ofType {
78+
kind
79+
name
80+
ofType {
81+
kind
82+
name
83+
ofType {
84+
kind
85+
name
86+
ofType {
87+
kind
88+
name
89+
}
90+
}
91+
}
92+
}
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)