Skip to content

Commit c8327cf

Browse files
committed
Update introspection docs.
1 parent d980d3b commit c8327cf

File tree

1 file changed

+71
-62
lines changed

1 file changed

+71
-62
lines changed

src/pages/learn/introspection.mdx

Lines changed: 71 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
11
# Introspection
22

3-
It's often useful to ask a GraphQL schema for information about what
4-
queries it supports. GraphQL allows us to do so using the introspection
5-
system!
3+
<p className="learn-subtitle">Learn how to query information about a GraphQL schema</p>
64

7-
For our Star Wars example, the file
8-
[starWarsIntrospection-test.ts](https://github.com/graphql/graphql-js/blob/main/src/__tests__/starWarsIntrospection-test.ts)
9-
contains a number of queries demonstrating the introspection system, and is a
10-
test file that can be run to exercise the reference implementation's
11-
introspection system.
5+
It's often useful to ask a GraphQL schema for information about what operations it supports. GraphQL allows us to do so using the [introspection system](https://spec.graphql.org/draft/#sec-Introspection).
126

13-
We designed the type system, so we know what types are available, but if
14-
we didn't, we can ask GraphQL, by querying the `__schema` field, always
15-
available on the root type of a Query. Let's do so now, and ask what types
16-
are available.
7+
Introspection queries are special kinds of queries that allow you to learn about a GraphQL API's schema, and they also help power GraphQL development tools. On this page, we'll learn how to run different queries to learn more about an underlying schema's types, fields, and descriptions.
8+
9+
## Type name introspection
10+
11+
We have already seen an example of introspection on the [Schemas and Types page](/learn/schema/). When querying a field that returned Union type, we included the `__typename` meta-field directly in a selection set to get the string value of the names of the different types returned by a search query. Let's look at this example again:
12+
13+
```graphql
14+
# { "graphiql": true }
15+
query {
16+
search(text: "an") {
17+
__typename
18+
... on Character {
19+
name
20+
}
21+
... on Starship {
22+
name
23+
}
24+
}
25+
}
26+
```
27+
28+
We didn't add the `__typename` field to our GraphQL API explicitly—the GraphQL specification says that it must be provided to clients by a GraphQL implementation. This field can be queried for any field with an Object, Interface, or Union type as an output type.
29+
30+
## Schema introspection
31+
32+
Introspection can do more than provide type names in a query. If you designed the type system for a GraphQL API, then you'll likely already know what types are available. But if you didn't design it, you can ask GraphQL by querying the `__schema` field, which is always available on the `query` root operation type.
33+
34+
Let's do so now and ask what types are available in the Star Wars schema:
1735

1836
```graphql
1937
# { "graphiql": true }
20-
{
38+
query {
2139
__schema {
2240
types {
2341
name
@@ -28,21 +46,15 @@ are available.
2846

2947
Wow, that's a lot of types! What are they? Let's group them:
3048

31-
- `Query`, `Character`, `Human`, `Episode`, `Droid` - These are the ones that we
32-
defined in our type system.
33-
- `String`, `Boolean` - These are built-in scalars that the type system
34-
provided.
35-
- `__Schema`, `__Type`, `__TypeKind`, `__Field`, `__InputValue`,
36-
`__EnumValue`, `__Directive` - These all are preceded with a double
37-
underscore, indicating that they are part of the introspection system.
49+
- Types that we defined in our type system: `Query`, `Mutation`, `Character`, `Human`, `Episode`, `Droid`, `LengthUnit`, `FriendsConnection`, `FriendsEdge`, `PageInfo`, `Review`, `ReviewInput`, `Starship`, and `SearchResult`
50+
- Built-in scalars that the type system provided: `Boolean`, `Float`, `ID`, `Int`, and `String`
51+
- Types preceded with a double underscore that are part of the introspection system: `__Schema`, `__Type`, `__TypeKind`, `__Field`, `__InputValue`, `__EnumValue`, `__Directive`, and `__DirectiveLocation`
3852

39-
Now, let's try and figure out a good place to start exploring what queries are
40-
available. When we designed our type system, we specified what type all queries
41-
would start at; let's ask the introspection system about that!
53+
Now, let's try to figure out a good place to start exploring what queries are available. When we designed our type system, we specified what type all queries would start at; let's ask the introspection system about that:
4254

4355
```graphql
4456
# { "graphiql": true }
45-
{
57+
query {
4658
__schema {
4759
queryType {
4860
name
@@ -51,57 +63,48 @@ would start at; let's ask the introspection system about that!
5163
}
5264
```
5365

54-
And that matches what we said in the type system section, that
55-
the `Query` type is where we will start! Note that the naming here
56-
was just by convention; we could have named our `Query` type anything
57-
else, and it still would have been returned here had we specified it
58-
was the starting type for queries. Naming it `Query`, though, is a useful
59-
convention.
66+
The result matches what we said in the [type system section](/learn/schema/#type-system)—that the `Query` type is where we will start. Note that the naming here was just by convention; we could have named our `Query` type anything else, and it still would have been returned here had we specified it was the starting type for queries. Naming it `Query`, though, is a useful convention.
6067

61-
It is often useful to examine one specific type. Let's take a look at
62-
the `Droid` type:
68+
It is often useful to examine one specific type. Let's take a look at the `Droid` type:
6369

6470
```graphql
6571
# { "graphiql": true }
66-
{
72+
query {
6773
__type(name: "Droid") {
6874
name
6975
}
7076
}
7177
```
7278

73-
What if we want to know more about Droid, though? For example, is it
74-
an interface or an object?
79+
But what if we want to know more about Droid? For example, is it an Interface or Object type?
7580

7681
```graphql
7782
# { "graphiql": true }
78-
{
83+
query {
7984
__type(name: "Droid") {
8085
name
8186
kind
8287
}
8388
}
8489
```
8590

86-
`kind` returns a `__TypeKind` enum, one of whose values is `OBJECT`. If
87-
we asked about `Character` instead we'd find that it is an interface:
91+
`kind` returns a `__TypeKind` Enum type, one of whose values is `OBJECT`. If we asked about `Character` instead we'd find that it is an Interface type:
8892

8993
```graphql
9094
# { "graphiql": true }
91-
{
95+
query {
9296
__type(name: "Character") {
9397
name
9498
kind
9599
}
96100
}
97101
```
98102

99-
It's useful for an object to know what fields are available, so let's
100-
ask the introspection system about `Droid`:
103+
It's useful for an Object type to know what fields are available, so let's ask the introspection system about `Droid`:
101104

102105
```graphql
103106
# { "graphiql": true }
104-
{
107+
query {
105108
__type(name: "Droid") {
106109
name
107110
fields {
@@ -115,20 +118,15 @@ ask the introspection system about `Droid`:
115118
}
116119
```
117120

118-
Those are our fields that we defined on `Droid`!
121+
Those are the fields that we defined on `Droid`!
119122

120-
`id` looks a bit weird there, it has no name for the type. That's
121-
because it's a "wrapper" type of kind `NON_NULL`. If we queried for
122-
`ofType` on that field's type, we would find the `ID` type there,
123-
telling us that this is a non-null ID.
123+
`id` looks a bit weird there, it has no name for the type. That's because it's a _wrapper type_ of kind `NON_NULL`. If we queried for `ofType` on that field's type, we would find the `ID` type there, telling us this is a non-null ID.
124124

125-
Similarly, both `friends` and `appearsIn` have no name, since they are the
126-
`LIST` wrapper type. We can query for `ofType` on those types, which will
127-
tell us what these are lists of.
125+
Similarly, both `friends` and `appearsIn` have no name, since they are the `LIST` wrapper type. We can query for `ofType` on those types, which will tell us what types are inside the list:
128126

129127
```graphql
130128
# { "graphiql": true }
131-
{
129+
query {
132130
__type(name: "Droid") {
133131
name
134132
fields {
@@ -146,25 +144,36 @@ tell us what these are lists of.
146144
}
147145
```
148146

149-
Let's end with a feature of the introspection system particularly useful
150-
for tooling; let's ask the system for documentation!
147+
Let's end with a feature of the introspection system particularly useful for tooling; let's ask the system for documentation:
151148

152149
```graphql
153150
# { "graphiql": true }
154-
{
151+
query {
155152
__type(name: "Droid") {
156153
name
157154
description
158155
}
159156
}
160157
```
161158

162-
So we can access the documentation about the type system using introspection,
163-
and create documentation browsers, or rich IDE experiences.
159+
As demonstrated above, we can access the documentation about the type system using introspection and create documentation browsers or rich IDE experiences.
160+
161+
This has just scratched the surface of the introspection system; we can query for Enum type values, what Interface types another type implements, and more. We can even introspect on the introspection system itself.
162+
163+
To see an example of a specification-compliant GraphQL query introspection system implemented in code, you can view the [introspection.ts](https://github.com/graphql/graphql-js/blob/main/src/type/introspection.ts) file in GraphQL.js repository.
164+
165+
## Introspection in production
166+
167+
Introspection is a useful feature of GraphQL, especially for client developers. However, for private GraphQL APIs, it may be undesirable to expose sensitive information about the schema publicly via the `__schema` field in a production environment.
168+
169+
In those cases, it may be preferable to disable introspection in production environments as a part of a broader API security strategy that could also include authentication and authorization, depth-limiting, query cost analysis, and more.
170+
171+
## Next steps
172+
173+
To recap what we've learned about introspection:
174+
175+
- Type names can be queried in a field selection set for an Object, Interface, or Union type using the `__typename` meta-field
176+
- Information about the elements of a GraphQL schema can be queried using the `__schema` field on the `query` root operation type
177+
- Introspection is often disabled in production environments for private APIs
164178

165-
This has just scratched the surface of the introspection system; we can
166-
query for enum values, what interfaces a type implements, and more. We
167-
can even introspect on the introspection system itself. The specification goes
168-
into more detail about this topic in the "Introspection" section, and the [introspection](https://github.com/graphql/graphql-js/blob/main/src/type/introspection.ts)
169-
file in GraphQL.js contains code implementing a specification-compliant GraphQL
170-
query introspection system.
179+
Now that you've explored the GraphQL type system, how to query data from an API, and what the lifecycle of a request looks like, head over to the [Best Practices](/learn/best-practices/) section to learn more about running GraphQL in production.

0 commit comments

Comments
 (0)