Description
Describe the bug
Schema:
schema {
query: Query
}
type Query {
loadFoo: Foo!
}
type Foo {
name: String!
}
"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer(
"Deferred when true."
if: Boolean,
"If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to."
label: String
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
I use @graphql-codegen/typescript-apollo-angular
for codegen.
When using this query:
query foos {
loadFoo {
... @defer {
name
}
}
}
, generate code (which works fine) and then try to run it, I get the following error:
ERROR ApolloError: Http failure during parsing for http://localhost:4200/graphql
at new ApolloError (index.js:28:28)
at QueryManager.js:673:19
at both (asyncMap.js:16:53)
at asyncMap.js:9:72
at new ZoneAwarePromise (zone.js:1411:21)
at Object.then (asyncMap.js:9:24)
at Object.error (asyncMap.js:18:26)
at notifySubscription (module.js:137:18)
at onNotify (module.js:176:3)
at SubscriptionObserver.error (module.js:229:5)
While digging deeper, you can find another error message:
{
"headers": {
"normalizedNames": {},
"lazyUpdate": null
},
"status": 200,
"statusText": "OK",
"url": "http://localhost:4200/graphql",
"ok": false,
"name": "HttpErrorResponse",
"message": "Http failure during parsing for http://localhost:4200/graphql",
"error": {
"error": {
"message": "No number after minus sign in JSON at position 3"
"stack: "SyntaxError: No number after minus sign in JSON at position 3
at JSON.parse (<anonymous>)
at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:22534:41)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:171)
at http://localhost:4200/vendor.js:34143:49
at AsyncStackTaggingZoneSpec.onInvokeTask (http://localhost:4200/vendor.js:34143:30)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:54)
at Object.onInvokeTask (http://localhost:4200/vendor.js:34454:25)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:54)
at Zone.runTask (http://localhost:4200/polyfills.js:8037:37)
at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:8312:26)"
},
"text": "\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"data\":{\"loadFoo\":{\"__typename\":\"Foo\"}},\"hasNext\":true}\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"incremental\":[{\"data\":{\"name\":\"Bar\",\"__typename\":\"Foo\"},\"path\":[\"loadFoo\"]}],\"hasNext\":false}\r\n-----\r\n"
}
}
Which might make sense, because the response is incremental. The Backends response looks like this (this is the multipart/mixed
format):
---
Content-Type: application/json; charset=utf-8
{"data":{"loadFoo":{"__typename":"Foo"}},"hasNext":true}
---
Content-Type: application/json; charset=utf-8
{"incremental":[{"data":{"name":"Bar","__typename":"Foo"},"path":["loadFoo"]}],"hasNext":false}
-----
If I try to use text/event-stream
the backend anwers like this:
event: next
data: {"data":{"sanctuaryById":{"kennels":[{"id":"ccce9657-fec8-4ce0-9d7e-0160e9cec514","name":"Test","__typename":"Kennel"}],"__typename":"Sanctuary"}},"hasNext":true}
event: next
data: {"incremental":[{"data":{"name":"Dingens","__typename":"Sanctuary"},"path":["sanctuaryById"]}],"hasNext":false}
event: complete
but then the Apollo Error looks like this:
{
"headers": {
"normalizedNames": {},
"lazyUpdate": null
},
"status": 200,
"statusText": "OK",
"url": "http://localhost:4200/graphql",
"ok": false,
"name": "HttpErrorResponse",
"message": "Http failure during parsing for http://localhost:4200/graphql",
"error": {
"error": {
"message": "Unexpected token 'e', "event: nex"... is not valid JSON"
"stack":"SyntaxError: Unexpected token 'e', "event: nex"... is not valid JSON
at JSON.parse (<anonymous>)
at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:22534:41)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:171)
at http://localhost:4200/vendor.js:34143:49
at AsyncStackTaggingZoneSpec.onInvokeTask (http://localhost:4200/vendor.js:34143:30)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:54)
at Object.onInvokeTask (http://localhost:4200/vendor.js:34454:25)
at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8235:54)
at Zone.runTask (http://localhost:4200/polyfills.js:8037:37)
at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:8312:26)"
},
"text": "event: next\ndata: {\"data\":{\"loadFoo\":{\"__typename\":\"Foo\"}},\"hasNext\":true}\n\nevent: next\ndata: {\"incremental\":[{\"data\":{\"name\":\"Bar\",\"__typename\":\"Foo\"},\"path\":[\"loadFoo\"]}],\"hasNext\":false}\n\nevent: complete\n\n"
}
}
I tested this with the react-client and it simply works. Maybe it's a bug in the codegen? I didn't use Codegen in the react test.
To Reproduce
Create a simple Backend with HotChocolate https://chillicream.com/docs/hotchocolate/v13 and defer any field. It doesn't work with the simplest case. If you want I can provide you one.
Expected behavior
Defer should work.
Environment:
├── @angular/[email protected]
├── @angular/[email protected]
├── @apollo/[email protected]
├── [email protected]
├── [email protected]
└── [email protected]
"@graphql-codegen/add": "^5.0.0",
"@graphql-codegen/cli": "^5.0.0",
"@graphql-codegen/typescript-apollo-angular": "^3.5.6",
"@graphql-codegen/typescript-operations": "^4.0.1",
Additional context