diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 02cafe21d..4c90aca04 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 requires exactly one +field be provided (and the value of that field must not be {null}): + +```graphql +input UserUniqueCondition @oneField { + id: ID + username: String + organizationAndEmail: OrganizationAndEmailInput +} +``` ## List @@ -1650,6 +1664,12 @@ 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 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: @@ -1778,3 +1798,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 9418a3b7c..2b90c8d44 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -141,6 +141,9 @@ type __Type { # should be non-null for ENUM only, must be null for the others enumValues(includeDeprecated: Boolean = false): [__EnumValue!] + # should be non-null for INPUT_OBJECT only, must be null for the others + requiresExactlyOneField: Boolean! + # should be non-null for INPUT_OBJECT only, must be null for the others inputFields: [__InputValue!] @@ -331,7 +334,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 7afcbb303..3dd802fcd 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 must not be null. ## Directives