@@ -422,6 +422,7 @@ FieldsInSetCanMerge(set):
422422 {set} including visiting fragments and inline fragments.
423423- Given each pair of members {fieldA} and {fieldB} in {fieldsForName}:
424424 - {SameResponseShape(fieldA, fieldB)} must be true.
425+ - {SameStreamDirective(fieldA, fieldB)} must be true.
425426 - If the parent types of {fieldA} and {fieldB} are equal or if either is not
426427 an Object Type:
427428 - {fieldA} and {fieldB} must have identical field names.
@@ -456,6 +457,16 @@ SameResponseShape(fieldA, fieldB):
456457 - If {SameResponseShape(subfieldA, subfieldB)} is {false}, return {false}.
457458- Return {true}.
458459
460+ SameStreamDirective(fieldA, fieldB):
461+
462+ - If neither {fieldA} nor {fieldB} has a directive named ` stream ` .
463+ - Return {true}.
464+ - If both {fieldA} and {fieldB} have a directive named ` stream ` .
465+ - Let {streamA} be the directive named ` stream ` on {fieldA}.
466+ - Let {streamB} be the directive named ` stream ` on {fieldB}.
467+ - If {streamA} and {streamB} have identical sets of arguments, return {true}.
468+ - Return {false}.
469+
459470Note: In prior versions of the spec the term "composite" was used to signal a
460471type that is either an Object, Interface or Union type.
461472
@@ -1521,6 +1532,174 @@ query ($foo: Boolean = true, $bar: Boolean = false) {
15211532}
15221533```
15231534
1535+ ### Defer And Stream Directives Are Used On Valid Root Field
1536+
1537+ ** Formal Specification **
1538+
1539+ - For every {directive} in a document.
1540+ - Let {directiveName} be the name of {directive}.
1541+ - Let {mutationType} be the root Mutation type in {schema}.
1542+ - Let {subscriptionType} be the root Subscription type in {schema}.
1543+ - If {directiveName} is "defer" or "stream":
1544+ - The parent type of {directive} must not be {mutationType} or
1545+ {subscriptionType}.
1546+
1547+ ** Explanatory Text**
1548+
1549+ The defer and stream directives are not allowed to be used on root fields of the
1550+ mutation or subscription type.
1551+
1552+ For example, the following document will not pass validation because ` @defer `
1553+ has been used on a root mutation field:
1554+
1555+ ``` raw graphql counter-example
1556+ mutation {
1557+ ... @defer {
1558+ mutationField
1559+ }
1560+ }
1561+ ```
1562+
1563+ ### Defer And Stream Directives Are Used On Valid Operations
1564+
1565+ ** Formal Specification **
1566+
1567+ - Let {subscriptionFragments} be the empty set.
1568+ - For each {operation} in a document:
1569+ - If {operation} is a subscription operation:
1570+ - Let {fragments} be every fragment referenced by that {operation}
1571+ transitively.
1572+ - For each {fragment} in {fragments}:
1573+ - Let {fragmentName} be the name of {fragment}.
1574+ - Add {fragmentName} to {subscriptionFragments}.
1575+ - For every {directive} in a document:
1576+ - If {directiveName} is not "defer" or "stream":
1577+ - Continue to the next {directive}.
1578+ - Let {ancestor} be the ancestor operation or fragment definition of
1579+ {directive}.
1580+ - If {ancestor} is a fragment definition:
1581+ - If the fragment name of {ancestor} is not present in
1582+ {subscriptionFragments}:
1583+ - Continue to the next {directive}.
1584+ - If {ancestor} is not a subscription operation:
1585+ - Continue to the next {directive}.
1586+ - Let {if} be the argument named "if" on {directive}.
1587+ - {if} must be defined.
1588+ - Let {argumentValue} be the value passed to {if}.
1589+ - {argumentValue} must be a variable, or the boolean value "false".
1590+
1591+ ** Explanatory Text**
1592+
1593+ The defer and stream directives can not be used to defer or stream data in
1594+ subscription operations. If these directives appear in a subscription operation
1595+ they must be disabled using the "if" argument. This rule will not permit any
1596+ defer or stream directives on a subscription operation that cannot be disabled
1597+ using the "if" argument.
1598+
1599+ For example, the following document will not pass validation because ` @defer `
1600+ has been used in a subscription operation with no "if" argument defined:
1601+
1602+ ``` raw graphql counter-example
1603+ subscription sub {
1604+ newMessage {
1605+ ... @defer {
1606+ body
1607+ }
1608+ }
1609+ }
1610+ ```
1611+
1612+ ### Defer And Stream Directive Labels Are Unique
1613+
1614+ ** Formal Specification **
1615+
1616+ - Let {labelValues} be an empty set.
1617+ - For every {directive} in the document:
1618+ - Let {directiveName} be the name of {directive}.
1619+ - If {directiveName} is "defer" or "stream":
1620+ - For every {argument} in {directive}:
1621+ - Let {argumentName} be the name of {argument}.
1622+ - Let {argumentValue} be the value passed to {argument}.
1623+ - If {argumentName} is "label":
1624+ - {argumentValue} must not be a variable.
1625+ - {argumentValue} must not be present in {labelValues}.
1626+ - Append {argumentValue} to {labelValues}.
1627+
1628+ ** Explanatory Text**
1629+
1630+ The ` @defer ` and ` @stream ` directives each accept an argument "label". This
1631+ label may be used by GraphQL clients to uniquely identify response payloads. If
1632+ a label is passed, it must not be a variable and it must be unique within all
1633+ other ` @defer ` and ` @stream ` directives in the document.
1634+
1635+ For example the following document is valid:
1636+
1637+ ``` graphql example
1638+ {
1639+ dog {
1640+ ... fragmentOne
1641+ ... fragmentTwo @defer (label : " dogDefer" )
1642+ }
1643+ pets @stream (label : " petStream" ) {
1644+ name
1645+ }
1646+ }
1647+
1648+ fragment fragmentOne on Dog {
1649+ name
1650+ }
1651+
1652+ fragment fragmentTwo on Dog {
1653+ owner {
1654+ name
1655+ }
1656+ }
1657+ ```
1658+
1659+ For example, the following document will not pass validation because the same
1660+ label is used in different ` @defer ` and ` @stream ` directives.:
1661+
1662+ ``` raw graphql counter-example
1663+ {
1664+ dog {
1665+ ...fragmentOne @defer(label: "MyLabel")
1666+ }
1667+ pets @stream(label: "MyLabel") {
1668+ name
1669+ }
1670+ }
1671+
1672+ fragment fragmentOne on Dog {
1673+ name
1674+ }
1675+ ```
1676+
1677+ ### Stream Directives Are Used On List Fields
1678+
1679+ ** Formal Specification**
1680+
1681+ - For every {directive} in a document.
1682+ - Let {directiveName} be the name of {directive}.
1683+ - If {directiveName} is "stream":
1684+ - Let {adjacent} be the AST node the directive affects.
1685+ - {adjacent} must be a List type.
1686+
1687+ ** Explanatory Text**
1688+
1689+ GraphQL directive locations do not provide enough granularity to distinguish the
1690+ type of fields used in a GraphQL document. Since the stream directive is only
1691+ valid on list fields, an additional validation rule must be used to ensure it is
1692+ used correctly.
1693+
1694+ For example, the following document will only pass validation if ` field ` is
1695+ defined as a List type in the associated schema.
1696+
1697+ ``` graphql counter-example
1698+ query {
1699+ field @stream (initialCount : 0 )
1700+ }
1701+ ```
1702+
15241703## Variables
15251704
15261705### Variable Uniqueness
0 commit comments