diff --git a/internal/exec/introspection.go b/internal/exec/introspection.go index 1095aff7f38..54546e9b8c0 100644 --- a/internal/exec/introspection.go +++ b/internal/exec/introspection.go @@ -54,37 +54,72 @@ func introspectType(r *request, name string, selSet *query.SelectionSet) interfa } var metaSchemaSrc = ` - type __Schema { - types: [__Type!]! - queryType: __Type! - mutationType: __Type - directives: [__Directive!]! - } - - type __Type { - kind: __TypeKind! - name: String + # A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document. + # + # In some cases, you need to provide options to alter GraphQL's execution behavior + # in ways field arguments will not suffice, such as conditionally including or + # skipping a field. Directives provide this by describing additional information + # to the executor. + type __Directive { + name: String! description: String + locations: [__DirectiveLocation!]! + args: [__InputValue!]! + } - # OBJECT and INTERFACE only - fields(includeDeprecated: Boolean = false): [__Field!] - - # OBJECT only - interfaces: [__Type!] - - # INTERFACE and UNION only - possibleTypes: [__Type!] - - # ENUM only - enumValues(includeDeprecated: Boolean = false): [__EnumValue!] - - # INPUT_OBJECT only - inputFields: [__InputValue!] + # A Directive can be adjacent to many parts of the GraphQL language, a + # __DirectiveLocation describes one such possible adjacencies. + enum __DirectiveLocation { + # Location adjacent to a query operation. + QUERY + # Location adjacent to a mutation operation. + MUTATION + # Location adjacent to a subscription operation. + SUBSCRIPTION + # Location adjacent to a field. + FIELD + # Location adjacent to a fragment definition. + FRAGMENT_DEFINITION + # Location adjacent to a fragment spread. + FRAGMENT_SPREAD + # Location adjacent to an inline fragment. + INLINE_FRAGMENT + # Location adjacent to a schema definition. + SCHEMA + # Location adjacent to a scalar definition. + SCALAR + # Location adjacent to an object type definition. + OBJECT + # Location adjacent to a field definition. + FIELD_DEFINITION + # Location adjacent to an argument definition. + ARGUMENT_DEFINITION + # Location adjacent to an interface definition. + INTERFACE + # Location adjacent to a union definition. + UNION + # Location adjacent to an enum definition. + ENUM + # Location adjacent to an enum value definition. + ENUM_VALUE + # Location adjacent to an input object type definition. + INPUT_OBJECT + # Location adjacent to an input object field definition. + INPUT_FIELD_DEFINITION + } - # NON_NULL and LIST only - ofType: __Type + # One possible value for a given Enum. Enum values are unique values, not a + # placeholder for a string or numeric value. However an Enum value is returned in + # a JSON response as a string. + type __EnumValue { + name: String! + description: String + isDeprecated: Boolean! + deprecationReason: String } + # Object and Interface types are described by a list of Fields, each of which has + # a name, potentially a list of arguments, and a return type. type __Field { name: String! description: String @@ -94,46 +129,72 @@ var metaSchemaSrc = ` deprecationReason: String } + # Arguments provided to Fields or Directives and the input fields of an + # InputObject are represented as Input Values which describe their type and + # optionally a default value. type __InputValue { name: String! description: String type: __Type! + # A GraphQL-formatted string representing the default value for this input value. defaultValue: String } - type __EnumValue { - name: String! - description: String - isDeprecated: Boolean! - deprecationReason: String + # A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all + # available types and directives on the server, as well as the entry points for + # query, mutation, and subscription operations. + type __Schema { + # A list of all types supported by this server. + types: [__Type!]! + # The type that query operations will be rooted at. + queryType: __Type! + # If this server supports mutation, the type that mutation operations will be rooted at. + mutationType: __Type + # If this server support subscription, the type that subscription operations will be rooted at. + subscriptionType: __Type + # A list of all directives supported by this server. + directives: [__Directive!]! } + # The fundamental unit of any GraphQL Schema is the type. There are many kinds of + # types in GraphQL as represented by the ` + "`" + `__TypeKind` + "`" + ` enum. + # + # Depending on the kind of a type, certain fields describe information about that + # type. Scalar types provide no information beyond a name and description, while + # Enum types provide their values. Object and Interface types provide the fields + # they describe. Abstract types, Union and Interface, provide the Object types + # possible at runtime. List and NonNull types compose other types. + type __Type { + kind: __TypeKind! + name: String + description: String + fields(includeDeprecated: Boolean = false): [__Field!] + interfaces: [__Type!] + possibleTypes: [__Type!] + enumValues(includeDeprecated: Boolean = false): [__EnumValue!] + inputFields: [__InputValue!] + ofType: __Type + } + + # An enum describing what kind of type a given ` + "`" + `__Type` + "`" + ` is. enum __TypeKind { + # Indicates this type is a scalar. SCALAR + # Indicates this type is an object. ` + "`" + `fields` + "`" + ` and ` + "`" + `interfaces` + "`" + ` are valid fields. OBJECT + # Indicates this type is an interface. ` + "`" + `fields` + "`" + ` and ` + "`" + `possibleTypes` + "`" + ` are valid fields. INTERFACE + # Indicates this type is a union. ` + "`" + `possibleTypes` + "`" + ` is a valid field. UNION + # Indicates this type is an enum. ` + "`" + `enumValues` + "`" + ` is a valid field. ENUM + # Indicates this type is an input object. ` + "`" + `inputFields` + "`" + ` is a valid field. INPUT_OBJECT + # Indicates this type is a list. ` + "`" + `ofType` + "`" + ` is a valid field. LIST + # Indicates this type is a non-null. ` + "`" + `ofType` + "`" + ` is a valid field. NON_NULL } - - type __Directive { - name: String! - description: String - locations: [__DirectiveLocation!]! - args: [__InputValue!]! - } - - enum __DirectiveLocation { - QUERY - MUTATION - FIELD - FRAGMENT_DEFINITION - FRAGMENT_SPREAD - INLINE_FRAGMENT - } ` type schemaResolver struct { @@ -160,11 +221,27 @@ func (r *schemaResolver) Types() []*typeResolver { } func (r *schemaResolver) QueryType() *typeResolver { - return &typeResolver{typ: r.schema.Types[r.schema.EntryPoints["query"]]} + t, ok := r.schema.Types[r.schema.EntryPoints["query"]] + if !ok { + return nil + } + return &typeResolver{typ: t} } func (r *schemaResolver) MutationType() *typeResolver { - return &typeResolver{typ: r.schema.Types[r.schema.EntryPoints["mutation"]]} + t, ok := r.schema.Types[r.schema.EntryPoints["mutation"]] + if !ok { + return nil + } + return &typeResolver{typ: t} +} + +func (r *schemaResolver) SubscriptionType() *typeResolver { + t, ok := r.schema.Types[r.schema.EntryPoints["subscription"]] + if !ok { + return nil + } + return &typeResolver{typ: t} } func (r *schemaResolver) Directives() []*directiveResolver {