Skip to content

Commit

Permalink
@OneOf fields
Browse files Browse the repository at this point in the history
  • Loading branch information
benjie committed Feb 19, 2021
1 parent f6bd659 commit 39e593c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
53 changes: 50 additions & 3 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ of rules must be adhered to by every Object type in a GraphQL schema.
characters {"__"} (two underscores).
2. The argument must accept a type where {IsInputType(argumentType)}
returns {true}.
3. If the field is a Oneof Field:
1. The field must be nullable.
2. The field must not have a default value.
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:
1. Let this object type be {objectType}.
Expand Down Expand Up @@ -845,6 +848,8 @@ IsValidImplementation(type, implementedType):
2. Let {implementedFieldType} be the return type of {implementedField}.
3. {IsValidImplementationFieldType(fieldType, implementedFieldType)}
must be {true}.
6. {field} must be a Oneof Field if and only if {implementedField} is a
Oneof Field.

IsValidImplementationFieldType(fieldType, implementedFieldType):
1. If {fieldType} is a Non-Null type:
Expand Down Expand Up @@ -917,6 +922,30 @@ May yield the result:
The type of an object field argument must be an input type (any type except an
Object, Interface, or Union type).

**Oneof Fields**

Oneof Fields are a special variant of Object Type fields where the type system
asserts that exactly one of the field's arguments must be set and non-null, all
others being omitted. This is useful for representing situations where an input
may be one of many different options.

When using the type system definition language, the `@oneOf` directive is used
to indicate that a Field is a Oneof Field (and thus requires exactly one of its
arguments be provided):

```graphql
type Query {
findUser(
byID: ID
byUsername: String
byEmail: String
byRegistrationNumber: Int
): User @oneOf
}
```

In schema introspection, the `__Field.oneArgument` field will return {true} for
Oneof Fields, and {false} for all other Fields.

### Field Deprecation

Expand Down Expand Up @@ -1160,6 +1189,9 @@ Interface types have the potential to be invalid if incorrectly defined.
characters {"__"} (two underscores).
2. The argument must accept a type where {IsInputType(argumentType)}
returns {true}.
3. If the field is a Oneof Field:
1. The field must be nullable.
2. The field must not have a default value.
3. An interface type may declare that it implements one or more unique
interfaces, but may not implement itself.
4. An interface type must be a super-set of all interfaces it implements:
Expand Down Expand Up @@ -1880,7 +1912,8 @@ provide:
- the `@deprecated` directive if representing deprecated portions of the
schema;
- the `@oneOf` directive if representing types that require exactly one field
(i.e. Oneof Input Objects).
(i.e. Oneof Input Objects) or fields that require exactly one argument (i.e.
Oneof Fields).

**Custom Directives**

Expand Down Expand Up @@ -2048,11 +2081,14 @@ type ExampleType {
### @oneOf

```graphql
directive @oneOf on INPUT_OBJECT
directive @oneOf on INPUT_OBJECT | FIELD_DEFINITION
```

The `@oneOf` directive is used within the type system definition language
to indicate an Input Object is a Oneof Input Object.
to indicate:

- an Input Object is a Oneof Input Object, or
- an Object Type's Field is a Oneof Field.

```graphql example
input UserUniqueCondition @oneOf {
Expand All @@ -2061,3 +2097,14 @@ input UserUniqueCondition @oneOf {
organizationAndEmail: OrganizationAndEmailInput
}
```

```graphql example
type Query {
findUser(
byID: ID
byUsername: String
byEmail: String
byRegistrationNumber: Int
): User @oneOf
}
```
3 changes: 3 additions & 0 deletions spec/Section 4 -- Introspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ type __Field {
type: __Type!
isDeprecated: Boolean!
deprecationReason: String
oneArgument: Boolean!
}

type __InputValue {
Expand Down Expand Up @@ -385,6 +386,8 @@ Fields
* `isDeprecated` returns {true} if this field should no longer be used,
otherwise {false}.
* `deprecationReason` optionally provides a reason why this field is deprecated.
* `oneArgument` must return {true} for Oneof Fields, {false} for all other
Fields.


### The __InputValue Type
Expand Down
14 changes: 14 additions & 0 deletions spec/Section 5 -- Validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,20 @@ fragment missingRequiredArg on Arguments {
}
```

#### Oneof Fields Have Exactly One Argument

* For each Oneof Field in the document:
* Let {arguments} be the arguments provided by the Field.
* {arguments} must contain exactly one entry.
* For the sole {argument} in {arguments}:
* Let {value} be the value of {argument}.
* {value} must not be the {null} literal.

**Explanatory Text**

Oneof Fields require that exactly one argument must be supplied and that
argument must not be null.

## Fragments

### Fragment Declarations
Expand Down

0 comments on commit 39e593c

Please sign in to comment.