Skip to content

Commit b4d9a09

Browse files
committed
@OneOf input objects
1 parent c385058 commit b4d9a09

File tree

3 files changed

+104
-3
lines changed

3 files changed

+104
-3
lines changed

Diff for: spec/Section 3 -- Type System.md

+83-3
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,28 @@ define arguments or contain references to interfaces and unions, neither of
14481448
which is appropriate for use as an input argument. For this reason, input
14491449
objects have a separate type in the system.
14501450

1451+
**Oneof Input Objects**
1452+
1453+
Oneof Input Objects are a special variant of Input Objects where the type
1454+
system asserts that exactly one of the fields must be set and non-null, all
1455+
others being omitted. This is useful for representing situations where an input
1456+
may be one of many different options.
1457+
1458+
When using the type system definition language, the `@oneOf` directive is used
1459+
to indicate that an Input Object is a Oneof Input Object (and thus requires
1460+
exactly one of its field be provided):
1461+
1462+
```graphql
1463+
input UserUniqueCondition @oneOf {
1464+
id: ID
1465+
username: String
1466+
organizationAndEmail: OrganizationAndEmailInput
1467+
}
1468+
```
1469+
1470+
In schema introspection, the `__Type.oneField` field will return {true} for
1471+
Oneof Input Objects, and {false} for all other Input Objects.
1472+
14511473
**Circular References**
14521474

14531475
Input Objects are allowed to reference other Input Objects as field types. A
@@ -1570,6 +1592,37 @@ Literal Value | Variables | Coerced Value
15701592
`{ b: $var }` | `{ var: null }` | Error: {b} must be non-null.
15711593
`{ b: 123, c: "xyz" }` | `{}` | Error: Unexpected field {c}
15721594

1595+
1596+
Following are examples of input coercion for a Oneof Input Object with a
1597+
`String` member field `a` and an `Int` member field `b`:
1598+
1599+
```graphql example
1600+
input ExampleInputTagged @oneOf {
1601+
a: String
1602+
b: Int
1603+
}
1604+
```
1605+
1606+
Literal Value | Variables | Coerced Value
1607+
------------------------ | ----------------------- | ---------------------------
1608+
`{ a: "abc", b: 123 }` | `{}` | Error: Exactly one key must be specified
1609+
`{ a: null, b: 123 }` | `{}` | Error: Exactly one key must be specified
1610+
`{ b: 123 }` | `{}` | `{ b: 123 }`
1611+
`{ a: $var, b: 123 }` | `{ var: null }` | Error: Exactly one key must be specified
1612+
`{ a: $var, b: 123 }` | `{}` | `{ b: 123 }`
1613+
`{ b: $var }` | `{ var: 123 }` | `{ b: 123 }`
1614+
`$var` | `{ var: { b: 123 } }` | `{ b: 123 }`
1615+
`"abc123"` | `{}` | Error: Incorrect value
1616+
`$var` | `{ var: "abc123" } }` | Error: Incorrect value
1617+
`{ a: "abc", b: "123" }` | `{}` | Error: Exactly one key must be specified
1618+
`{ b: "123" }` | `{}` | Error: Incorrect value for member field {b}
1619+
`{ a: "abc" }` | `{}` | `{ a: "abc" }`
1620+
`{ b: $var }` | `{}` | Error: No keys were specified
1621+
`$var` | `{ var: { a: "abc" } }` | `{ a: "abc" }`
1622+
`{ a: "abc", b: null }` | `{}` | Error: Exactly one key must be specified
1623+
`{ b: $var }` | `{ var: null }` | Error: Value for member field {b} must be non-null
1624+
`{ b: 123, c: "xyz" }` | `{}` | Error: Exactly one key must be specified
1625+
15731626
**Type Validation**
15741627

15751628
1. An Input Object type must define one or more input fields.
@@ -1580,11 +1633,13 @@ Literal Value | Variables | Coerced Value
15801633
characters {"__"} (two underscores).
15811634
3. The input field must accept a type where {IsInputType(inputFieldType)}
15821635
returns {true}.
1636+
4. If the Input Object is a Oneof Input Object then:
1637+
1. The type of the input field must be nullable.
1638+
2. The input field must not have a default value.
15831639
3. If an Input Object references itself either directly or through referenced
15841640
Input Objects, at least one of the fields in the chain of references must be
15851641
either a nullable or a List type.
15861642

1587-
15881643
### Input Object Extensions
15891644

15901645
InputObjectTypeExtension :
@@ -1605,6 +1660,10 @@ Input object type extensions have the potential to be invalid if incorrectly def
16051660
the original Input Object.
16061661
4. Any non-repeatable directives provided must not already apply to the
16071662
original Input Object type.
1663+
5. If the original Input Object is a Oneof Input Object then:
1664+
1. All fields of the Input Object type extension must be nullable.
1665+
2. All fields of the Input Object type extension must not have default
1666+
values.
16081667

16091668

16101669
## List
@@ -1815,8 +1874,12 @@ by a validator, executor, or client tool such as a code generator.
18151874
GraphQL implementations should provide the `@skip` and `@include` directives.
18161875

18171876
GraphQL implementations that support the type system definition language must
1818-
provide the `@deprecated` directive if representing deprecated portions of
1819-
the schema.
1877+
provide:
1878+
1879+
- the `@deprecated` directive if representing deprecated portions of the
1880+
schema;
1881+
- the `@oneOf` directive if representing types that require exactly one field
1882+
(i.e. Oneof Input Objects).
18201883

18211884
**Custom Directives**
18221885

@@ -1980,3 +2043,20 @@ type ExampleType {
19802043
oldField: String @deprecated(reason: "Use `newField`.")
19812044
}
19822045
```
2046+
2047+
### @oneOf
2048+
2049+
```graphql
2050+
directive @oneOf on INPUT_OBJECT
2051+
```
2052+
2053+
The `@oneOf` directive is used within the type system definition language
2054+
to indicate an Input Object is a Oneof Input Object.
2055+
2056+
```graphql example
2057+
input UserUniqueCondition @oneOf {
2058+
id: ID
2059+
username: String
2060+
organizationAndEmail: OrganizationAndEmailInput
2061+
}
2062+
```

Diff for: spec/Section 4 -- Introspection.md

+5
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ type __Type {
147147

148148
# should be non-null for NON_NULL and LIST only, must be null for the others
149149
ofType: __Type
150+
151+
# should be non-null for INPUT_OBJECT only
152+
oneField: Boolean
150153
}
151154

152155
type __Field {
@@ -336,6 +339,8 @@ Fields
336339
* `name` must return a String.
337340
* `description` may return a String or {null}.
338341
* `inputFields`: a list of `InputValue`.
342+
* `oneField` must return {true} for Oneof Input Objects, {false} for all other
343+
Input Objects.
339344
* All other fields must return {null}.
340345

341346

Diff for: spec/Section 5 -- Validation.md

+16
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,22 @@ arguments, an input object may have required fields. An input field is required
14241424
if it has a non-null type and does not have a default value. Otherwise, the
14251425
input object field is optional.
14261426

1427+
### Oneof Input Object Has Exactly One Field
1428+
1429+
**Formal Specification**
1430+
1431+
* For each Oneof Input Object in the document:
1432+
* Let {fields} be the fields provided by that Oneof Input Object.
1433+
* {fields} must contain exactly one entry.
1434+
* For the sole {field} in {fields}:
1435+
* Let {value} be the value of {field}.
1436+
* {value} must not be the {null} literal.
1437+
1438+
**Explanatory Text**
1439+
1440+
Oneof Input Objects require that exactly one field must be supplied and that
1441+
field must not be null.
1442+
14271443

14281444
## Directives
14291445

0 commit comments

Comments
 (0)