diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md index 8514811e0..db699fdd5 100644 --- a/STYLE_GUIDE.md +++ b/STYLE_GUIDE.md @@ -55,3 +55,8 @@ hyphens) should be capitalized, with the following exceptions: All elements in hyphenated words follow the same rules, e.g. headings may contain `Non-Null`, `Context-Free`, `Built-in` (`in` is a preposition, so is not capitalized). + +## Lists + +Lists can be written as full sentences or as fragments. Algorithms that appear +as lists, however, should be written in full sentences with proper punctuation. diff --git a/spec/Appendix B -- Grammar Summary.md b/spec/Appendix B -- Grammar Summary.md index 23ddf92d1..22c30704b 100644 --- a/spec/Appendix B -- Grammar Summary.md +++ b/spec/Appendix B -- Grammar Summary.md @@ -100,7 +100,7 @@ StringValue :: - `""` [lookahead != `"`] - `"` StringCharacter+ `"` -- `"""` BlockStringCharacter\* `"""` +- BlockString StringCharacter :: @@ -121,6 +121,8 @@ HexDigit :: one of EscapedCharacter :: one of `"` `\` `/` `b` `f` `n` `r` `t` +BlockString :: `"""` BlockStringCharacter\* `"""` + BlockStringCharacter :: - SourceCharacter but not `"""` or `\"""` diff --git a/spec/Section 2 -- Language.md b/spec/Section 2 -- Language.md index 4a9c6b399..dddcb68d2 100644 --- a/spec/Section 2 -- Language.md +++ b/spec/Section 2 -- Language.md @@ -806,7 +806,7 @@ StringValue :: - `""` [lookahead != `"`] - `"` StringCharacter+ `"` -- `"""` BlockStringCharacter\* `"""` +- BlockString StringCharacter :: @@ -827,6 +827,8 @@ HexDigit :: one of EscapedCharacter :: one of `"` `\` `/` `b` `f` `n` `r` `t` +BlockString :: `"""` BlockStringCharacter\* `"""` + BlockStringCharacter :: - SourceCharacter but not `"""` or `\"""` @@ -1007,7 +1009,11 @@ StringCharacter :: `\` EscapedCharacter | {`r`} | U+000D | carriage return | | {`t`} | U+0009 | horizontal tab | -StringValue :: `"""` BlockStringCharacter\* `"""` +StringValue :: BlockString + +- Return the _Unicode text_ by evaluating the {BlockString}. + +BlockString :: `"""` BlockStringCharacter\* `"""` - Let {rawValue} be the _Unicode text_ by concatenating the evaluation of all {BlockStringCharacter} (which may be an empty sequence). @@ -1114,7 +1120,7 @@ ListValue : [ Value+ ] - For each {Value+} - Let {value} be the result of evaluating {Value}. - Append {value} to {inputList}. -- Return {inputList} +- Return {inputList}. ### Input Object Values @@ -1162,7 +1168,7 @@ ObjectValue : { ObjectField+ } - Let {name} be {Name} in {field}. - Let {value} be the result of evaluating {Value} in {field}. - Add a field to {inputObject} of name {name} containing value {value}. -- Return {inputObject} +- Return {inputObject}. ## Variables diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 7c116bf81..58ed8d5cb 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -122,7 +122,7 @@ RootOperationTypeDefinition : OperationType : NamedType 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, +supports as well as the _root operation type_ for each kind of operation: query, mutation, and subscription; this determines the place in the type system where those operations begin. @@ -141,24 +141,24 @@ introspection system. ### Root Operation Types -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 +:: 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 {`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 +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 +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 {`query`}, {`mutation`}, and {`subscription`} root types must all be different types if provided. -The fields on the {`query`} root operation type indicate what fields are +The fields on the {`query`} _root operation type_ indicate what fields are available at the top level of a GraphQL query operation. For example, this example operation: @@ -169,7 +169,8 @@ query { } ``` -is only valid when the {`query`} root operation type has a field named "myName": +is only valid when the {`query`} _root operation type_ has a field named +"myName": ```graphql example type Query { @@ -177,8 +178,8 @@ type Query { } ``` -Similarly, the following mutation is only valid if the {`mutation`} root -operation type has a field named "setName". +Similarly, the following mutation is only valid if the {`mutation`} _root +operation type_ has a field named "setName". ```graphql example mutation { @@ -191,8 +192,8 @@ mutation { 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 -operation types: +In this example, a GraphQL schema is defined with both a query and mutation +_root operation type_: ```graphql example schema { @@ -211,18 +212,22 @@ type MyMutationRootType { **Default Root Operation Type 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. +:: The _default root type name_ for each {`query`}, {`mutation`}, and +{`subscription`} _root operation type_ are {"Query"}, {"Mutation"}, and +{"Subscription"} respectively. + +The type system definition language can omit the schema definition when each +_root operation type_ uses its respective _default root type name_ and no other +type uses any _default root type name_. 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. +language, a schema definition should be omitted if each _root operation type_ +uses its respective _default root type name_ and no other type uses any _default +root type name_. 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. +{`query`} _root operation type_ of the schema. ```graphql example type Query { @@ -230,6 +235,30 @@ type Query { } ``` +This example describes a valid GraphQL schema without a {`mutation`} _root +operation type_, even though it contains a type named {"Mutation"}. The schema +definition must be included, otherwise the {"Mutation"} type would be +incorrectly presumed to be the {`mutation`} _root operation type_ of the schema. + +```graphql example +schema { + query: Query +} + +type Query { + latestVirus: Virus +} + +type Virus { + name: String + mutations: [Mutation] +} + +type Mutation { + name: String +} +``` + ### Schema Extension SchemaExtension : @@ -325,7 +354,7 @@ IsInputType(type) : - Return IsInputType({unwrappedType}) - If {type} is a Scalar, Enum, or Input Object type: - Return {true} -- Return {false} +- Return {false}. IsOutputType(type) : @@ -334,7 +363,7 @@ IsOutputType(type) : - Return IsOutputType({unwrappedType}) - If {type} is a Scalar, Object, Interface, Union, or Enum type: - Return {true} -- Return {false} +- Return {false}. ### Type Extensions @@ -405,12 +434,17 @@ conform to its described rules. ```graphql example scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122") scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986") +scalar DateTime + @specifiedBy(url: "https://scalars.graphql.org/andimarek/date-time") ``` Custom *scalar specification URL*s should provide a single, stable format to avoid ambiguity. If the linked specification is in flux, the service should link to a fixed version rather than to a resource which might change. +Note: Some community-maintained custom scalar specifications are hosted at +[scalars.graphql.org](https://scalars.graphql.org/). + Custom *scalar specification URL*s should not be changed once defined. Doing so would likely disrupt tooling or could introduce breaking changes within the linked specification's contents. @@ -419,7 +453,9 @@ Built-in scalar types must not provide a _scalar specification URL_ as they are specified by this document. Note: Custom scalars should also summarize the specified format and provide -examples in their description. +examples in their description; see the GraphQL scalars +[implementation guide](https://scalars.graphql.org/implementation-guide) for +more guidance. **Result Coercion and Serialization** @@ -878,9 +914,11 @@ of rules must be adhered to by every Object type in a GraphQL schema. 4. For each argument of the field: 1. The argument must not have a name which begins with the characters {"\_\_"} (two underscores). - 2. The argument must accept a type where {IsInputType(argumentType)} + 2. The argument must have a unique name within that field; no two + arguments may share the same name. + 3. The argument must accept a type where {IsInputType(argumentType)} returns {true}. - 3. If argument type is Non-Null and a default value is not defined: + 4. If argument type is Non-Null and a default value is not defined: - The `@deprecated` directive must not be applied to this argument. 3. An object type may declare that it implements one or more unique interfaces. 4. An object type must be a super-set of all interfaces it implements: @@ -1228,7 +1266,9 @@ Interface types have the potential to be invalid if incorrectly defined. 4. For each argument of the field: 1. The argument must not have a name which begins with the characters {"\_\_"} (two underscores). - 2. The argument must accept a type where {IsInputType(argumentType)} + 2. The argument must have a unique name within that field; no two + arguments may share the same name. + 3. The argument must accept a type where {IsInputType(argumentType)} returns {true}. 3. An interface type may declare that it implements one or more unique interfaces, but may not implement itself. @@ -1756,8 +1796,9 @@ to denote a field that uses a Non-Null type like this: `name: String!`. **Nullable vs. Optional** Fields are _always_ optional within the context of a selection set, a field may -be omitted and the selection set is still valid. However fields that return -Non-Null types will never return the value {null} if queried. +be omitted and the selection set is still valid (so long as the selection set +does not become empty). However fields that return Non-Null types will never +return the value {null} if queried. Inputs (such as field arguments), are always optional by default. However a non-null input type is required. In addition to not accepting the value {null}, @@ -2004,7 +2045,9 @@ repeatable directives. 4. For each argument of the directive: 1. The argument must not have a name which begins with the characters {"\_\_"} (two underscores). - 2. The argument must accept a type where {IsInputType(argumentType)} returns + 2. The argument must have a unique name within that directive; no two + arguments may share the same name. + 3. The argument must accept a type where {IsInputType(argumentType)} returns {true}. ### @skip @@ -2110,6 +2153,9 @@ behavior of [custom scalar types](#sec-Scalars.Custom-Scalars). The URL should point to a human-readable specification of the data format, serialization, and coercion rules. It must not appear on built-in scalar types. +Note: Details on implementing a GraphQL scalar specification can be found in the +[scalars.graphql.org implementation guide](https://scalars.graphql.org/implementation-guide). + In this example, a custom scalar type for `UUID` is defined with a URL pointing to the relevant IETF specification. diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 3f9d7449f..0828febd9 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -810,7 +810,7 @@ ambiguous and invalid. which contains {argument}. - {arguments} must be the set containing only {argument}. -#### Required Arguments +### Required Arguments - For each Field, Fragment Spread or Directive in the document: - Let {arguments} be the arguments provided by the Field, Directive or @@ -1086,7 +1086,7 @@ is a validation error if the target of a spread is not defined. - For each {fragmentDefinition} in the document: - Let {visited} be the empty set. - - {DetectFragmentCycles(fragmentDefinition, visited)} + - {DetectFragmentCycles(fragmentDefinition, visited)}. DetectFragmentCycles(fragmentDefinition, visited): @@ -1095,7 +1095,7 @@ DetectFragmentCycles(fragmentDefinition, visited): - {visited} must not contain {spread}. - Let {nextVisited} be the set including {spread} and members of {visited}. - Let {nextFragmentDefinition} be the target of {spread}. - - {DetectFragmentCycles(nextFragmentDefinition, nextVisited)} + - {DetectFragmentCycles(nextFragmentDefinition, nextVisited)}. **Explanatory Text** diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index ca884744a..b703c9cd1 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -224,9 +224,8 @@ must receive no more events from that event stream. **Supporting Subscriptions at Scale** -Supporting subscriptions is a significant change for any GraphQL service. Query -and mutation operations are stateless, allowing scaling via cloning of GraphQL -service instances. Subscriptions, by contrast, are stateful and require +Query and mutation operations are stateless, allowing scaling via cloning of +GraphQL service instances. Subscriptions, by contrast, are stateful and require maintaining the GraphQL document, variables, and other context over the lifetime of the subscription. @@ -264,7 +263,7 @@ CreateSourceEventStream(subscription, schema, variableValues, initialValue): is unaffected if an alias is used. - Let {field} be the first entry in {fields}. - Let {argumentValues} be the result of {CoerceArgumentValues(subscriptionType, - field, variableValues)} + field, variableValues)}. - Let {fieldStream} be the result of running {ResolveFieldEventStream(subscriptionType, initialValue, fieldName, argumentValues)}.