Introspection

A GraphQL schema has a built-in introspection system that publishes the schema’s structure. In fact, the introspection system can be queried using GraphQL, for example:

{
  __schema {
    queryType {
      name
    }
  }
}
# Returns:
# {
#   "data": {
#     "__schema": {
#       "queryType": {
#         "name": "Query"
#       }
#     }
#   }
# }

This system is used for GraphQL tooling like the GraphiQL editor.

Here are the default parts of the introspection system:

Here are some __typename examples:

{
  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:

{
  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

This is an experimental feature, only supported in class-based schemas.

With a class-based schema, you can use custom introspection types.

# 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:

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
TypeType __Type GraphQL::Introspection::TypeType
DirectiveType __Directive GraphQL::Introspection::DirectiveType
DirectiveLocationType __DirectiveLocation GraphQL::Introspection::DirectiveLocationEnum
EnumValueType __EnumValue GraphQL::Introspection::EnumValueType
FieldType __Field GraphQL::Introspection::FieldType
InputValueType __InputValue GraphQL::Introspection::InputValueType
TypeKindType __TypeKind GraphQL::Introspection::TypeKindEnum

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:

module Introspection
  class SchemaType < GraphQL::Introspection::SchemaType
    # ...
  end
end

Inside the class definition, you may:

Introspection Entry Points

The GraphQL spec describes two entry points to the introspection system:

You can re-implement these fields or create new ones by creating a custom EntryPoints class in your introspection namespace:

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 defintion:

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:

class MySchema < GraphQL::Schema
  disable_introspection_entry_points if Rails.env.production?
end