# GraphQL : Standard
\[ [spec](https://spec.graphql.org/October2021/) | [site](http://graphql.org/) ]
- Language-agnostic, though the [reference implementation](https://github.com/graphql/graphql-js/) is in JavaScript.
- Transport-agnostic, though mostly used with HTTP with JSON payloads.
- Both schemas and queries are described in GraphQL "documents".
- Mutations are syntactically identical to queries, but are allowed (by convention) to have "side-effects".
- The root fields of the Mutation type are guaranteed to be called serially, rather than in parallel.
## Types
#### Terms
- **Abstract** — Interface and Union
- **Concrete** — Enum, Object, Scalar
- **Enum** — special kind of Scalar with explicit value set
- **Fields** — can take arguments (scalars and input types) and return any non-input type
- **Input** — like Object types, but contains input fields, and is used as arguments to fields
- **Input Fields** — cannot take arguments, and can only return scalars or other input types
- **Interface** — defines the set of fields an Object type must include to implement the Interface
- **Mutation** — starting point for all mutation operations
- **Object** — contains fields which can also be objects
- **Query** — starting point for all query operations
- **Root** — sometimes refers to the Query type, sometimes to any of the three root types (Query/Mutation/Subscription), which are Object types
- **Scalar** — Boolean, Float, ID (string), Int, String
- **Subscription** — starting point for all subscription operations
- **Union** — set of Object types that can be returned by a field
#### Syntax
- comments (`#`) are allowed
- newlines are optional except to terminate comments
- commas are optional
- names can be composed of: `A-Za-z0-9_` (don't start with `__`)
- types are nullable by default
- non-nullable type T expressed as: `T!`
- list of type T expressed as: `[T]`
- also non-nullable list of T: `[T]!`
- and list of non-nullable T: `[T!]`
- custom scalars are treated like strings, but *should* specify a human-readable reference
###### Scalars
```graphql
# scalar <name> @specifiedBy( url: "..." )
scalar Date @specifiedBy( url: "https://tools.ietf.org/html/rfc3339" )
# enum <name> { <values> }
enum LengthUnit { FOOT, METER }
```
###### Fields
```graphql
# <name>: <type>
height: Float
# <name>( <arg>: <type> ): <type>
height( unit: LengthUnit ): Float
# <name>( <arg>: <type> = <default> ): <type>
height( unit: LengthUnit = FOOT ): Float
```
###### Objects, Inputs, and Abstract
```graphql
# type <name> { <fields> }
type Starship { id: ID!, name: String!, model: String! }
# interface <name> { <fields> }
interface Character { id: ID!, name: String! }
# type <name> implements <interface> { <fields> }
type Person implements Character {
id: ID!
name: String!
species: String!
height( unit: LengthUnit = FOOT ): Float
}
# union <name> = <type> | ...
union SearchResult = Person | Starship
# input <name> { <fields> }
input ReviewInput { stars: Int, commentary String }
```
###### Root Types
```graphql
# schema { query: <type>[, mutation: <type>][, subscription: <type>] }
# optional if you stick with the default type names
schema { query: Query, mutation: Mutation }
# type <root-type> { <root-fields> }
# only required to define query root type
type Query {
hero: ID!
char( id: ID! ): Character
search( query: String! ): [ SearchResult! ]!
}
```
## Documents
#### Terms
- **GraphQL Document** — A string written in the GraphQL Schema Language that defines one or more Operations and Fragments.
- **Operation** — A single Query, Mutation, or Subscription that can be interpreted by a GraphQL execution engine.
- **Operation Type** — Either `query`, `mutation`, or `subscription`.
- **Operation Name** — (OPTIONAL) It’s useful to give your Operations meaningful names for debugging and logging.
- **Variable Definition** — The list of Variables (name and type) accepted by an Operation.
- **Variable** — A dynamic parameter passed to an Operation. Must be a Scalar, Enum, or Input Type. Values must be provided in a separate, transport-specific (usually JSON) variables dictionary.
- **Selection Set** — The set of fields requested in an Operation or nested within another field. (The `{ <fields> }` block.)
- **Field** — A field on the parent object. Can accept Input Arguments. Any field that returns an Object Type must contain a Selection Set on that field. (No `SELECT *`.)
- **Input Argument** — A value passed to a field's Resolver.
- **Fragment** — Fragments are the primary unit of composition, and allow for reuse of common Selection Sets. Can be Named or Inline, and are used inside Operations and other Fragments.
- **Fragment Definition** — Defines a Named Fragment.
- **Fragment Name** — The name of a Named Fragment. Used to refer to fragment in operations or other fragments, and in debugging/logging.
- **Named Fragment** — Defined separately, given a name so it can be used, and a Type Condition so it can be validated against the schema.
- **Inline Fragment** — Used to conditionally access fields on the Concrete Type underlying the Interface or Union Type.
- **Type Condition** — The `on <Type>` that indicates what Object, Interface, or Union Type a Fragment expects.
- **Spread Operator** — The `...` operator. Includes the contents of a Fragment into the parent Selection Set.
- **Directive** — An annotation on a field, Fragment, or Operation that affects how it is executed or returned.
- **Directive Argument** — Like Input Arguments, but are handled by the execution engine instead of being passed down to the field Resolver.
#### Syntax
###### Operation
```
# { <fields> }
{ hero } # operation type assumed to be "query"
# w/field alias
{ fool: hero }
# <OperationType> { <fields> }
query { hero }
# <OperationType> <OperationName> { <fields> }
query GetHero { hero }
# <OperationType> (
lt;Variable>: <Type>, ... ) { <fields> }
query ( $CharID: ID! ) { char( id: $CharID ) { name } }
# <OperationType> <OperationName>( lt;Variable>: <Type>, ... ) { <fields> }
query GetChar ( $CharID: ID! ) { char( id: $CharID ) { name } }
```
###### Named Fragments
```
# defining a fragment:
# fragment <name> <TypeCondition> { <fields> }
fragment CharFields on Character { id, name }
# using a fragment in field selection set:
query ( $CharID: ID! ) { char( id: $CharID ) { ...CharFields } }
```
###### Inline Fragments
```
# ... <TypeCondition> { <fields> }
query ( $CharID: ID! ) { char( id: $CharID ) {
name
... on Person { species }
} }
```
###### Directives
```
@include( if: lt;var> )
@skip( if: lt;var> )
# on a field:
<Field> <Directive> { <fields> }
# on a named fragment:
...<Fragment> <Directive>
# on an inline fragment:
... <TypeCondition> <Directive> { <fields> }
```
## Introspection
- We can ask GraphQL what types are available by querying the `__schema` field, always available on the Query Type.
- You can request `__typename`, a Meta Field, in any Selection Set to get the name of the Object Type at that point.
###### Introspection Types
```graphql
__Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive
```
###### Introspection Schema
```graphql
__schema
queryType
name
types
name
__type(name: <Name>)
description
fields
name
type
kind # ex: INTERFACE, LIST, NON_NULL, OBJECT, SCALAR
name
ofType # for "wrapper" types (LIST and NON_NULL)
# returns type of value contained within
```
## Transport (Best Practices)
- Service mounted at single endpoint (usually `/graphql`).
- Should handle both `GET` and `POST` methods, with three params:
- query — document containing one or more operations
- variables — encoded as JSON
- operationName — if query contains multiple named operations, specifies which one to execute
#### Request
- **GET:** `https://myapi/graphql?query=<GraphQLDocument>&variables=<Variables>&operationName=<OperationName>`
- **POST:** Use the `application/json` content type, and include a JSON-encoded body with the parameters.
#### Response
The response should be returned in the body of the request in JSON format.
- If there were no errors returned, the "errors" field should not be present on the response.
- If no data is returned, according to the GraphQL spec, the "data" field should only be included if the error occurred during execution.
```json
{
"data": { ... },
"errors": [ ... ]
}
```
## Execution
A Resolver function receives three arguments:
- *obj* — The previous (parent) object, which for a field on a Root Type is generally not used.
- *args* — The field's Input Arguments.
- *context* — A value provided to every Resolver with contextual information, like the DB handle or current user.