From df0d201795d827d7875e902446464536534af235 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 5 Apr 2024 09:47:14 +0100 Subject: [PATCH 1/7] Define Data Collections used in the spec --- spec/Appendix A -- Notation Conventions.md | 31 ++++++++++++++++++++++ spec/GraphQL.md | 8 ++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/spec/Appendix A -- Notation Conventions.md b/spec/Appendix A -- Notation Conventions.md index 2375f3d67..d24387e93 100644 --- a/spec/Appendix A -- Notation Conventions.md +++ b/spec/Appendix A -- Notation Conventions.md @@ -216,3 +216,34 @@ Fibonacci(number): Note: Algorithms described in this document are written to be easy to understand. Implementers are encouraged to include equivalent but optimized implementations. + +## Data Collections + +This specification describes the semantic properties of data collections using +types like "list", "set" and "map". These describe observable data collections +such as the result of applying a grammar and the inputs and outputs of +algorithms. They also describe unobservable data collections such as temporary +data internal to an algorithm. Each data collection type defines the operations +available, and whether values are unique or ordered. + +**List** + +:: The term _list_ describes a sequence of values which may not be unique. A +list is ordered unless explicitly stated otherwise (as an "unordered list"). For +clarity the term "ordered list" may be used when an order is semantically +important. + +**Set** + +:: The term _set_ describes a unique collection of values, where each value is +considered a "member" of that set. A set is unordered unless explicitly stated +otherwise (as an "ordered set"). For clarity the term "unordered set" may be +used when the lack of an order is semantically important. + +**Map** + +:: The term _map_ describes a collection of "entry" key and value pairs, where +the set of keys across all entries is unique but the values across all entries +may repeat. A map is unordered unless explicitly stated otherwise (as an +"ordered map"). For clarity the term "unordered map" may be used when the lack +of an order is semantically important. diff --git a/spec/GraphQL.md b/spec/GraphQL.md index fad6bcdbe..e39be12fe 100644 --- a/spec/GraphQL.md +++ b/spec/GraphQL.md @@ -92,10 +92,14 @@ Conformance requirements expressed as algorithms can be fulfilled by an implementation of this specification in any way as long as the perceived result is equivalent. Algorithms described in this document are written to be easy to understand. Implementers are encouraged to include equivalent but optimized -implementations. +implementations. Similarly, data collections such as _list_, _set_ and _map_ +also introduce conformance requirements. Implementers are free to use +alternative data collections as long as the perceived result remains equivalent. See [Appendix A](#sec-Appendix-Notation-Conventions) for more details about the -definition of algorithms and other notational conventions used in this document. +definition of algorithms and other notational conventions used in this document, +and [Appendix A: Data Collections](#sec-Data-Collections) for specifics of data +collections and their ordering. **Non-Normative Portions** From 368a48bae017c126b700d4db442b9f8d8090029c Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 5 Apr 2024 09:52:34 +0100 Subject: [PATCH 2/7] Add recommendation to preserve order where possible --- spec/Appendix A -- Notation Conventions.md | 8 ++++++++ spec/Section 4 -- Introspection.md | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/spec/Appendix A -- Notation Conventions.md b/spec/Appendix A -- Notation Conventions.md index d24387e93..4f98c7a20 100644 --- a/spec/Appendix A -- Notation Conventions.md +++ b/spec/Appendix A -- Notation Conventions.md @@ -247,3 +247,11 @@ the set of keys across all entries is unique but the values across all entries may repeat. A map is unordered unless explicitly stated otherwise (as an "ordered map"). For clarity the term "unordered map" may be used when the lack of an order is semantically important. + +**Preserving order** + +To improve legibility, when possible implementations should preserve observable +order for unordered data collections. For example, if applying a grammar to an +input string produces an unordered set, serializing that set (to a string or +other observable output) should produce the same order found in the original +input string. diff --git a/spec/Section 4 -- Introspection.md b/spec/Section 4 -- Introspection.md index d2ec33b6b..a5f5ad366 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -117,6 +117,17 @@ Tools built using GraphQL introspection should respect deprecation by discouraging deprecated use through information hiding or developer-facing warnings. +**Ordering** + +When possible, implementations should preserve observable order for unordered +data collections. For example, if a schema was produced from a source +{TypeSystemDocument} then introspection of fields, input fields, arguments, enum +values, directives, union members, implemented interfaces and so on should +produce the same order as found in the source. + +Note: This recommendation is to improve legibility and stability of schema +representations. + **Schema Introspection Schema** The schema introspection system is itself represented as a GraphQL schema. Below From d7d9e37ebd534b6ae6312c8a24384bac04b29267 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 5 Apr 2024 10:08:56 +0100 Subject: [PATCH 3/7] Be explicit about the ordering of data types --- spec/Section 3 -- Type System.md | 53 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 4f9356f0c..4deb3c2f2 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -302,17 +302,18 @@ 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. +`Object` types, which define an ordered 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. +An `Interface` defines an ordered set 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 +A `Union` defines a set of possible types; similar to interfaces, whenever the type system claims a union will be returned, one of the possible types will be returned. @@ -674,11 +675,11 @@ GraphQL operations are hierarchical and composed, describing a tree of information. While Scalar types describe the leaf values of these hierarchical operations, 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 -selected 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 _selection -set_. +GraphQL Objects represent an ordered set of named fields, each of which yield a +value of a specific type. Object values should be serialized as ordered maps, +where the selected 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 _selection set_. 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 @@ -920,7 +921,8 @@ of rules must be adhered to by every Object type in a GraphQL schema. returns {true}. 4. If argument type is Non-Null and a default value is not defined: 1. The `@deprecated` directive must not be applied to this argument. -3. An object type may declare that it implements one or more unique interfaces. +3. An object type may declare that it implements a set of one or more unique + interfaces. 4. An object type must be a super-set of all interfaces it implements: 1. Let this object type be {objectType}. 2. For each interface declared implemented as {interfaceType}, @@ -982,7 +984,7 @@ InputValueDefinition : Description? Name : Type DefaultValue? Directives[Const]? 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 +arguments are defined as an ordered set of all possible argument names and their expected input types. All arguments defined within a field must not have a name which begins with @@ -1093,9 +1095,10 @@ InterfaceTypeDefinition : - Description? interface Name ImplementsInterfaces? Directives[Const]? [lookahead != `{`] -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. +GraphQL interfaces represent an ordered set 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 @@ -1347,7 +1350,7 @@ UnionMemberTypes : - UnionMemberTypes | NamedType - = `|`? NamedType -GraphQL Unions represent an object that could be one of a list of GraphQL Object +GraphQL Unions represent an object that could be one of a set 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. @@ -1408,7 +1411,7 @@ A valid operation includes typed fragments (in this example, inline fragments): ``` Union members may be defined with an optional leading `|` character to aid -formatting when representing a longer list of possible types: +formatting when representing a longer set of possible types: ```raw graphql example union SearchResult = @@ -1547,9 +1550,9 @@ InputFieldsDefinition : { InputValueDefinition+ } 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. +A GraphQL Input Object defines an ordered set of named 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: @@ -1936,6 +1939,10 @@ 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. +Directives can accept arguments to further specify their behavior. Directive +arguments are defined as an ordered set of all possible argument names and their +expected input types. + **Built-in Directives** :: A _built-in directive_ is any directive defined within this specification. @@ -1983,7 +1990,7 @@ fragment SomeFragment on SomeType { ``` Directive locations may be defined with an optional leading `|` character to aid -formatting when representing a longer list of possible locations: +formatting when representing a longer set of possible locations: ```raw graphql example directive @example on From 7170d82a653034eb459db168f03686a6682d8470 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Wed, 12 Jun 2024 10:18:29 +0100 Subject: [PATCH 4/7] Interface fields do not need to be implemented in order. --- spec/Section 3 -- Type System.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 4deb3c2f2..ec4e92e96 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -310,8 +310,8 @@ GraphQL supports two abstract types: interfaces and unions. An `Interface` defines an ordered set 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. +fields (in any order). Whenever a field claims it will return an Interface type, +it will return a valid implementing Object type during execution. A `Union` defines a set of possible types; similar to interfaces, whenever the type system claims a union will be returned, one of the possible types will be From 602d3195723bc53973d96b1ac883f5ab92171efe Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Wed, 12 Jun 2024 10:22:36 +0100 Subject: [PATCH 5/7] Interfaces an object implements are ordered --- spec/Section 3 -- Type System.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index ec4e92e96..cb07751b4 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -921,8 +921,8 @@ of rules must be adhered to by every Object type in a GraphQL schema. returns {true}. 4. If argument type is Non-Null and a default value is not defined: 1. The `@deprecated` directive must not be applied to this argument. -3. An object type may declare that it implements a set of one or more unique - interfaces. +3. An object type may declare that it implements an ordered set of one or more + unique interfaces. 4. An object type must be a super-set of all interfaces it implements: 1. Let this object type be {objectType}. 2. For each interface declared implemented as {interfaceType}, From ce8c732d814f4fe609ddd7d52736d505e6067b1d Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Wed, 12 Jun 2024 10:23:59 +0100 Subject: [PATCH 6/7] Unions are ordered. --- spec/Section 3 -- Type System.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index cb07751b4..963794d08 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1350,10 +1350,10 @@ UnionMemberTypes : - UnionMemberTypes | NamedType - = `|`? NamedType -GraphQL Unions represent an object that could be one of a set 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. +GraphQL Unions represent an object that could be one of an ordered set 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 From da69309e7ad69c37aa62397345fb967a98990af0 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Mon, 1 Jul 2024 17:13:38 +0100 Subject: [PATCH 7/7] Clarify wording --- spec/Section 3 -- Type System.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 963794d08..04dd0a80c 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -921,8 +921,8 @@ of rules must be adhered to by every Object type in a GraphQL schema. returns {true}. 4. If argument type is Non-Null and a default value is not defined: 1. The `@deprecated` directive must not be applied to this argument. -3. An object type may declare that it implements an ordered set of one or more - unique interfaces. +3. An object type may declare that it implements one or more unique interfaces, + these interfaces form an ordered set. 4. An object type must be a super-set of all interfaces it implements: 1. Let this object type be {objectType}. 2. For each interface declared implemented as {interfaceType},