Skip to content

Add descriptions to executable documents | 2025 Update #1170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
13 changes: 7 additions & 6 deletions spec/Appendix B -- Grammar Summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ ExecutableDefinition :
- OperationDefinition
- FragmentDefinition

Description : StringValue

OperationDefinition :

- OperationType Name? VariablesDefinition? Directives? SelectionSet
- Description? OperationType Name? VariablesDefinition? Directives? SelectionSet
- SelectionSet

OperationType : one of `query` `mutation` `subscription`
Expand All @@ -174,8 +176,8 @@ FragmentSpread : ... FragmentName Directives?

InlineFragment : ... TypeCondition? Directives? SelectionSet

FragmentDefinition : fragment FragmentName TypeCondition Directives?
SelectionSet
FragmentDefinition : Description? fragment FragmentName TypeCondition
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use case for providing descriptions for a FragmentDefinition. Is this tailored to the case where we use a FragmentDefinition as a reusable selection-set across the codebase? Do we really want to encourage that? I'd think that with Fragment Arguments this could carry merit though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have it in Apollo Kotlin to add Kdoc to the generated models. Not 100% sure how many people use it. Probably not too many but I would still include it for consistency.

We have also APIs to load fragments from the cache so maybe having more contextual info about what is loaded could help.

Directives? SelectionSet

FragmentName : Name but not `on`

Expand Down Expand Up @@ -213,7 +215,8 @@ ObjectField[Const] : Name : Value[?Const]

VariablesDefinition : ( VariableDefinition+ )

VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
VariableDefinition : Description? Variable : Type DefaultValue?
Directives[Const]?

Variable : $ Name

Expand Down Expand Up @@ -268,8 +271,6 @@ SchemaExtension :

RootOperationTypeDefinition : OperationType : NamedType

Description : StringValue

TypeDefinition :

- ScalarTypeDefinition
Expand Down
85 changes: 80 additions & 5 deletions spec/Section 2 -- Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,77 @@ 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.

## Descriptions

Description : StringValue

Documentation is a first-class feature of GraphQL. GraphQL descriptions are
defined using the Markdown syntax (as specified by
[CommonMark](https://commonmark.org/)). Description strings (often
{BlockString}) occur immediately before the definition they describe.

Descriptions may appear before:

- Operation definitions (queries, mutations, subscriptions) in their full form
(not the shorthand form).
- Fragment definitions.
- Variable definitions within operation definitions.

```graphql example
"""
Request the current status of a time machine and its operator.
You can also check the status for a particular year.
**Warning:** certain years may trigger an anomaly in the space-time continuum.
"""
query GetTimeMachineStatus(
"The unique serial number of the time machine to inspect."
$machineId: ID!
"The year to check the status for."
$year: Int
) {
timeMachine(id: $machineId) {
...TimeMachineDetails
status(year: $year)
}
}

"Details about a time machine and its operator."
fragment TimeMachineDetails on TimeMachine {
id
model
lastMaintenance
operator {
name
licenseLevel
}
}
```

Descriptions are not permitted on the shorthand form of operations:

```graphql counter-example
"This description is invalid, because this is a shorthand operation definition"
{
timeMachine(id: "TM-1985") {
status
destination {
year
location
}
}
}
```

Note: Descriptions and comments in executable GraphQL documents are purely for
documentation purposes. They MUST NOT affect the execution, validation, or
response of a GraphQL document. It is safe to remove all descriptions and
comments from executable documents without changing their behavior or results.

## Operations

OperationDefinition :

- OperationType Name? VariablesDefinition? Directives? SelectionSet
- Description? OperationType Name? VariablesDefinition? Directives? SelectionSet
- SelectionSet

OperationType : one of `query` `mutation` `subscription`
Expand All @@ -298,6 +364,10 @@ For example, this mutation operation might "like" a story and then retrieve the
new number of likes:

```graphql example
"""
Mark story 12345 as "liked"
and return the updated number of likes on the story
"""
mutation {
likeStory(storyID: 12345) {
story {
Expand Down Expand Up @@ -523,8 +593,8 @@ which returns the result:

FragmentSpread : ... FragmentName Directives?

FragmentDefinition : fragment FragmentName TypeCondition Directives?
SelectionSet
FragmentDefinition : Description? fragment FragmentName TypeCondition
Directives? SelectionSet

FragmentName : Name but not `on`

Expand Down Expand Up @@ -570,6 +640,7 @@ query withFragments {
}
}

"""Common fields for a user's friends."""
fragment friendFields on User {
id
name
Expand Down Expand Up @@ -1181,7 +1252,8 @@ Variable : $ Name

VariablesDefinition : ( VariableDefinition+ )

VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
VariableDefinition : Description? Variable : Type DefaultValue?
Directives[Const]?

DefaultValue : = Value[Const]

Expand All @@ -1200,7 +1272,10 @@ In this example, we want to fetch a profile picture size based on the size of a
particular device:

```graphql example
query getZuckProfile($devicePicSize: Int) {
query getZuckProfile(
"""The size of the profile picture to fetch."""
$devicePicSize: Int
) {
user(id: 4) {
id
name
Expand Down
3 changes: 3 additions & 0 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ documentation of a GraphQL service remains consistent with its capabilities,
descriptions of GraphQL definitions are provided alongside their definitions and
made available via introspection.

Note: See Section 2, "Descriptions", for normative rules and additional details
on descriptions in executable documents.

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](https://commonmark.org/)). In the
Expand Down
6 changes: 6 additions & 0 deletions spec/Section 6 -- Execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ Note: GraphQL requests do not require any specific serialization format or
transport mechanism. Message serialization and transport mechanisms should be
chosen by the implementing service.

Note: Descriptions and comments in executable documents (operation definitions,
fragment definitions, and variable definitions) MUST be ignored during execution
and have no effect on the execution, validation, or response of a GraphQL
document. Descriptions and comments on executable documents MAY be used for
observability and logging purposes.

## Executing Requests

To execute a request, the executor must have a parsed {Document} and a selected
Expand Down