From f97b8c566ae49405fce8b4c78c6ab2e85719db91 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Sat, 18 May 2019 10:12:26 +0100 Subject: [PATCH 1/5] Add specification changes for @oneField directive --- spec/Section 3 -- Type System.md | 46 ++++++++++++++++++++++++++++++ spec/Section 4 -- Introspection.md | 6 ++++ spec/Section 5 -- Validation.md | 18 ++++++++++++ 3 files changed, 70 insertions(+) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 9677a17f4..800a61001 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1440,6 +1440,20 @@ Input object type extensions have the potential to be invalid if incorrectly def the original Input Object. 5. Any directives provided must not already apply to the original Input Object type. +### Input Objects Requiring Exactly One Field + +A GraphQL schema may wish to represent a situation where an input could take +one of many different options. When using the type system definition language, +`@oneField` is used to indicate that the input object accepts exactly one +field: + +```graphql +input UserUniqueCondition @oneField { + id: ID + username: String + organizationAndEmail: OrganizationAndEmailInput +} +``` ## List @@ -1650,6 +1664,10 @@ GraphQL implementations that support the type system definition language must provide the `@deprecated` directive if representing deprecated portions of the schema. +GraphQL implementations that support the type system definition language must +provide the `@oneField` directive if representing input types that should +accept exactly one field. + Directives must only be used in the locations they are declared to belong in. In this example, a directive is defined which can be used to annotate a field: @@ -1778,3 +1796,31 @@ type ExampleType { oldField: String @deprecated(reason: "Use `newField`.") } ``` + +### @oneField + + +```graphql +directive @oneField on INPUT_OBJECT +``` + +The `@oneField` directive is used within the type system definition language to +indicate an input object where the user should specify exactly one field, such +as where the schema wishes to accept different types for an input. + +The `@oneField` directive does not accept any arguments. + +Any inputs of this type present in a query must provide one and only one field +from the input object, and that field (and only that field) is treated as +non-nullable for the purposes of validation. + +In this example type definition, media blocks can be of different types, and +these are enumerated via a `@oneField` input object. + +```graphql example +input MediaBlockInput @oneField { + post: PostInput + image: ImageInput + href: String +} +``` diff --git a/spec/Section 4 -- Introspection.md b/spec/Section 4 -- Introspection.md index 8a24e2882..9cf54bcce 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -142,6 +142,7 @@ type __Type { enumValues(includeDeprecated: Boolean = false): [__EnumValue!] # INPUT_OBJECT only + requiresExactlyOneField: Boolean! inputFields: [__InputValue!] # NON_NULL and LIST only @@ -331,7 +332,12 @@ Fields * `kind` must return `__TypeKind.INPUT_OBJECT`. * `name` must return a String. * `description` may return a String or {null}. +* `requiresExactlyOneField` must return a Boolean * `inputFields`: a list of `InputValue`. + * if `requiresExactlyOneField` is {true}: + * for each {inputValue} in {inputFields} + * the {type} of {inputValue} must not be Non-Null + * the {defaultValue} of {inputValue} must be {null} * All other fields must return {null}. diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index d16debb79..17b33cf78 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -1389,6 +1389,24 @@ arguments, an input object may have required fields. An input field is required if it has a non-null type and does not have a default value. Otherwise, the input object field is optional. +### Input Object With Requires Exactly One Field + +**Formal Specification** + + * For each Input Object in the document for which {requiresExactlyOneField} is {true}: + * Let {fields} be the fields provided by that Input Object. + * Let {fieldDefinitions} be the set of input field definitions of that Input Object. + * {fieldDefinitions} must contain exactly one entry + * For the sole {fieldDefinition} in {fieldDefinitions}: + * Let {fieldName} be the name of {fieldDefinition}. + * Let {field} be the input field in {fields} named {fieldName} + * Let {value} be the value of {field}. + * {value} must not be the {null} literal. + +**Explanatory Text** + +When an input object requires exactly one field, exactly one field must be +supplied and that field may not be null. ## Directives From d08eae1bee20781c9a2cad46067a6ee0a5a02286 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 23 May 2019 12:41:47 +0100 Subject: [PATCH 2/5] may -> must --- spec/Section 5 -- Validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 17b33cf78..ee5792b2b 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -1406,7 +1406,7 @@ input object field is optional. **Explanatory Text** When an input object requires exactly one field, exactly one field must be -supplied and that field may not be null. +supplied and that field must not be null. ## Directives From 8bba50b132c07ef574b210d01fec9bd03e3aa776 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Wed, 12 Jun 2019 17:23:43 +0100 Subject: [PATCH 3/5] Tweak wording: accepts -> requires --- 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 800a61001..a1e6c651f 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1444,8 +1444,8 @@ Input object type extensions have the potential to be invalid if incorrectly def A GraphQL schema may wish to represent a situation where an input could take one of many different options. When using the type system definition language, -`@oneField` is used to indicate that the input object accepts exactly one -field: +`@oneField` is used to indicate that the input object requires exactly one +field be provided (and the value of that field must not be {null}): ```graphql input UserUniqueCondition @oneField { @@ -1665,8 +1665,8 @@ provide the `@deprecated` directive if representing deprecated portions of the schema. GraphQL implementations that support the type system definition language must -provide the `@oneField` directive if representing input types that should -accept exactly one field. +provide the `@oneField` directive if representing input types that accept +exactly one field. Directives must only be used in the locations they are declared to belong in. In this example, a directive is defined which can be used to annotate a field: From 3c181d1c610ca9d0be1d142664ba2967e87087a3 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 13 Jun 2019 09:28:10 +0100 Subject: [PATCH 4/5] Tweak wording for when IDL directive is required --- spec/Section 3 -- Type System.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index a1e6c651f..c7327e08e 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1665,8 +1665,9 @@ provide the `@deprecated` directive if representing deprecated portions of the schema. GraphQL implementations that support the type system definition language must -provide the `@oneField` directive if representing input types that accept -exactly one field. +provide the `@oneField` directive if representing input types that implement +the [Input Objects Requiring Exactly One +Field](#input-objects-requiring-exactly-one-field) feature. Directives must only be used in the locations they are declared to belong in. In this example, a directive is defined which can be used to annotate a field: From bba008cc44a322f30da146b197464dbd14d3e36a Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Mon, 22 Jul 2019 10:09:18 +0100 Subject: [PATCH 5/5] Fix lint issue --- spec/Section 3 -- Type System.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 57c12545b..4c90aca04 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1666,8 +1666,9 @@ the schema. GraphQL implementations that support the type system definition language must provide the `@oneField` directive if representing input types that implement -the [Input Objects Requiring Exactly One -Field](#input-objects-requiring-exactly-one-field) feature. +the +[Input Objects Requiring Exactly One Field](#input-objects-requiring-exactly-one-field) +feature. Directives must only be used in the locations they are declared to belong in. In this example, a directive is defined which can be used to annotate a field: