@@ -560,6 +560,7 @@ FieldsInSetCanMerge(set):
560560 {set} including visiting fragments and inline fragments.
561561- Given each pair of distinct members {fieldA} and {fieldB} in {fieldsForName}:
562562 - {SameResponseShape(fieldA, fieldB)} must be true.
563+ - {SameStreamDirective(fieldA, fieldB)} must be true.
563564 - If the parent types of {fieldA} and {fieldB} are equal or if either is not
564565 an Object Type:
565566 - {fieldA} and {fieldB} must have identical field names.
@@ -595,6 +596,16 @@ SameResponseShape(fieldA, fieldB):
595596 - If {SameResponseShape(subfieldA, subfieldB)} is {false}, return {false}.
596597- Return {true}.
597598
599+ SameStreamDirective(fieldA, fieldB):
600+
601+ - If neither {fieldA} nor {fieldB} has a directive named ` stream ` .
602+ - Return {true}.
603+ - If both {fieldA} and {fieldB} have a directive named ` stream ` .
604+ - Let {streamA} be the directive named ` stream ` on {fieldA}.
605+ - Let {streamB} be the directive named ` stream ` on {fieldB}.
606+ - If {streamA} and {streamB} have identical sets of arguments, return {true}.
607+ - Return {false}.
608+
598609Note: In prior versions of the spec the term "composite" was used to signal a
599610type that is either an Object, Interface or Union type.
600611
@@ -1695,6 +1706,174 @@ query ($foo: Boolean = true, $bar: Boolean = false) {
16951706}
16961707```
16971708
1709+ ### Defer And Stream Directives Are Used On Valid Root Field
1710+
1711+ ** Formal Specification **
1712+
1713+ - For every {directive} in a document.
1714+ - Let {directiveName} be the name of {directive}.
1715+ - Let {mutationType} be the root Mutation type in {schema}.
1716+ - Let {subscriptionType} be the root Subscription type in {schema}.
1717+ - If {directiveName} is "defer" or "stream":
1718+ - The parent type of {directive} must not be {mutationType} or
1719+ {subscriptionType}.
1720+
1721+ ** Explanatory Text**
1722+
1723+ The defer and stream directives are not allowed to be used on root fields of the
1724+ mutation or subscription type.
1725+
1726+ For example, the following document will not pass validation because ` @defer `
1727+ has been used on a root mutation field:
1728+
1729+ ``` raw graphql counter-example
1730+ mutation {
1731+ ... @defer {
1732+ mutationField
1733+ }
1734+ }
1735+ ```
1736+
1737+ ### Defer And Stream Directives Are Used On Valid Operations
1738+
1739+ ** Formal Specification **
1740+
1741+ - Let {subscriptionFragments} be the empty set.
1742+ - For each {operation} in a document:
1743+ - If {operation} is a subscription operation:
1744+ - Let {fragments} be every fragment referenced by that {operation}
1745+ transitively.
1746+ - For each {fragment} in {fragments}:
1747+ - Let {fragmentName} be the name of {fragment}.
1748+ - Add {fragmentName} to {subscriptionFragments}.
1749+ - For every {directive} in a document:
1750+ - If {directiveName} is not "defer" or "stream":
1751+ - Continue to the next {directive}.
1752+ - Let {ancestor} be the ancestor operation or fragment definition of
1753+ {directive}.
1754+ - If {ancestor} is a fragment definition:
1755+ - If the fragment name of {ancestor} is not present in
1756+ {subscriptionFragments}:
1757+ - Continue to the next {directive}.
1758+ - If {ancestor} is not a subscription operation:
1759+ - Continue to the next {directive}.
1760+ - Let {if} be the argument named "if" on {directive}.
1761+ - {if} must be defined.
1762+ - Let {argumentValue} be the value passed to {if}.
1763+ - {argumentValue} must be a variable, or the boolean value "false".
1764+
1765+ ** Explanatory Text**
1766+
1767+ The defer and stream directives can not be used to defer or stream data in
1768+ subscription operations. If these directives appear in a subscription operation
1769+ they must be disabled using the "if" argument. This rule will not permit any
1770+ defer or stream directives on a subscription operation that cannot be disabled
1771+ using the "if" argument.
1772+
1773+ For example, the following document will not pass validation because ` @defer `
1774+ has been used in a subscription operation with no "if" argument defined:
1775+
1776+ ``` raw graphql counter-example
1777+ subscription sub {
1778+ newMessage {
1779+ ... @defer {
1780+ body
1781+ }
1782+ }
1783+ }
1784+ ```
1785+
1786+ ### Defer And Stream Directive Labels Are Unique
1787+
1788+ ** Formal Specification **
1789+
1790+ - Let {labelValues} be an empty set.
1791+ - For every {directive} in the document:
1792+ - Let {directiveName} be the name of {directive}.
1793+ - If {directiveName} is "defer" or "stream":
1794+ - For every {argument} in {directive}:
1795+ - Let {argumentName} be the name of {argument}.
1796+ - Let {argumentValue} be the value passed to {argument}.
1797+ - If {argumentName} is "label":
1798+ - {argumentValue} must not be a variable.
1799+ - {argumentValue} must not be present in {labelValues}.
1800+ - Append {argumentValue} to {labelValues}.
1801+
1802+ ** Explanatory Text**
1803+
1804+ The ` @defer ` and ` @stream ` directives each accept an argument "label". This
1805+ label may be used by GraphQL clients to uniquely identify response payloads. If
1806+ a label is passed, it must not be a variable and it must be unique within all
1807+ other ` @defer ` and ` @stream ` directives in the document.
1808+
1809+ For example the following document is valid:
1810+
1811+ ``` graphql example
1812+ {
1813+ dog {
1814+ ... fragmentOne
1815+ ... fragmentTwo @defer (label : " dogDefer" )
1816+ }
1817+ pets @stream (label : " petStream" ) {
1818+ name
1819+ }
1820+ }
1821+
1822+ fragment fragmentOne on Dog {
1823+ name
1824+ }
1825+
1826+ fragment fragmentTwo on Dog {
1827+ owner {
1828+ name
1829+ }
1830+ }
1831+ ```
1832+
1833+ For example, the following document will not pass validation because the same
1834+ label is used in different ` @defer ` and ` @stream ` directives.:
1835+
1836+ ``` raw graphql counter-example
1837+ {
1838+ dog {
1839+ ...fragmentOne @defer(label: "MyLabel")
1840+ }
1841+ pets @stream(label: "MyLabel") {
1842+ name
1843+ }
1844+ }
1845+
1846+ fragment fragmentOne on Dog {
1847+ name
1848+ }
1849+ ```
1850+
1851+ ### Stream Directives Are Used On List Fields
1852+
1853+ ** Formal Specification**
1854+
1855+ - For every {directive} in a document.
1856+ - Let {directiveName} be the name of {directive}.
1857+ - If {directiveName} is "stream":
1858+ - Let {adjacent} be the AST node the directive affects.
1859+ - {adjacent} must be a List type.
1860+
1861+ ** Explanatory Text**
1862+
1863+ GraphQL directive locations do not provide enough granularity to distinguish the
1864+ type of fields used in a GraphQL document. Since the stream directive is only
1865+ valid on list fields, an additional validation rule must be used to ensure it is
1866+ used correctly.
1867+
1868+ For example, the following document will only pass validation if ` field ` is
1869+ defined as a List type in the associated schema.
1870+
1871+ ``` graphql counter-example
1872+ query {
1873+ field @stream (initialCount : 0 )
1874+ }
1875+ ```
1876+
16981877## Variables
16991878
17001879### Variable Uniqueness
0 commit comments