- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.2k
 
Spec edits for @defer/@stream #742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
42bd98a
              583acb6
              a4bbad6
              b4fb65c
              3257f19
              3cce3fa
              f81d745
              b0cae7f
              9449853
              c812890
              c1fefe4
              6dd9b79
              ebfefb6
              30674c8
              101516b
              80ff450
              b73af22
              f634192
              7eafac8
              83e058d
              5aa915b
              d7fe43a
              379f10c
              1ffad84
              21dd0bc
              3a569b6
              a596ead
              4543a47
              5a093cd
              8fa426e
              fcc6393
              aa22c5f
              089d06c
              a154bda
              67689c5
              9230085
              4bf09d0
              1499e64
              722de48
              c4bdfaf
              d84dd0b
              2248f35
              2fb409c
              66c3f7b
              9287b62
              e0c0ad9
              99baf54
              4931f7a
              da96e98
              aff1113
              fb3e05c
              039e4eb
              777c21b
              7626800
              d16a432
              979e581
              1207121
              6545a55
              4c2e3f9
              e4ee3eb
              22de5de
              c630301
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -422,6 +422,7 @@ FieldsInSetCanMerge(set): | |
| {set} including visiting fragments and inline fragments. | ||
| - Given each pair of members {fieldA} and {fieldB} in {fieldsForName}: | ||
| - {SameResponseShape(fieldA, fieldB)} must be true. | ||
| - {SameStreamDirective(fieldA, fieldB)} must be true. | ||
| - If the parent types of {fieldA} and {fieldB} are equal or if either is not | ||
| an Object Type: | ||
| - {fieldA} and {fieldB} must have identical field names. | ||
| 
          
            
          
           | 
    @@ -455,6 +456,16 @@ SameResponseShape(fieldA, fieldB): | |
| - If {SameResponseShape(subfieldA, subfieldB)} is false, return false. | ||
| - Return true. | ||
| 
     | 
||
| SameStreamDirective(fieldA, fieldB): | ||
| 
     | 
||
| - If neither {fieldA} nor {fieldB} has a directive named `stream`. | ||
| - Return true. | ||
| - If both {fieldA} and {fieldB} have a directive named `stream`. | ||
| - Let {streamA} be the directive named `stream` on {fieldA}. | ||
| - Let {streamB} be the directive named `stream` on {fieldB}. | ||
| - If {streamA} and {streamB} have identical sets of arguments, return true. | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if they have just different initialCount, shouldn't it be considered 'the same' case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was what was decided based on feedback from Facebook's implementation: graphql/graphql-js#2319 (comment) If multiple streams on the same field are needed, they can be aliased. Again, if this blocks certain use cases I think it can be explored in a follow up proposal.  | 
||
| - Return false. | ||
| 
     | 
||
| **Explanatory Text** | ||
| 
     | 
||
| If multiple field selections with the same response names are encountered during | ||
| 
          
            
          
           | 
    @@ -1517,6 +1528,174 @@ query ($foo: Boolean = true, $bar: Boolean = false) { | |
| } | ||
| ``` | ||
| 
     | 
||
| ### Defer And Stream Directives Are Used On Valid Root Field | ||
| 
     | 
||
| ** Formal Specification ** | ||
| 
     | 
||
| - For every {directive} in a document. | ||
| - Let {directiveName} be the name of {directive}. | ||
| - Let {mutationType} be the root Mutation type in {schema}. | ||
| - Let {subscriptionType} be the root Subscription type in {schema}. | ||
| - If {directiveName} is "defer" or "stream": | ||
| - The parent type of {directive} must not be {mutationType} or | ||
| {subscriptionType}. | ||
| 
     | 
||
| **Explanatory Text** | ||
| 
     | 
||
| The defer and stream directives are not allowed to be used on root fields of the | ||
| mutation or subscription type. | ||
| 
     | 
||
| For example, the following document will not pass validation because `@defer` | ||
| has been used on a root mutation field: | ||
| 
     | 
||
| ```raw graphql counter-example | ||
| mutation { | ||
| ... @defer { | ||
| mutationField | ||
| } | ||
| } | ||
| ``` | ||
| 
     | 
||
| ### Defer And Stream Directives Are Used On Valid Operations | ||
| 
     | 
||
| ** Formal Specification ** | ||
| 
     | 
||
| - Let {subscriptionFragments} be the empty set. | ||
| - For each {operation} in a document: | ||
| - If {operation} is a subscription operation: | ||
| - Let {fragments} be every fragment referenced by that {operation} | ||
| transitively. | ||
| - For each {fragment} in {fragments}: | ||
| - Let {fragmentName} be the name of {fragment}. | ||
| - Add {fragmentName} to {subscriptionFragments}. | ||
| - For every {directive} in a document: | ||
| - If {directiveName} is not "defer" or "stream": | ||
| - Continue to the next {directive}. | ||
| - Let {ancestor} be the ancestor operation or fragment definition of | ||
| {directive}. | ||
| - If {ancestor} is a fragment definition: | ||
| - If the fragment name of {ancestor} is not present in | ||
| {subscriptionFragments}: | ||
| - Continue to the next {directive}. | ||
| - If {ancestor} is not a subscription operation: | ||
| - Continue to the next {directive}. | ||
| - Let {if} be the argument named "if" on {directive}. | ||
| - {if} must be defined. | ||
| - Let {argumentValue} be the value passed to {if}. | ||
| - {argumentValue} must be a variable, or the boolean value "false". | ||
| 
     | 
||
| **Explanatory Text** | ||
| 
     | 
||
| The defer and stream directives can not be used to defer or stream data in | ||
| subscription operations. If these directives appear in a subscription operation | ||
| they must be disabled using the "if" argument. This rule will not permit any | ||
| defer or stream directives on a subscription operation that cannot be disabled | ||
| using the "if" argument. | ||
| 
     | 
||
| For example, the following document will not pass validation because `@defer` | ||
| has been used in a subscription operation with no "if" argument defined: | ||
| 
     | 
||
| ```raw graphql counter-example | ||
| subscription sub { | ||
| newMessage { | ||
| ... @defer { | ||
| body | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| 
     | 
||
| ### Defer And Stream Directive Labels Are Unique | ||
| 
     | 
||
| ** Formal Specification ** | ||
| 
     | 
||
| - Let {labelValues} be an empty set. | ||
| - For every {directive} in the document: | ||
| - Let {directiveName} be the name of {directive}. | ||
| - If {directiveName} is "defer" or "stream": | ||
| - For every {argument} in {directive}: | ||
| - Let {argumentName} be the name of {argument}. | ||
| - Let {argumentValue} be the value passed to {argument}. | ||
| - If {argumentName} is "label": | ||
| - {argumentValue} must not be a variable. | ||
| - {argumentValue} must not be present in {labelValues}. | ||
| - Append {argumentValue} to {labelValues}. | ||
| 
     | 
||
| **Explanatory Text** | ||
| 
     | 
||
| The `@defer` and `@stream` directives each accept an argument "label". This | ||
| label may be used by GraphQL clients to uniquely identify response payloads. If | ||
| a label is passed, it must not be a variable and it must be unique within all | ||
| other `@defer` and `@stream` directives in the document. | ||
| 
     | 
||
| For example the following document is valid: | ||
| 
     | 
||
| ```graphql example | ||
| { | ||
| dog { | ||
| ...fragmentOne | ||
| ...fragmentTwo @defer(label: "dogDefer") | ||
| } | ||
| pets @stream(label: "petStream") { | ||
| name | ||
| } | ||
| } | ||
| 
     | 
||
| fragment fragmentOne on Dog { | ||
| name | ||
| } | ||
| 
     | 
||
| fragment fragmentTwo on Dog { | ||
| owner { | ||
| name | ||
| } | ||
| } | ||
| ``` | ||
| 
     | 
||
| For example, the following document will not pass validation because the same | ||
| label is used in different `@defer` and `@stream` directives.: | ||
| 
     | 
||
| ```raw graphql counter-example | ||
| { | ||
| dog { | ||
| ...fragmentOne @defer(label: "MyLabel") | ||
| } | ||
| pets @stream(label: "MyLabel") { | ||
| name | ||
| } | ||
| } | ||
| 
     | 
||
| fragment fragmentOne on Dog { | ||
| name | ||
| } | ||
| ``` | ||
| 
     | 
||
| ### Stream Directives Are Used On List Fields | ||
| 
     | 
||
| **Formal Specification** | ||
| 
     | 
||
| - For every {directive} in a document. | ||
| - Let {directiveName} be the name of {directive}. | ||
| - If {directiveName} is "stream": | ||
| - Let {adjacent} be the AST node the directive affects. | ||
| - {adjacent} must be a List type. | ||
| 
     | 
||
| **Explanatory Text** | ||
| 
     | 
||
| GraphQL directive locations do not provide enough granularity to distinguish the | ||
| type of fields used in a GraphQL document. Since the stream directive is only | ||
| valid on list fields, an additional validation rule must be used to ensure it is | ||
| used correctly. | ||
| 
     | 
||
| For example, the following document will only pass validation if `field` is | ||
| defined as a List type in the associated schema. | ||
| 
     | 
||
| ```graphql counter-example | ||
| query { | ||
| field @stream(initialCount: 0) | ||
| } | ||
| ``` | ||
| 
     | 
||
| ## Variables | ||
| 
     | 
||
| ### Variable Uniqueness | ||
| 
          
            
          
           | 
    ||
Uh oh!
There was an error while loading. Please reload this page.