ast

package
Version: v1.0.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2020 License: MIT Imports: 3 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsEnumType

func IsEnumType(p Node) bool

func IsInputObjectType

func IsInputObjectType(p Node) bool

func IsInputType

func IsInputType(p Node) bool

Types are used throughout GraphQL to describe both the values accepted as input to arguments and variables as well as the values output by fields. These two uses categorize types as input types and output types. Some kinds of types, like Scalar and Enum types, can be used as both input types and output types; other kinds of types can only be used in one or the other. Input Object types can only be used as input types. Object, Interface, and Union types can only be used as output types. Lists and Non‐Null types may be used as input types or output types depending on how the wrapped type may be used.

IsInputType(type):
	1.If type is a List type or Non‐Null type:
		a.Let unwrappedType be the unwrapped type of type.
		b.Return IsInputType(unwrappedType)
	2.If type is a Scalar, Enum, or Input Object type:
		a.Return true
	3.Return false
IsOutputType(type):
	1.If type is a List type or Non‐Null type:
		a.Let unwrappedType be the unwrapped type of type.
		b.Return IsOutputType(unwrappedType)
	2.If type is a Scalar, Object, Interface, Union, or Enum type:
		a.Return true
	3.Return false

func IsInterfaceType

func IsInterfaceType(p Node) bool

func IsObjectType

func IsObjectType(p Node) bool

func IsOutputType

func IsOutputType(p Node) bool

func IsScalarType

func IsScalarType(p Node) bool

func IsUnionType

func IsUnionType(p Node) bool

Types

type Argument

type Argument struct {
	Kind  string          `json:"kind"`
	Name  *Name           `json:"name"`
	Value Value           `json:"value"`
	Loc   errors.Location `json:"loc"`
}

Fields are conceptually functions which return values, and occasionally accept arguments which alter their behavior. These arguments often map directly to function arguments within a GraphQL server’s implementation.

In this example, we want to query a specific user (requested via the id argument) and their profile picture of a specific size:

{

user(id: 4) {
  id
  name
  profilePic(size: 100)
}

} Many arguments can exist for a given field:

{

user(id: 4) {
  id
  name
  profilePic(width: 100, height: 50)
}

}

Arguments are unordered Arguments may be provided in any syntactic order and maintain identical semantic meaning.

These two queries are semantically identical:

{

picture(width: 200, height: 100)

} {

picture(height: 100, width: 200)

}

func (*Argument) GetKind

func (a *Argument) GetKind() string

func (*Argument) Location

func (a *Argument) Location() errors.Location

type BooleanValue

type BooleanValue struct {
	Kind  string          `json:"kind"`
	Value bool            `json:"value"`
	Loc   errors.Location `json:"loc"`
}

The two keywords true and false represent the two boolean values.

func (*BooleanValue) GetKind

func (b *BooleanValue) GetKind() string

func (*BooleanValue) GetValue

func (b *BooleanValue) GetValue() interface{}

func (*BooleanValue) Location

func (b *BooleanValue) Location() errors.Location

type Definition

type Definition interface {
	Node
	IsDefinition()
}

type Description

type Description interface {
	GetDescription() StringValue
}

Documentation is a first‐class feature of GraphQL type systems. To ensure the documentation of a GraphQL service remains consistent with its capabilities, descriptions of GraphQL definitions are provided alongside their definitions and made available via introspection.

To allow GraphQL service designers to easily publish documentation alongside the capabilities of a GraphQL service, GraphQL descriptions are defined using the Markdown syntax (as specified by CommonMark). In the type system definition language, these description strings (often BlockString) occur immediately before the definition they describe.

GraphQL schema and all other definitions (e.g. types, fields, arguments, etc.) which can be described should provide a Description unless they are considered self descriptive.

As an example, this simple GraphQL schema is well described:

""" A simple GraphQL schema which is well described. """ schema {

query: Query

}

""" Root type for all your queries """ type Query {

"""
Translates a string from a given language into a different language.
"""
translate(
  "The original language that `text` is provided in."
  fromLanguage: Language

  "The translated language to be returned."
  toLanguage: Language

  "The text to be translated."
  text: String
): String

}

""" The set of languages supported by `translate`. """ enum Language {

"English"
EN

"French"
FR

"Chinese"
CH

}

type Directive

type Directive struct {
	Kind string          `json:"kind"`
	Name *Name           `json:"name"`
	Args []*Argument     `json:"arguments"`
	Loc  errors.Location `json:"loc"`
}

Directives provide 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.

Directives have a name along with a list of arguments which may accept values of any input type.

Directives can be used to describe additional information for types, fields, fragments and operations.

As future versions of GraphQL adopt new configurable execution capabilities, they may be exposed via directives. GraphQL services and tools may also provide additional custom directives beyond those described here.

#Directive order is significant Directives may be provided in a specific syntactic order which may have semantic interpretation.

These two type definitions may have different semantic meaning:

type Person @addExternalFields(source: "profiles") @excludeField(name: "photo") {

name: String

} type Person @excludeField(name: "photo") @addExternalFields(source: "profiles") {

name: String

}

func (*Directive) GetKind

func (d *Directive) GetKind() string

func (*Directive) Location

func (d *Directive) Location() errors.Location

type DirectiveDefinition

type DirectiveDefinition struct {
	Kind      string                  `json:"kind"`
	Desc      *StringValue            `json:"desc"`
	Name      *Name                   `json:"name"`
	Arguments []*InputValueDefinition `json:"arguments"`
	Locations []string                `json:"locations"`
	Loc       errors.Location         `json:"loc"`
}

A GraphQL schema describes directives which are used to annotate various parts of a GraphQL document as an indicator that they should be evaluated differently by a validator, executor, or client tool such as a code generator.

GraphQL implementations should provide the @skip and @include directives.

GraphQL implementations that support the type system definition language must provide the @deprecated directive if representing deprecated portions of the schema.

func (*DirectiveDefinition) GetKind

func (d *DirectiveDefinition) GetKind() string

func (*DirectiveDefinition) IsDefinition

func (d *DirectiveDefinition) IsDefinition()

func (*DirectiveDefinition) IsTypeSystemDefinition

func (d *DirectiveDefinition) IsTypeSystemDefinition()

func (*DirectiveDefinition) Location

func (d *DirectiveDefinition) Location() errors.Location

type Document

type Document struct {
	Kind       string          `json:"kind"`
	Definition []Definition    `json:"definition"`
	Loc        errors.Location `json:"loc"`
}

A GraphQL Document describes a complete file or request string operated on by a GraphQL service or client. A document contains multiple definitions, either executable or representative of a GraphQL type system.

Documents are only executable by a GraphQL service if they contain an OperationDefinition and otherwise only contain ExecutableDefinition. However documents which do not contain OperationDefinition or do contain TypeSystemDefinition or TypeSystemExtension may still be parsed and validated to allow client tools to represent many GraphQL uses which may appear across many individual files.

If a Document contains only one operation, that operation may be unnamed or represented in the shorthand form, which omits both the query keyword and operation name. Otherwise, if a GraphQL Document contains multiple operations, each operation must be named. When submitting a Document with multiple operations to a GraphQL service, the name of the desired operation to be executed must also be provided.

GraphQL services which only seek to provide GraphQL query execution may choose to only include ExecutableDefinition and omit the TypeSystemDefinition and TypeSystemExtension rules from Definition.

func (*Document) GetKind

func (d *Document) GetKind() string

func (*Document) Location

func (d *Document) Location() errors.Location

type EnumDefinition

type EnumDefinition struct {
	Kind       string                 `json:"kind"`
	Desc       *StringValue           `json:"desc"`
	Name       *Name                  `json:"name"`
	Directives []*Directive           `json:"directives"`
	Values     []*EnumValueDefinition `json:"values"`
	Loc        errors.Location        `json:"loc"`
}

GraphQL Enum types, like Scalar types, also represent leaf values in a GraphQL type system. However Enum types describe the set of possible values.

Enums are not references for a numeric value, but are unique values in their own right. They may serialize as a string: the name of the represented value.

In this example, an Enum type called Direction is defined:

enum Direction {

NORTH
EAST
SOUTH
WEST

}

func (*EnumDefinition) GetKind

func (e *EnumDefinition) GetKind() string

func (*EnumDefinition) IsDefinition

func (e *EnumDefinition) IsDefinition()

func (*EnumDefinition) IsTypeDefinition

func (e *EnumDefinition) IsTypeDefinition()

func (*EnumDefinition) IsTypeSystemDefinition

func (e *EnumDefinition) IsTypeSystemDefinition()

func (*EnumDefinition) Location

func (e *EnumDefinition) Location() errors.Location

type EnumExtension

type EnumExtension struct {
	Name       *Name
	Directives []*Directive
	Values     []*EnumValueDefinition
	Loc        errors.Location
}

Enum type extensions are used to represent an enum type which has been extended from some original enum type. For example, this might be used to represent additional local data, or by a GraphQL service which is itself an extension of another GraphQL service.

func (*EnumExtension) GetKind

func (e *EnumExtension) GetKind() string

func (*EnumExtension) IsDefinition

func (e *EnumExtension) IsDefinition()

func (*EnumExtension) IsTypeExtension

func (e *EnumExtension) IsTypeExtension()

func (*EnumExtension) IsTypeSystemExtension

func (e *EnumExtension) IsTypeSystemExtension()

func (*EnumExtension) Location

func (e *EnumExtension) Location() errors.Location

type EnumValue

type EnumValue struct {
	Kind  string          `json:"kind"`
	Value string          `json:"value"`
	Loc   errors.Location `json:"loc"`
}

Enum values are represented as unquoted names (ex. MOBILE_WEB). It is recommended that Enum values be “all caps”. Enum values are only used in contexts where the precise enumeration type is known. Therefore it’s not necessary to supply an enumeration type name in the literal.

func (*EnumValue) GetKind

func (e *EnumValue) GetKind() string

func (*EnumValue) GetValue

func (e *EnumValue) GetValue() interface{}

func (*EnumValue) Location

func (e *EnumValue) Location() errors.Location

type EnumValueDefinition

type EnumValueDefinition struct {
	Kind       string          `json:"kind"`
	Desc       *StringValue    `json:"desc"`
	Value      *EnumValue      `json:"value"`
	Directives []*Directive    `json:"directives"`
	Loc        errors.Location `json:"loc"`
}

func (*EnumValueDefinition) GetKind

func (e *EnumValueDefinition) GetKind() string

func (*EnumValueDefinition) Location

func (e *EnumValueDefinition) Location() errors.Location

type Field

type Field struct {
	Kind         string          `json:"kind"`
	Alias        *Name           `json:"alias"`
	Name         *Name           `json:"name"`
	Arguments    []*Argument     `json:"arguments"`
	Directives   []*Directive    `json:"directives"`
	SelectionSet *SelectionSet   `json:"selectionSet"`
	Loc          errors.Location `json:"loc"`
}

A selection set is primarily composed of fields. A field describes one discrete piece of information available to request within a selection set.

Some fields describe complex data or relationships to other data. In order to further explore this data, a field may itself contain a selection set, allowing for deeply nested requests. All GraphQL operations must specify their selections down to fields which return scalar values to ensure an unambiguously shaped response.

For example, this operation selects fields of complex data and relationships down to scalar values.

{

me {
  id
  firstName
  lastName
  birthday {
    month
    day
  }
  friends {
    name
  }
}

} Fields in the top‐level selection set of an operation often represent some information that is globally accessible to your application and its current viewer. Some typical examples of these top fields include references to a current logged‐in viewer, or accessing certain types of data referenced by a unique identifier.

For example:

# `me` could represent the currently logged in viewer. {

me {
  name
}

}

# `user` represents one of many users in a graph of data, referred to by a # unique identifier. {

user(id: 4) {
  name
}

}

func (*Field) GetKind

func (f *Field) GetKind() string

func (*Field) IsSelection

func (f *Field) IsSelection()

func (*Field) Location

func (f *Field) Location() errors.Location

type FieldDefinition

type FieldDefinition struct {
	Kind       string                  `json:"kind"`
	Desc       *StringValue            `json:"desc"`
	Name       *Name                   `json:"name"`
	Argument   []*InputValueDefinition `json:"argument"`
	Type       Type                    `json:"type"`
	Directives []*Directive            `json:"directives"`
	Loc        errors.Location         `json:"loc"`
}

func (*FieldDefinition) GetKind

func (f *FieldDefinition) GetKind() string

func (*FieldDefinition) Location

func (f *FieldDefinition) Location() errors.Location

type FloatValue

type FloatValue struct {
	Kind  string          `json:"kind"`
	Value string          `json:"value"`
	Loc   errors.Location `json:"loc"`
}

A FloatValue includes either a decimal point (ex. 1.0) or an exponent (ex. 1e50) or both (ex. 6.0221413e23) and may be negative. Like IntValue, it also must not have any leading 0.

A FloatValue must not be followed by a Digit. In other words, a FloatValue token is always the longest possible valid sequence. The source characters 1.23 cannot be interpreted as two tokens since 1.2 is followed by the Digit 3.

A FloatValue must not be followed by a .. For example, the sequence 1.23.4 cannot be interpreted as two tokens (1.2, 3.4).

A FloatValue must not be followed by a NameStart. For example the sequence 0x1.2p3 has no valid lexical representation.

func (*FloatValue) GetKind

func (f *FloatValue) GetKind() string

func (*FloatValue) GetValue

func (f *FloatValue) GetValue() interface{}

func (*FloatValue) Location

func (f *FloatValue) Location() errors.Location

type FragmentDefinition

type FragmentDefinition struct {
	Kind                string                `json:"kind"`
	Name                *Name                 `json:"name"`
	VariableDefinitions []*VariableDefinition `json:"variableDefinitions"`
	TypeCondition       *Named                `json:"typeCondition"`
	Directives          []*Directive          `json:"directives"`
	SelectionSet        *SelectionSet         `json:"selectionSet"`
	Loc                 errors.Location       `json:"loc"`
}

func (*FragmentDefinition) GetKind

func (f *FragmentDefinition) GetKind() string

func (*FragmentDefinition) IsDefinition

func (f *FragmentDefinition) IsDefinition()

func (*FragmentDefinition) Location

func (f *FragmentDefinition) Location() errors.Location

type FragmentSpread

type FragmentSpread struct {
	Kind       string          `json:"kind"`
	Name       *Name           `json:"name"`
	Directives []*Directive    `json:"directives"`
	Loc        errors.Location `json:"loc"`
}

Fragments are the primary unit of composition in GraphQL.

Fragments allow for the reuse of common repeated selections of fields, reducing duplicated text in the document. Inline Fragments can be used directly within a selection to condition upon a type condition when querying against an interface or union.

For example, if we wanted to fetch some common information about mutual friends as well as friends of some user:

query noFragments {

user(id: 4) {
  friends(first: 10) {
    id
    name
    profilePic(size: 50)
  }
  mutualFriends(first: 10) {
    id
    name
    profilePic(size: 50)
  }
}

} The repeated fields could be extracted into a fragment and composed by a parent fragment or query.

query withFragments {

user(id: 4) {
  friends(first: 10) {
    ...friendFields
  }
  mutualFriends(first: 10) {
    ...friendFields
  }
}

}

fragment friendFields on User {

id
name
profilePic(size: 50)

} Fragments are consumed by using the spread operator (...). All fields selected by the fragment will be added to the query field selection at the same level as the fragment invocation. This happens through multiple levels of fragment spreads.

For example:

query withNestedFragments {

user(id: 4) {
  friends(first: 10) {
    ...friendFields
  }
  mutualFriends(first: 10) {
    ...friendFields
  }
}

}

fragment friendFields on User {

id
name
...standardProfilePic

}

fragment standardProfilePic on User {

profilePic(size: 50)

} The queries noFragments, withFragments, and withNestedFragments all produce the same response object.

func (*FragmentSpread) GetKind

func (f *FragmentSpread) GetKind() string

func (*FragmentSpread) IsSelection

func (f *FragmentSpread) IsSelection()

func (*FragmentSpread) Location

func (f *FragmentSpread) Location() errors.Location

type InlineFragment

type InlineFragment struct {
	Kind          string          `json:"kind"`
	TypeCondition *Named          `json:"typeCondition"`
	Directives    []*Directive    `json:"directives"`
	SelectionSet  *SelectionSet   `json:"selectionSet"`
	Loc           errors.Location `json:"loc"`
}

Fragments can be defined inline within a selection set. This is done to conditionally include fields based on their runtime type. This feature of standard fragment inclusion was demonstrated in the query FragmentTyping example. We could accomplish the same thing using inline fragments.

query inlineFragmentTyping {

profiles(handles: ["zuck", "cocacola"]) {
  handle
  ... on User {
    friends {
      count
    }
  }
  ... on Page {
    likers {
      count
    }
  }
}

} Inline fragments may also be used to apply a directive to a group of fields. If the TypeCondition is omitted, an inline fragment is considered to be of the same type as the enclosing context.

query inlineFragmentNoType($expandedInfo: Boolean) {

user(handle: "zuck") {
  id
  name
  ... @include(if: $expandedInfo) {
    firstName
    lastName
    birthday
  }
}

}

func (*InlineFragment) GetKind

func (i *InlineFragment) GetKind() string

func (*InlineFragment) IsSelection

func (i *InlineFragment) IsSelection()

func (*InlineFragment) Location

func (i *InlineFragment) Location() errors.Location

type InputObjectDefinition

type InputObjectDefinition struct {
	Kind        string                  `json:"kind"`
	Desc        *StringValue            `json:"desc"`
	Name        *Name                   `json:"name"`
	Directives  []*Directive            `json:"directives"`
	InputFields []*InputValueDefinition `json:"inputFields"`
	Loc         errors.Location         `json:"loc"`
}

Fields may accept arguments to configure their behavior. These inputs are often scalars or enums, but they sometimes need to represent more complex values.

A GraphQL Input Object defines a set of input fields; the input fields are either scalars, enums, or other input objects. This allows arguments to accept arbitrarily complex structs.

In this example, an Input Object called Point2D describes x and y inputs:

input Point2D {

x: Float
y: Float

}

func (*InputObjectDefinition) GetKind

func (i *InputObjectDefinition) GetKind() string

func (*InputObjectDefinition) IsDefinition

func (i *InputObjectDefinition) IsDefinition()

func (*InputObjectDefinition) IsTypeDefinition

func (i *InputObjectDefinition) IsTypeDefinition()

func (*InputObjectDefinition) IsTypeSystemDefinition

func (i *InputObjectDefinition) IsTypeSystemDefinition()

func (*InputObjectDefinition) Location

func (i *InputObjectDefinition) Location() errors.Location

type InputObjectExtension

type InputObjectExtension struct {
	Name        *Name
	Directives  []*Directive
	InputFields []*InputValueDefinition
	Loc         errors.Location
}

Input object type extensions are used to represent an input object type which has been extended from some original input object type. For example, this might be used by a GraphQL service which is itself an extension of another GraphQL service.

func (*InputObjectExtension) GetKind

func (i *InputObjectExtension) GetKind() string

func (*InputObjectExtension) IsDefinition

func (i *InputObjectExtension) IsDefinition()

func (*InputObjectExtension) IsTypeExtension

func (i *InputObjectExtension) IsTypeExtension()

func (*InputObjectExtension) IsTypeSystemExtension

func (i *InputObjectExtension) IsTypeSystemExtension()

func (*InputObjectExtension) Location

func (i *InputObjectExtension) Location() errors.Location

type InputValueDefinition

type InputValueDefinition struct {
	Kind         string          `json:"kind"`
	Desc         *StringValue    `json:"desc"`
	Name         *Name           `json:"name"`
	Type         Type            `json:"type"`
	DefaultValue Value           `json:"defaultValue"`
	Directives   []*Directive    `json:"directives"`
	Loc          errors.Location `json:"loc"`
}

Object fields are conceptually functions which yield values. Occasionally object fields can accept arguments to further specify the return value. Object field arguments are defined as a list of all possible argument names and their expected input types.

All arguments defined within a field must not have a name which begins with "__" (two underscores), as this is used exclusively by GraphQL’s introspection system.

For example, a Person type with a picture field could accept an argument to determine what size of an image to return.

type Person {

name: String
picture(size: Int): Url

} GraphQL queries can optionally specify arguments to their fields to provide these arguments.

This example query:

{

name
picture(size: 600)

} May yield the result:

{

"name": "Mark Zuckerberg",
"picture": "http://some.cdn/picture_600.jpg"

} The type of an object field argument must be an input type (any type except an Object, Interface, or Union type).

func (*InputValueDefinition) GetKind

func (i *InputValueDefinition) GetKind() string

func (*InputValueDefinition) Location

func (i *InputValueDefinition) Location() errors.Location

type IntValue

type IntValue struct {
	Kind  string          `json:"kind"`
	Value string          `json:"value"`
	Loc   errors.Location `json:"loc"`
}

An IntValue is specified without a decimal point or exponent but may be negative (ex. -123). It must not have any leading 0.

An IntValue must not be followed by a Digit. In other words, an IntValue token is always the longest possible valid sequence. The source characters 12 cannot be interpreted as two tokens since 1 is followed by the Digit 2. This also means the source 00 is invalid since it can neither be interpreted as a single token nor two 0 tokens.

An IntValue must not be followed by a . or NameStart. If either . or ExponentIndicator follows then the token must only be interpreted as a possible FloatValue. No other NameStart character can follow. For example the sequences 0x123 and 123L have no valid lexical representations.

func (*IntValue) GetKind

func (i *IntValue) GetKind() string

func (*IntValue) GetValue

func (i *IntValue) GetValue() interface{}

func (*IntValue) Location

func (i *IntValue) Location() errors.Location

type InterfaceDefinition

type InterfaceDefinition struct {
	Kind       string             `json:"kind"`
	Desc       *StringValue       `json:"desc"`
	Name       *Name              `json:"name"`
	Interfaces []*Named           `json:"interfaces"`
	Directives []*Directive       `json:"directives"`
	Fields     []*FieldDefinition `json:"fields"`
	Loc        errors.Location    `json:"loc"`
}

GraphQL interfaces represent a list of named fields and their arguments. GraphQL objects and interfaces can then implement these interfaces which requires that the implementing type will define all fields defined by those interfaces.

Fields on a GraphQL interface have the same rules as fields on a GraphQL object; their type can be Scalar, Object, Enum, Interface, or Union, or any wrapping type whose base type is one of those five.

For example, an interface NamedEntity may describe a required field and types such as Person or Business may then implement this interface to guarantee this field will always exist.

Types may also implement multiple interfaces. For example, Business implements both the NamedEntity and ValuedEntity interfaces in the example below.

interface NamedEntity {

name: String

}

interface ValuedEntity {

value: Int

}

type Person implements NamedEntity {

name: String
age: Int

}

type Business implements NamedEntity & ValuedEntity {

name: String
value: Int
employeeCount: Int

}

func (*InterfaceDefinition) GetKind

func (i *InterfaceDefinition) GetKind() string

func (*InterfaceDefinition) IsDefinition

func (i *InterfaceDefinition) IsDefinition()

func (*InterfaceDefinition) IsTypeDefinition

func (i *InterfaceDefinition) IsTypeDefinition()

func (*InterfaceDefinition) IsTypeSystemDefinition

func (i *InterfaceDefinition) IsTypeSystemDefinition()

func (*InterfaceDefinition) Location

func (i *InterfaceDefinition) Location() errors.Location

type InterfaceExtension

type InterfaceExtension struct {
	Name       *Name
	Interfaces []*Named
	Directives []*Directive
	Fields     []*FieldDefinition
	Loc        errors.Location
}

Interface type extensions are used to represent an interface which has been extended from some original interface. For example, this might be used to represent common local data on many types, or by a GraphQL service which is itself an extension of another GraphQL service.

In this example, an extended data field is added to a NamedEntity type along with the types which implement it:

extend interface NamedEntity {

nickname: String

}

extend type Person {

nickname: String

}

extend type Business {

nickname: String

} Interface type extensions may choose not to add additional fields, instead only adding directives.

In this example, a directive is added to a NamedEntity type without adding fields:

extend interface NamedEntity @addedDirective

func (*InterfaceExtension) GetKind

func (i *InterfaceExtension) GetKind() string

func (*InterfaceExtension) IsDefinition

func (i *InterfaceExtension) IsDefinition()

func (*InterfaceExtension) IsTypeExtension

func (i *InterfaceExtension) IsTypeExtension()

func (*InterfaceExtension) IsTypeSystemExtension

func (i *InterfaceExtension) IsTypeSystemExtension()

func (*InterfaceExtension) Location

func (i *InterfaceExtension) Location() errors.Location

type List

type List struct {
	Kind string          `json:"kind"`
	Type Type            `json:"type"`
	Loc  errors.Location `json:"loc"`
}

func (*List) GetKind

func (l *List) GetKind() string

func (*List) Location

func (l *List) Location() errors.Location

func (*List) OfType

func (l *List) OfType() Type

func (*List) String

func (l *List) String() string

type ListValue

type ListValue struct {
	Kind   string          `json:"kind"`
	Loc    errors.Location `json:"loc"`
	Values []Value         `json:"values"`
}

Lists are ordered sequences of values wrapped in square‐brackets [ ]. The values of a List literal may be any value literal or variable (ex. [1, 2, 3]).

Commas are optional throughout GraphQL so trailing commas are allowed and repeated commas do not represent missing values.

func (*ListValue) GetKind

func (l *ListValue) GetKind() string

func (*ListValue) GetValue

func (l *ListValue) GetValue() interface{}

func (*ListValue) Location

func (l *ListValue) Location() errors.Location

type Name

type Name struct {
	Kind string          `json:"kind"`
	Name string          `json:"value"`
	Loc  errors.Location `json:"loc"`
}

func (*Name) GetKind

func (n *Name) GetKind() string

func (*Name) Location

func (n *Name) Location() errors.Location

type Named

type Named struct {
	Kind string          `json:"kind"`
	Name *Name           `json:"name"`
	Loc  errors.Location `json:"loc"`
}

func (*Named) GetKind

func (n *Named) GetKind() string

func (*Named) Location

func (n *Named) Location() errors.Location

func (*Named) String

func (n *Named) String() string

type Node

type Node interface {
	GetKind() string
	Location() errors.Location
}

type NonNull

type NonNull struct {
	Kind string          `json:"kind"`
	Type Type            `json:"type"`
	Loc  errors.Location `json:"loc"`
}

func (*NonNull) GetKind

func (n *NonNull) GetKind() string

func (*NonNull) Location

func (n *NonNull) Location() errors.Location

func (*NonNull) OfType

func (n *NonNull) OfType() Type

func (*NonNull) String

func (n *NonNull) String() string

type NullValue

type NullValue struct {
	Kind string          `json:"kind"`
	Loc  errors.Location `json:"loc"`
}

NullValue

func (*NullValue) GetKind

func (n *NullValue) GetKind() string

func (*NullValue) GetValue

func (n *NullValue) GetValue() interface{}

func (*NullValue) Location

func (n *NullValue) Location() errors.Location

type ObjectDefinition

type ObjectDefinition struct {
	Kind       string             `json:"kind"`
	Desc       *StringValue       `json:"desc"`
	Name       *Name              `json:"name"`
	Interfaces []*Named           `json:"interfaces"`
	Directives []*Directive       `json:"directives"`
	Fields     []*FieldDefinition `json:"fields"`
	Loc        errors.Location    `json:"loc"`
}

GraphQL queries are hierarchical and composed, describing a tree of information. While Scalar types describe the leaf values of these hierarchical queries, Objects describe the intermediate levels.

GraphQL Objects represent a list of named fields, each of which yield a value of a specific type. Object values should be serialized as ordered maps, where the queried field names (or aliases) are the keys and the result of evaluating the field is the value, ordered by the order in which they appear in the query.

All fields defined within an Object type must not have a name which begins with "__" (two underscores), as this is used exclusively by GraphQL’s introspection system.

For example, a type Person could be described as:

type Person {

name: String
age: Int
picture: Url

} Where name is a field that will yield a String value, and age is a field that will yield an Int value, and picture is a field that will yield a Url value.

A query of an object value must select at least one field. This selection of fields will yield an ordered map containing exactly the subset of the object queried, which should be represented in the order in which they were queried. Only fields that are declared on the object type may validly be queried on that object.

For example, selecting all the fields of Person:

{

name
age
picture

} Would yield the object:

{

"name": "Mark Zuckerberg",
"age": 30,
"picture": "http://some.cdn/picture.jpg"

} While selecting a subset of fields:

{

age
name

} Must only yield exactly that subset:

{

"age": 30,
"name": "Mark Zuckerberg"

} A field of an Object type may be a Scalar, Enum, another Object type, an Interface, or a Union. Additionally, it may be any wrapping type whose underlying base type is one of those five.

For example, the Person type might include a relationship:

type Person {

name: String
age: Int
picture: Url
relationship: Person

} Valid queries must supply a nested field set for a field that returns an object, so this query is not valid:

{

name
relationship

} However, this example is valid:

{

name
relationship {
  name
}

} And will yield the subset of each object type queried:

{

"name": "Mark Zuckerberg",
"relationship": {
  "name": "Priscilla Chan"
}

}

func (*ObjectDefinition) GetKind

func (o *ObjectDefinition) GetKind() string

func (*ObjectDefinition) IsDefinition

func (o *ObjectDefinition) IsDefinition()

func (*ObjectDefinition) IsTypeDefinition

func (o *ObjectDefinition) IsTypeDefinition()

func (*ObjectDefinition) IsTypeSystemDefinition

func (o *ObjectDefinition) IsTypeSystemDefinition()

func (*ObjectDefinition) Location

func (o *ObjectDefinition) Location() errors.Location

type ObjectExtension

type ObjectExtension struct {
	Name       *Name
	Interfaces []*Named
	Directives []*Directive
	Fields     []*FieldDefinition
	Loc        errors.Location
}

Object type extensions are used to represent a type which has been extended from some original type. For example, this might be used to represent local data, or by a GraphQL service which is itself an extension of another GraphQL service.

In this example, a local data field is added to a Story type:

extend type Story {

isHiddenLocally: Boolean

} Object type extensions may choose not to add additional fields, instead only adding interfaces or directives.

In this example, a directive is added to a User type without adding fields:

extend type User @addedDirective

func (*ObjectExtension) GetKind

func (o *ObjectExtension) GetKind() string

func (*ObjectExtension) IsDefinition

func (o *ObjectExtension) IsDefinition()

func (*ObjectExtension) IsTypeExtension

func (o *ObjectExtension) IsTypeExtension()

func (*ObjectExtension) IsTypeSystemExtension

func (o *ObjectExtension) IsTypeSystemExtension()

func (*ObjectExtension) Location

func (o *ObjectExtension) Location() errors.Location

type ObjectField

type ObjectField struct {
	Kind  string          `json:"kind"`
	Name  *Named          `json:"name"`
	Value Value           `json:"value"`
	Loc   errors.Location `json:"loc"`
}

func (*ObjectField) GetKind

func (o *ObjectField) GetKind() string

func (*ObjectField) Location

func (o *ObjectField) Location() errors.Location

type ObjectValue

type ObjectValue struct {
	Kind   string          `json:"kind"`
	Fields []*ObjectField  `json:"fields"`
	Loc    errors.Location `json:"loc"`
}

Input object literal values are unordered lists of keyed input values wrapped in curly‐braces { }. The values of an object literal may be any input value literal or variable (ex. { name: "Hello world", score: 1.0 }). We refer to literal representation of input objects as “object literals.”

Input object fields are unordered Input object fields may be provided in any syntactic order and maintain identical semantic meaning.

These two queries are semantically identical:

{

nearestThing(location: { lon: 12.43, lat: -53.211 })

} {

nearestThing(location: { lat: -53.211, lon: 12.43 })

}

func (*ObjectValue) GetKind

func (o *ObjectValue) GetKind() string

func (*ObjectValue) GetValue

func (o *ObjectValue) GetValue() interface{}

func (*ObjectValue) Location

func (o *ObjectValue) Location() errors.Location

type OperationDefinition

type OperationDefinition struct {
	Kind         string                `json:"kind"`
	Operation    OperationType         `json:"Operation"`
	Name         *Name                 `json:"name"`
	Vars         []*VariableDefinition `json:"variables"`
	Directives   []*Directive          `json:"directives"`
	SelectionSet *SelectionSet         `json:"selectionSet"`
	Loc          errors.Location       `json:"loc"`
}

Each operation is represented by an optional operation name and a selection set.

For example, this mutation operation might “like” a story and then retrieve the new number of likes:

mutation {

likeStory(storyID: 12345) {
  story {
    likeCount
  }
}

}

If a document contains only one query operation, and that query defines no variables and contains no directives, that operation may be represented in a short‐hand form which omits the query keyword and query name.

For example, this unnamed query operation is written via query shorthand.

{

field

}

func (*OperationDefinition) GetKind

func (o *OperationDefinition) GetKind() string

func (*OperationDefinition) IsDefinition

func (o *OperationDefinition) IsDefinition()

func (*OperationDefinition) Location

func (o *OperationDefinition) Location() errors.Location

type OperationType

type OperationType string

There are three types of operations that GraphQL models:

query – a read‐only fetch. mutation – a write followed by a fetch. subscription – a long‐lived request that fetches data in response to source events.

const (
	Query        OperationType = "QUERY"
	Mutation     OperationType = "MUTATION"
	Subscription OperationType = "SUBSCRIPTION"
)

type OperationTypeDefinition

type OperationTypeDefinition struct {
	Kind      string          `json:"kind"`
	Operation OperationType   `json:"operation"`
	Type      *Named          `json:"type"`
	Loc       errors.Location `json:"loc"`
}

A schema defines the initial root operation type for each kind of operation it supports: query, mutation, and subscription; this determines the place in the type system where those operations begin.

The query root operation type must be provided and must be an Object type.

The mutation root operation type is optional; if it is not provided, the service does not support mutations. If it is provided, it must be an Object type.

Similarly, the subscription root operation type is also optional; if it is not provided, the service does not support subscriptions. If it is provided, it must be an Object type.

The fields on the query root operation type indicate what fields are available at the top level of a GraphQL query. For example, a basic GraphQL query like:

query {

myName

} Is valid when the query root operation type has a field named “myName”.

type Query {

myName: String

} Similarly, the following mutation is valid if a mutation root operation type has a field named “setName”. Note that the query and mutation root types must be different types.

mutation {

setName(name: "Zuck") {
  newName
}

} When using the type system definition language, a document must include at most one schema definition.

In this example, a GraphQL schema is defined with both query and mutation root types:

schema {

query: MyQueryRootType
mutation: MyMutationRootType

}

type MyQueryRootType {

someField: String

}

type MyMutationRootType {

setSomeField(to: String): String

} Default Root Operation Operation Names While any type can be the root operation type for a GraphQL operation, the type system definition language can omit the schema definition when the query, mutation, and subscription root types are named Query, Mutation, and Subscription respectively.

Likewise, when representing a GraphQL schema using the type system definition language, a schema definition should be omitted if it only uses the default root operation type names.

This example describes a valid complete GraphQL schema, despite not explicitly including a schema definition. The Query type is presumed to be the query root operation type of the schema.

type Query {

someField: String

}

func (*OperationTypeDefinition) GetKind

func (o *OperationTypeDefinition) GetKind() string

func (*OperationTypeDefinition) Location

func (o *OperationTypeDefinition) Location() errors.Location

type ScalarDefinition

type ScalarDefinition struct {
	Kind       string          `json:"kind"`
	Desc       *StringValue    `json:"desc"`
	Name       *Name           `json:"name"`
	Directives []*Directive    `json:"directives"`
	Loc        errors.Location `json:"loc"`
}

Scalar types represent primitive leaf values in a GraphQL type system. GraphQL responses take the form of a hierarchical tree; the leaves of this tree are typically GraphQL Scalar types (but may also be Enum types or null values).

GraphQL provides a number of built‐in scalars (see below), but type systems can add additional scalars with semantic meaning. For example, a GraphQL system could define a scalar called Time which, while serialized as a string, promises to conform to ISO‐8601. When querying a field of type Time, you can then rely on the ability to parse the result with an ISO‐8601 parser and use a client‐specific primitive for time. Another example of a potentially useful custom scalar is Url, which serializes as a string, but is guaranteed by the server to be a valid URL.

For example:

scalar Time scalar Url

func (*ScalarDefinition) GetKind

func (s *ScalarDefinition) GetKind() string

func (*ScalarDefinition) IsDefinition

func (s *ScalarDefinition) IsDefinition()

func (*ScalarDefinition) IsTypeDefinition

func (s *ScalarDefinition) IsTypeDefinition()

func (*ScalarDefinition) IsTypeSystemDefinition

func (s *ScalarDefinition) IsTypeSystemDefinition()

func (*ScalarDefinition) Location

func (s *ScalarDefinition) Location() errors.Location

type ScalarExtension

type ScalarExtension struct {
	Name       *Name
	Directives []*Directive
	Loc        errors.Location
}

Scalar type extensions are used to represent a scalar type which has been extended from some original scalar type. For example, this might be used by a GraphQL tool or service which adds directives to an existing scalar.

Operation Validation Scalar type extensions have the potential to be invalid if incorrectly defined.

1.The named type must already be defined and must be a Scalar type. 2.Any non‐repeatable directives provided must not already apply to the original Scalar type.

func (*ScalarExtension) GetKind

func (s *ScalarExtension) GetKind() string

func (*ScalarExtension) IsDefinition

func (s *ScalarExtension) IsDefinition()

func (*ScalarExtension) IsTypeExtension

func (s *ScalarExtension) IsTypeExtension()

func (*ScalarExtension) IsTypeSystemExtension

func (s *ScalarExtension) IsTypeSystemExtension()

func (*ScalarExtension) Location

func (s *ScalarExtension) Location() errors.Location

type SchemaDefinition

type SchemaDefinition struct {
	Kind           string                     `json:"kind"`
	Desc           *StringValue               `json:"desc"`
	Directives     []*Directive               `json:"directives"`
	OperationTypes []*OperationTypeDefinition `json:"operationTypes"`
	Loc            errors.Location            `json:"loc"`
}

A GraphQL service’s collective type system capabilities are referred to as that service’s “schema”. A schema is defined in terms of the types and directives it supports as well as the root operation types for each kind of operation: query, mutation, and subscription; this determines the place in the type system where those operations begin.

A GraphQL schema must itself be internally valid. This section describes the rules for this validation process where relevant.

All types within a GraphQL schema must have unique names. No two provided types may have the same name. No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).

All directives within a GraphQL schema must have unique names.

All types and directives defined within a schema must not have a name which begins with "__" (two underscores), as this is used exclusively by GraphQL’s introspection system.

func (*SchemaDefinition) GetKind

func (s *SchemaDefinition) GetKind() string

func (*SchemaDefinition) IsDefinition

func (s *SchemaDefinition) IsDefinition()

func (*SchemaDefinition) IsTypeSystemDefinition

func (s *SchemaDefinition) IsTypeSystemDefinition()

func (*SchemaDefinition) Location

func (s *SchemaDefinition) Location() errors.Location

type SchemaExtension

type SchemaExtension struct {
	Directives    []*Directive
	RootOperation []*OperationTypeDefinition
	Loc           errors.Location
}

Schema extensions are used to represent a schema which has been extended from an original schema. For example, this might be used by a GraphQL service which adds additional operation types, or additional directives to an existing schema.

Schema Validation Schema extensions have the potential to be invalid if incorrectly defined.

1.The Schema must already be defined. 2.Any non‐repeatable directives provided must not already apply to the original Schema.

func (*SchemaExtension) GetKind

func (s *SchemaExtension) GetKind() string

func (*SchemaExtension) IsDefinition

func (s *SchemaExtension) IsDefinition()

func (*SchemaExtension) IsTypeSystemExtension

func (s *SchemaExtension) IsTypeSystemExtension()

func (*SchemaExtension) Location

func (s *SchemaExtension) Location() errors.Location

type Selection

type Selection interface {
	Node
	// non-op interface, just to identify the interface that implements Selection
	IsSelection()
}

type SelectionSet

type SelectionSet struct {
	Kind       string          `json:"kind"`
	Selections []Selection     `json:"selections"`
	Loc        errors.Location `json:"loc"`
}

An operation selects the set of information it needs, and will receive exactly that information and nothing more, avoiding over‐fetching and under‐fetching data.

{

id
firstName
lastName

} In this query, the id, firstName, and lastName fields form a selection set. Selection sets may also contain fragment references.

func (*SelectionSet) GetKind

func (s *SelectionSet) GetKind() string

func (*SelectionSet) Location

func (s *SelectionSet) Location() errors.Location

type StringValue

type StringValue struct {
	Kind  string          `json:"kind"`
	Value string          `json:"value"`
	Loc   errors.Location `json:"loc"`
}

Strings are sequences of characters wrapped in quotation marks (U+0022). (ex. "Hello World"). White space and other otherwise‐ignored characters are significant within a string value.

The empty string "" must not be followed by another " otherwise it would be interpreted as the beginning of a block string. As an example, the source """""" can only be interpreted as a single empty block string and not three empty strings.

func (*StringValue) GetKind

func (s *StringValue) GetKind() string

func (*StringValue) GetValue

func (s *StringValue) GetValue() interface{}

func (*StringValue) Location

func (s *StringValue) Location() errors.Location

type Type

type Type interface {
	Node
	String() string
}

GraphQL describes the types of data expected by query variables. Input types may be lists of another input type, or a non‐null variant of any other input type.

type TypeDefinition

type TypeDefinition interface {
	TypeSystemDefinition
	IsTypeDefinition()
}

The fundamental unit of any GraphQL Schema is the type. There are six kinds of named type definitions in GraphQL, and two wrapping types.

The most basic type is a Scalar. A scalar represents a primitive value, like a string or an integer. Oftentimes, the possible responses for a scalar field are enumerable. GraphQL offers an Enum type in those cases, where the type specifies the space of valid responses.

Scalars and Enums form the leaves in response trees; the intermediate levels are Object types, which define a set of fields, where each field is another type in the system, allowing the definition of arbitrary type hierarchies.

GraphQL supports two abstract types: interfaces and unions.

An Interface defines a list of fields; Object types and other Interface types which implement this Interface are guaranteed to implement those fields. Whenever a field claims it will return an Interface type, it will return a valid implementing Object type during execution.

A Union defines a list of possible types; similar to interfaces, whenever the type system claims a union will be returned, one of the possible types will be returned.

Finally, oftentimes it is useful to provide complex structs as inputs to GraphQL field arguments or variables; the Input Object type allows the schema to define exactly what data is expected.

type TypeExtension

type TypeExtension interface {
	TypeSystemExtension
	IsTypeExtension()
}

Operation extensions are used to represent a GraphQL type which has been extended from some original type. For example, this might be used by a local service to represent additional fields a GraphQL client only accesses locally.

type TypeSystemDefinition

type TypeSystemDefinition interface {
	Definition
	IsTypeSystemDefinition()
}

The GraphQL Operation system describes the capabilities of a GraphQL server and is used to determine if a query is valid. The type system also describes the input types of query variables to determine if values provided at runtime are valid.

The GraphQL language includes an IDL used to describe a GraphQL service’s type system. Tools may use this definition language to provide utilities such as client code generation or service boot‐strapping.

GraphQL tools which only seek to provide GraphQL query execution may choose not to parse TypeSystemDefinition.

A GraphQL Document which contains TypeSystemDefinition must not be executed; GraphQL execution services which receive a GraphQL Document containing type system definitions should return a descriptive error.

type TypeSystemExtension

type TypeSystemExtension interface {
	Definition
	IsTypeSystemExtension()
}

Operation system extensions are used to represent a GraphQL type system which has been extended from some original type system. For example, this might be used by a local service to represent data a GraphQL client only accesses locally, or by a GraphQL service which is itself an extension of another GraphQL service.

type UnionDefinition

type UnionDefinition struct {
	Kind       string          `json:"kind"`
	Desc       *StringValue    `json:"desc"`
	Name       *Name           `json:"name"`
	Directives []*Directive    `json:"directives"`
	Members    []*Named        `json:"members"`
	Loc        errors.Location `json:"loc"`
}

GraphQL Unions represent an object that could be one of a list of GraphQL Object types, but provides for no guaranteed fields between those types. They also differ from interfaces in that Object types declare what interfaces they implement, but are not aware of what unions contain them.

With interfaces and objects, only those fields defined on the type can be queried directly; to query other fields on an interface, typed fragments must be used. This is the same as for unions, but unions do not define any fields, so no fields may be queried on this type without the use of type refining fragments or inline fragments.

For example, we might define the following types:

union SearchResult = Photo | Person

type Person {

name: String
age: Int

}

type Photo {

height: Int
width: Int

}

type SearchQuery {

firstSearchResult: SearchResult

} When querying the firstSearchResult field of type SearchQuery, the query would ask for all fields inside of a fragment indicating the appropriate type. If the query wanted the name if the result was a Person, and the height if it was a photo, the following query is invalid, because the union itself defines no fields:

{

firstSearchResult {
  name
  height
}

} Instead, the query would be:

{

firstSearchResult {
  ... on Person {
    name
  }
  ... on Photo {
    height
  }
}

} Union members may be defined with an optional leading | character to aid formatting when representing a longer list of possible types:

union SearchResult =

| Photo
| Person

func (*UnionDefinition) GetKind

func (u *UnionDefinition) GetKind() string

func (*UnionDefinition) IsDefinition

func (u *UnionDefinition) IsDefinition()

func (*UnionDefinition) IsTypeDefinition

func (u *UnionDefinition) IsTypeDefinition()

func (*UnionDefinition) IsTypeSystemDefinition

func (u *UnionDefinition) IsTypeSystemDefinition()

func (*UnionDefinition) Location

func (u *UnionDefinition) Location() errors.Location

type UnionExtension

type UnionExtension struct {
	Name       *Name
	Directives []*Directive
	Members    []*Named
	Loc        errors.Location
}

Union type extensions are used to represent a union type which has been extended from some original union type. For example, this might be used to represent additional local data, or by a GraphQL service which is itself an extension of another GraphQL service.

func (*UnionExtension) GetKind

func (u *UnionExtension) GetKind() string

func (*UnionExtension) IsDefinition

func (u *UnionExtension) IsDefinition()

func (*UnionExtension) IsTypeExtension

func (u *UnionExtension) IsTypeExtension()

func (*UnionExtension) IsTypeSystemExtension

func (u *UnionExtension) IsTypeSystemExtension()

func (*UnionExtension) Location

func (u *UnionExtension) Location() errors.Location

type Value

type Value interface {
	Node
	GetValue() interface{}
}

Field and directive arguments accept input values of various literal primitives; input values can be scalars, enumeration values, lists, or input objects.

If not defined as constant (for example, in DefaultValue), input values can be specified as a variable. List and inputs objects may also contain variables (unless defined to be constant).

type Variable

type Variable struct {
	Kind string          `json:"kind"`
	Name *Name           `json:"name"`
	Loc  errors.Location `json:"loc"`
}

A GraphQL query can be parameterized with variables, maximizing query reuse, and avoiding costly string building in clients at runtime.

If not defined as constant (for example, in DefaultValue), a Variable can be supplied for an input value.

Variables must be defined at the top of an operation and are in scope throughout the execution of that operation.

In this example, we want to fetch a profile picture size based on the size of a particular device:

query getZuckProfile($devicePicSize: Int) {

user(id: 4) {
  id
  name
  profilePic(size: $devicePicSize)
}

} Values for those variables are provided to a GraphQL service along with a request so they may be substituted during execution. If providing JSON for the variables’ values, we could run this query and request profilePic of size 60 width:

{

"devicePicSize": 60

} Variable use within Fragments Query variables can be used within fragments. Query variables have global scope with a given operation, so a variable used within a fragment must be declared in any top‐level operation that transitively consumes that fragment. If a variable is referenced in a fragment and is included by an operation that does not define that variable, the operation cannot be executed.

func (*Variable) GetKind

func (v *Variable) GetKind() string

func (*Variable) GetValue

func (v *Variable) GetValue() interface{}

func (*Variable) Location

func (v *Variable) Location() errors.Location

type VariableDefinition

type VariableDefinition struct {
	Kind         string          `json:"kind"`
	Var          *Variable       `json:"variable"`
	Type         Type            `json:"type"`
	DefaultValue Value           `json:"defaultValue"`
	Directives   []*Directive    `json:"directives"`
	Loc          errors.Location `json:"loc"`
}

func (*VariableDefinition) GetKind

func (v *VariableDefinition) GetKind() string

func (*VariableDefinition) Location

func (v *VariableDefinition) Location() errors.Location

type WrappingType

type WrappingType interface {
	OfType() Type
}

All of the types so far are assumed to be both nullable and singular: e.g. a scalar string returns either null or a singular string.

A GraphQL schema may describe that a field represents a list of another type; the List type is provided for this reason, and wraps another type.

Similarly, the Non-Null type wraps another type, and denotes that the resulting value will never be null (and that an error cannot result in a null value).

These two types are referred to as “wrapping types”; non‐wrapping types are referred to as “named types”. A wrapping type has an underlying named type, found by continually unwrapping the type until a named type is found.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL