diff --git a/.changeset/healthy-lemons-pull.md b/.changeset/healthy-lemons-pull.md new file mode 100644 index 0000000000..3f26923f20 --- /dev/null +++ b/.changeset/healthy-lemons-pull.md @@ -0,0 +1,5 @@ +--- +'@urql/core': patch +--- + +Increase strictness of merging incrementally delivered result payloads (e.g. for `fetchSubscriptions: true` or other streamed results). `hasNext` will now be set to `false` early if a non-incremental response (e.g. from subscriptions) has errored, and the fetch transport will now abort early if `hasNext` has been forced to `false`. diff --git a/packages/core/src/internal/fetchSource.ts b/packages/core/src/internal/fetchSource.ts index 2b4f0a28fa..727e31f2c0 100644 --- a/packages/core/src/internal/fetchSource.ts +++ b/packages/core/src/internal/fetchSource.ts @@ -109,7 +109,6 @@ async function* parseEventStream( } catch (error) { if (!payload) throw error; } - if (payload && payload.hasNext === false) break; } } if (payload && payload.hasNext !== false) { @@ -140,7 +139,6 @@ async function* parseMultipartMixed( } catch (error) { if (!payload) throw error; } - if (payload && payload.hasNext === false) break; } if (payload && payload.hasNext !== false) { yield { hasNext: false }; @@ -204,6 +202,7 @@ async function* fetchOperation( : makeResult(operation, payload, response); networkMode = false; yield result; + if (result.hasNext === false) break; networkMode = true; } diff --git a/packages/core/src/utils/result.ts b/packages/core/src/utils/result.ts index cdcf0a589a..6ebf83569e 100644 --- a/packages/core/src/utils/result.ts +++ b/packages/core/src/utils/result.ts @@ -110,6 +110,8 @@ export const mergeResultPatch = ( } const withData = { data: prevResult.data }; + let hasNext = + nextResult.hasNext != null ? nextResult.hasNext : prevResult.hasNext; if (incremental) { for (let i = 0, l = incremental.length; i < l; i++) { const patch = incremental[i]; @@ -159,6 +161,9 @@ export const mergeResultPatch = ( (nextResult.errors as any[]) || (nextResult.payload && nextResult.payload.errors) || errors; + if (hasNext && errors.length && !nextResult.data) { + hasNext = false; + } } return { @@ -168,8 +173,7 @@ export const mergeResultPatch = ( ? new CombinedError({ graphQLErrors: errors, response }) : undefined, extensions: hasExtensions ? extensions : undefined, - hasNext: - nextResult.hasNext != null ? nextResult.hasNext : prevResult.hasNext, + hasNext, stale: false, }; };