1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
---
layout: guide
doc_stub: false
search: true
title: Introspection
section: Schema
desc: GraphQL has an introspection system that tells about the schema.
index: 3
---
A GraphQL schema has a [built-in introspection system](https://graphql.org/learn/introspection/) that publishes the schema's structure. In fact, the introspection system can be queried using GraphQL, for example:
```graphql
{
__schema {
queryType {
name
}
}
}
# Returns:
# {
# "data": {
# "__schema": {
# "queryType": {
# "name": "Query"
# }
# }
# }
# }
```
This system is used for GraphQL tooling like the [GraphiQL editor](https://github.com/graphql/graphiql).
Here are the default parts of the introspection system:
- `__schema` is a root-level field that contains data about the schema: its entry points, types, and directives.
- `__type(name: String!)` is a root-level field that returns data about a type with the given `name`, if there is a type with that name.
- `__typename` works a bit differently: it can be added to _any_ selection, and it will return the type of object being queried.
Here are some `__typename` examples:
```graphql
{
user(id: "1") {
handle
__typename
}
}
# Returns:
# {
# "data": {
# "user": {
# "handle": "rmosolgo",
# "__typename": "User"
# }
# }
# }
```
For unions and interfaces, `__typename` returns the _object_ type for the current object, for example:
```graphql
{
search(term: "puppies") {
title
__typename
}
}
# Returns:
# {
# "data": {
# "search": [
# {
# "title": "Sound of Dogs Barking",
# "__typename": "AudioClip",
# },
# {
# "title": "Cute puppies playing with a stick",
# "__typename": "VideoClip",
# },
# {
# "title": "The names of my favorite pets",
# "__typename": "TextSnippet"
# },
# ]
# }
# }
```
## Customizing Introspection
You can use custom introspection types.
```ruby
# create a module namespace for your custom types:
module Introspection
# described below ...
end
class MySchema < GraphQL::Schema
# ...
# then pass the module as `introspection`
introspection Introspection
end
```
Keep in mind that off-the-shelf tooling may not support your custom introspection fields. You may have to modify existing tooling or create your own tools to make use of your extensions.
### Introspection Namespace
The introspection namespace may contain a few different customizations:
- Class-based {% internal_link "object definitions", "/type_definitions/objects" %} which replace the built-in introspection types (such as `__Schema` and `__Type`)
- `EntryPoints`, A class-based {% internal_link "object definition", "/type_definitions/objects" %} containing introspection entry points (like `__schema` and `__type(name:)`).
- `DynamicFields`, A class-based {% internal_link "object definition", "/type_definitions/objects" %} containing dynamic, globally-available fields (like `__typename`.)
### Custom Introspection Types
The `module` passed as `introspection` may contain classes with the following names, which replace the built-in introspection types:
Custom class name | GraphQL type | Built-in class name
--|--|--
`SchemaType` | `__Schema` | {{ "GraphQL::Introspection::SchemaType" | api_doc }}
`TypeType` | `__Type` | {{ "GraphQL::Introspection::TypeType" | api_doc }}
`DirectiveType` | `__Directive` | {{ "GraphQL::Introspection::DirectiveType" | api_doc }}
`DirectiveLocationType` | `__DirectiveLocation` | {{ "GraphQL::Introspection::DirectiveLocationEnum" | api_doc }}
`EnumValueType` | `__EnumValue` | {{ "GraphQL::Introspection::EnumValueType" | api_doc }}
`FieldType` | `__Field` | {{ "GraphQL::Introspection::FieldType" | api_doc }}
`InputValueType` | `__InputValue` | {{ "GraphQL::Introspection::InputValueType" | api_doc }}
`TypeKindType` | `__TypeKind` | {{ "GraphQL::Introspection::TypeKindEnum" | api_doc }}
The class-based definitions' names _must_ match the names of the types they replace.
#### Extending a Built-in Type
The built-in classes listed above may be extended:
```ruby
module Introspection
class SchemaType < GraphQL::Introspection::SchemaType
# ...
end
end
```
Inside the class definition, you may:
- add new fields by calling `field(...)` and providing implementations
- redefine field structure by calling `field(...)`
- provide new field implementations by defining methods
- provide new descriptions by calling `description(...)`
### Introspection Entry Points
The GraphQL spec describes two entry points to the introspection system:
- `__schema` returns data about the schema (as type `__Schema`)
- `__type(name:)` returns data about a type, if one is found by name (as type `__Type`)
You can re-implement these fields or create new ones by creating a custom `EntryPoints` class in your introspection namespace:
```ruby
module Introspection
class EntryPoints < GraphQL::Introspection::EntryPoints
# ...
end
end
```
This class an object type definition, so you can override fields or add new ones here. They'll be available on the root `query` object, but ignored in introspection (just like `__schema` and `__type`).
### Dynamic Fields
The GraphQL spec describes a field which may be added to _any_ selection: `__typename`. It returns the name of the current GraphQL type.
You can add fields like this (or override `__typename`) by creating a custom `DynamicFields` definition:
```ruby
module Introspection
class DynamicFields < GraphQL::Introspection::DynamicFields
# ...
end
end
```
Any fields defined there will be available in any selection, but ignored in introspection (just like `__typename`).
## Disabling Introspection
In case you want to turn off introspection entry points `__schema` and `__type` (for instance in the production environment) you can use a `#disable_introspection_entry_points` shorthand method:
```ruby
class MySchema < GraphQL::Schema
disable_introspection_entry_points if Rails.env.production?
end
```
Where `disable_introspection_entry_points` will disable both the `__schema` and `__type` introspection entry points, you can also individually disable the introspection entry points using the `disable_schema_introspection_entry_point` and `disable_type_introspection_entry_point` shorthand methods:
```ruby
class MySchema < GraphQL::Schema
disable_schema_introspection_entry_point
disable_type_introspection_entry_point
end
```
|