@apollo/client 4.3.0-alpha.4 → 4.3.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +3 -7
  3. package/__cjs/cache/core/cache.cjs +1 -1
  4. package/__cjs/cache/core/cache.cjs.map +1 -1
  5. package/__cjs/cache/core/cache.d.cts +5 -1
  6. package/__cjs/cache/inmemory/entityStore.cjs +3 -3
  7. package/__cjs/cache/inmemory/inMemoryCache.cjs +0 -4
  8. package/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
  9. package/__cjs/cache/inmemory/inMemoryCache.d.cts +3 -4
  10. package/__cjs/cache/inmemory/key-extractor.cjs +1 -1
  11. package/__cjs/cache/inmemory/policies.cjs +4 -4
  12. package/__cjs/cache/inmemory/readFromStore.cjs +71 -54
  13. package/__cjs/cache/inmemory/readFromStore.cjs.map +1 -1
  14. package/__cjs/cache/inmemory/readFromStore.d.cts +1 -1
  15. package/__cjs/cache/inmemory/types.d.cts +1 -2
  16. package/__cjs/cache/inmemory/writeToStore.cjs +4 -4
  17. package/__cjs/core/ApolloClient.cjs +21 -22
  18. package/__cjs/core/ApolloClient.cjs.map +1 -1
  19. package/__cjs/core/ApolloClient.d.cts +44 -10
  20. package/__cjs/core/ObservableQuery.cjs +46 -5
  21. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  22. package/__cjs/core/ObservableQuery.d.cts +12 -1
  23. package/__cjs/core/QueryInfo.cjs +177 -154
  24. package/__cjs/core/QueryInfo.cjs.map +1 -1
  25. package/__cjs/core/QueryInfo.d.cts +13 -3
  26. package/__cjs/core/QueryManager.cjs +49 -27
  27. package/__cjs/core/QueryManager.cjs.map +1 -1
  28. package/__cjs/core/RefetchEventManager.cjs +3 -3
  29. package/__cjs/core/dataStateErrorCache.cjs +12 -0
  30. package/__cjs/core/dataStateErrorCache.cjs.map +1 -0
  31. package/__cjs/core/dataStateErrorCache.d.cts +3 -0
  32. package/__cjs/core/types.d.cts +2 -0
  33. package/__cjs/incremental/handlers/graphql17Alpha9.cjs +34 -11
  34. package/__cjs/incremental/handlers/graphql17Alpha9.cjs.map +1 -1
  35. package/__cjs/incremental/handlers/graphql17Alpha9.d.cts +26 -3
  36. package/__cjs/incremental/types.d.cts +41 -3
  37. package/__cjs/invariantErrorCodes.cjs +50 -31
  38. package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
  39. package/__cjs/react/hooks/useBackgroundQuery.d.cts +100 -47
  40. package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
  41. package/__cjs/react/hooks/useLazyQuery.d.cts +26 -20
  42. package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
  43. package/__cjs/react/hooks/useLoadableQuery.d.cts +23 -15
  44. package/__cjs/react/hooks/useMutation.cjs.map +1 -1
  45. package/__cjs/react/hooks/useMutation.d.cts +10 -7
  46. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  47. package/__cjs/react/hooks/useQuery.d.cts +74 -32
  48. package/__cjs/react/hooks/useQueryRefHandlers.cjs.map +1 -1
  49. package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
  50. package/__cjs/react/hooks/useSuspenseQuery.d.cts +83 -34
  51. package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
  52. package/__cjs/react/internal/types.d.cts +14 -3
  53. package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
  54. package/__cjs/react/query-preloader/createQueryPreloader.d.cts +20 -5
  55. package/__cjs/testing/core/mocking/mockLink.cjs +21 -1
  56. package/__cjs/testing/core/mocking/mockLink.cjs.map +1 -1
  57. package/__cjs/testing/core/mocking/mockLink.d.cts +1 -2
  58. package/__cjs/utilities/internal/addDeferFragmentLabels.cjs +33 -0
  59. package/__cjs/utilities/internal/addDeferFragmentLabels.cjs.map +1 -0
  60. package/__cjs/utilities/internal/addDeferFragmentLabels.d.cts +3 -0
  61. package/__cjs/utilities/internal/getDirectiveArgValue.cjs +19 -0
  62. package/__cjs/utilities/internal/getDirectiveArgValue.cjs.map +1 -0
  63. package/__cjs/utilities/internal/getDirectiveArgValue.d.cts +9 -0
  64. package/__cjs/utilities/internal/index.cjs +6 -2
  65. package/__cjs/utilities/internal/index.cjs.map +1 -1
  66. package/__cjs/utilities/internal/index.d.cts +2 -0
  67. package/__cjs/version.cjs +1 -1
  68. package/cache/core/cache.d.ts +5 -1
  69. package/cache/core/cache.js +1 -1
  70. package/cache/core/cache.js.map +1 -1
  71. package/cache/inmemory/entityStore.js +3 -3
  72. package/cache/inmemory/inMemoryCache.d.ts +3 -4
  73. package/cache/inmemory/inMemoryCache.js +1 -5
  74. package/cache/inmemory/inMemoryCache.js.map +1 -1
  75. package/cache/inmemory/key-extractor.js +1 -1
  76. package/cache/inmemory/policies.js +4 -4
  77. package/cache/inmemory/readFromStore.d.ts +1 -1
  78. package/cache/inmemory/readFromStore.js +72 -55
  79. package/cache/inmemory/readFromStore.js.map +1 -1
  80. package/cache/inmemory/types.d.ts +1 -2
  81. package/cache/inmemory/types.js.map +1 -1
  82. package/cache/inmemory/writeToStore.js +4 -4
  83. package/core/ApolloClient.d.ts +44 -10
  84. package/core/ApolloClient.js +21 -22
  85. package/core/ApolloClient.js.map +1 -1
  86. package/core/ObservableQuery.d.ts +12 -1
  87. package/core/ObservableQuery.js +46 -5
  88. package/core/ObservableQuery.js.map +1 -1
  89. package/core/QueryInfo.d.ts +13 -3
  90. package/core/QueryInfo.js +173 -154
  91. package/core/QueryInfo.js.map +1 -1
  92. package/core/QueryManager.js +49 -27
  93. package/core/QueryManager.js.map +1 -1
  94. package/core/RefetchEventManager.js +3 -3
  95. package/core/dataStateErrorCache.d.ts +3 -0
  96. package/core/dataStateErrorCache.js +9 -0
  97. package/core/dataStateErrorCache.js.map +1 -0
  98. package/core/types.d.ts +2 -0
  99. package/core/types.js.map +1 -1
  100. package/incremental/handlers/graphql17Alpha9.d.ts +26 -3
  101. package/incremental/handlers/graphql17Alpha9.js +35 -12
  102. package/incremental/handlers/graphql17Alpha9.js.map +1 -1
  103. package/incremental/types.d.ts +41 -3
  104. package/incremental/types.js.map +1 -1
  105. package/invariantErrorCodes.js +50 -31
  106. package/package.json +1 -1
  107. package/react/hooks/useBackgroundQuery.d.ts +100 -47
  108. package/react/hooks/useBackgroundQuery.js.map +1 -1
  109. package/react/hooks/useLazyQuery.d.ts +26 -20
  110. package/react/hooks/useLazyQuery.js.map +1 -1
  111. package/react/hooks/useLoadableQuery.d.ts +23 -15
  112. package/react/hooks/useLoadableQuery.js.map +1 -1
  113. package/react/hooks/useMutation.d.ts +10 -7
  114. package/react/hooks/useMutation.js.map +1 -1
  115. package/react/hooks/useQuery.d.ts +74 -32
  116. package/react/hooks/useQuery.js.map +1 -1
  117. package/react/hooks/useQueryRefHandlers.js.map +1 -1
  118. package/react/hooks/useSuspenseQuery.d.ts +83 -34
  119. package/react/hooks/useSuspenseQuery.js.map +1 -1
  120. package/react/hooks-compiled/useBackgroundQuery.d.ts +100 -47
  121. package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
  122. package/react/hooks-compiled/useLazyQuery.d.ts +26 -20
  123. package/react/hooks-compiled/useLazyQuery.js.map +1 -1
  124. package/react/hooks-compiled/useLoadableQuery.d.ts +23 -15
  125. package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
  126. package/react/hooks-compiled/useMutation.d.ts +10 -7
  127. package/react/hooks-compiled/useMutation.js.map +1 -1
  128. package/react/hooks-compiled/useQuery.d.ts +74 -32
  129. package/react/hooks-compiled/useQuery.js.map +1 -1
  130. package/react/hooks-compiled/useQueryRefHandlers.js.map +1 -1
  131. package/react/hooks-compiled/useSuspenseQuery.d.ts +83 -34
  132. package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
  133. package/react/internal/cache/QueryReference.js.map +1 -1
  134. package/react/internal/types.d.ts +15 -4
  135. package/react/internal/types.js.map +1 -1
  136. package/react/query-preloader/createQueryPreloader.d.ts +20 -5
  137. package/react/query-preloader/createQueryPreloader.js.map +1 -1
  138. package/testing/core/mocking/mockLink.d.ts +1 -2
  139. package/testing/core/mocking/mockLink.js +21 -1
  140. package/testing/core/mocking/mockLink.js.map +1 -1
  141. package/utilities/internal/addDeferFragmentLabels.d.ts +3 -0
  142. package/utilities/internal/addDeferFragmentLabels.js +30 -0
  143. package/utilities/internal/addDeferFragmentLabels.js.map +1 -0
  144. package/utilities/internal/getDirectiveArgValue.d.ts +9 -0
  145. package/utilities/internal/getDirectiveArgValue.js +16 -0
  146. package/utilities/internal/getDirectiveArgValue.js.map +1 -0
  147. package/utilities/internal/index.d.ts +2 -0
  148. package/utilities/internal/index.js +2 -0
  149. package/utilities/internal/index.js.map +1 -1
  150. package/version.js +1 -1
@@ -232,7 +232,7 @@ class Policies {
232
232
  const rootId = "ROOT_" + which.toUpperCase();
233
233
  const old = this.rootTypenamesById[rootId];
234
234
  if (typename !== old) {
235
- (0, invariant_1.invariant)(!old || old === which, 108, which);
235
+ (0, invariant_1.invariant)(!old || old === which, 109, which);
236
236
  // First, delete any old __typename associated with this rootId from
237
237
  // rootIdsByTypename.
238
238
  if (old)
@@ -375,7 +375,7 @@ class Policies {
375
375
  if (supertypeSet.has(supertype)) {
376
376
  if (!typenameSupertypeSet.has(supertype)) {
377
377
  if (checkingFuzzySubtypes) {
378
- __DEV__ && invariant_1.invariant.warn(109, typename, supertype);
378
+ __DEV__ && invariant_1.invariant.warn(110, typename, supertype);
379
379
  }
380
380
  // Record positive results for faster future lookup.
381
381
  // Unfortunately, we cannot safely cache negative results,
@@ -632,7 +632,7 @@ function normalizeReadFieldOptions(readFieldArgs, objectOrReference, variables)
632
632
  }
633
633
  }
634
634
  if (environment_1.__DEV__ && options.from === void 0) {
635
- __DEV__ && invariant_1.invariant.warn(110, (0, internal_2.stringifyForDisplay)(Array.from(readFieldArgs)));
635
+ __DEV__ && invariant_1.invariant.warn(111, (0, internal_2.stringifyForDisplay)(Array.from(readFieldArgs)));
636
636
  }
637
637
  if (void 0 === options.variables) {
638
638
  options.variables = variables;
@@ -642,7 +642,7 @@ function normalizeReadFieldOptions(readFieldArgs, objectOrReference, variables)
642
642
  function makeMergeObjectsFunction(store) {
643
643
  return function mergeObjects(existing, incoming) {
644
644
  if ((0, internal_2.isArray)(existing) || (0, internal_2.isArray)(incoming)) {
645
- throw (0, invariant_1.newInvariantError)(111);
645
+ throw (0, invariant_1.newInvariantError)(112);
646
646
  }
647
647
  // These dynamic checks are necessary because the parameters of a
648
648
  // custom merge function can easily have the any type, so the type
@@ -96,12 +96,10 @@ class StoreReader {
96
96
  },
97
97
  });
98
98
  }
99
- diffQueryAgainstStore({ store, query, rootId = "ROOT_QUERY", variables, returnPartialData = true, [internal_1.handleIncrementalSymbol]: handleIncremental, }) {
99
+ diffQueryAgainstStore({ store, query, rootId = "ROOT_QUERY", variables, returnPartialData = true, ...options }) {
100
+ const returnIncremental = Object.hasOwn(options, internal_1.handleIncrementalSymbol);
100
101
  const policies = this.config.cache.policies;
101
- variables = {
102
- ...(0, internal_1.getDefaultValues)((0, internal_1.getQueryDefinition)(query)),
103
- ...variables,
104
- };
102
+ variables = (0, internal_1.compact)((0, internal_1.getDefaultValues)((0, internal_1.getQueryDefinition)(query)), variables);
105
103
  const rootRef = (0, internal_1.makeReference)(rootId);
106
104
  const context = {
107
105
  store,
@@ -110,7 +108,7 @@ class StoreReader {
110
108
  variables,
111
109
  varString: (0, utilities_1.canonicalStringify)(variables),
112
110
  ...(0, helpers_js_1.extractFragmentContext)(query, this.config.fragments),
113
- ...(typeof handleIncremental === "object" ? handleIncremental : (undefined)),
111
+ ...options[internal_1.handleIncrementalSymbol],
114
112
  };
115
113
  let execResult = this.executeSelectionSet({
116
114
  selectionSet: (0, internal_1.getMainDefinition)(query).selectionSet,
@@ -123,17 +121,7 @@ class StoreReader {
123
121
  // partial defer boundaries. The "deferPartial" data state tells us that the
124
122
  // only part of the result that contributed to its partiality is data inside
125
123
  // a defer boundary.
126
- if (handleIncremental &&
127
- (execResult.dataState === "deferPartial" ||
128
- execResult.dataState === "streamPartial" ||
129
- // If the last cache write repaired a partial @stream array to a
130
- // complete array, the stream array might contain stale entries after
131
- // the last written value. We only want to deliver the results up to
132
- // the index the network wrote so we need to prune it too.
133
- context.streamInfo ||
134
- // The network hasn't delivered these @defer boundaries yet, so prune
135
- // the (possibly complete) cached data sitting at them.
136
- context.deferInfo)) {
124
+ if (returnIncremental && shouldPrune(execResult, context)) {
137
125
  const pruned = this.prunePartialBoundaries({
138
126
  selectionSet: (0, internal_1.getMainDefinition)(query).selectionSet,
139
127
  data: execResult.result,
@@ -141,7 +129,7 @@ class StoreReader {
141
129
  context,
142
130
  path: [],
143
131
  });
144
- const changed = execResult.result !== pruned;
132
+ const changed = execResult.result !== pruned.result;
145
133
  // It's possible that pruning didn't actually change the result which can
146
134
  // happen if a defer boundary is misclassified as "deferPartial" instead
147
135
  // of "streaming" (sibling defer boundaries with overlapping selection
@@ -151,19 +139,12 @@ class StoreReader {
151
139
  // we want to keep the original execResult which contains the partial
152
140
  // data.
153
141
  if (!changed || !returnPartialData) {
154
- const { dataState } = execResult;
155
142
  // Omit `missing` property since pruning puts it in a state that doesn't
156
143
  // report missing fields.
157
144
  execResult = {
158
- result: pruned,
145
+ result: pruned.result,
159
146
  partialBoundaries: execResult.partialBoundaries,
160
- dataState: dataState === "deferPartial" ? "streaming"
161
- : dataState === "streamPartial" ? "complete"
162
- // A cached @defer boundary the network hasn't delivered was
163
- // pruned from an otherwise complete result, so we're still
164
- // streaming.
165
- : context.deferInfo && changed ? "streaming"
166
- : dataState,
147
+ dataState: pruned.dataState,
167
148
  };
168
149
  }
169
150
  }
@@ -174,7 +155,7 @@ class StoreReader {
174
155
  // We don't need to report missing fields inside defer boundaries since
175
156
  // the "streaming" dataState tells us that the only missing fields in
176
157
  // the object is inside a defer boundary.
177
- (dataState !== "streaming" || !handleIncremental);
158
+ (dataState !== "streaming" || !returnIncremental);
178
159
  // If we get all root @defer boundaries with an empty result, report it as
179
160
  // empty instead of streaming.
180
161
  if (dataState === "streaming" && Object.keys(result).length === 0) {
@@ -183,7 +164,7 @@ class StoreReader {
183
164
  let missingError;
184
165
  if (dataState === "deferPartial" ||
185
166
  dataState === "streamPartial" ||
186
- (dataState === "streaming" && !handleIncremental)) {
167
+ (dataState === "streaming" && !returnIncremental)) {
187
168
  dataState = "partial";
188
169
  }
189
170
  if (dataState === "partial" && !returnPartialData) {
@@ -203,7 +184,7 @@ class StoreReader {
203
184
  return missingError;
204
185
  },
205
186
  };
206
- if (handleIncremental) {
187
+ if (returnIncremental) {
207
188
  diffResult.dataState =
208
189
  dataState;
209
190
  }
@@ -308,7 +289,7 @@ class StoreReader {
308
289
  if (typename) {
309
290
  const policy = policies["getFieldPolicy"](typename, fieldName);
310
291
  if (policy?.scalar) {
311
- __DEV__ && invariant_1.invariant.warn(112, `${typename}.${fieldName}`, policy.scalar);
292
+ __DEV__ && invariant_1.invariant.warn(113, `${typename}.${fieldName}`, policy.scalar);
312
293
  }
313
294
  }
314
295
  }
@@ -345,7 +326,7 @@ class StoreReader {
345
326
  else {
346
327
  const fragment = (0, internal_1.getFragmentFromSelection)(selection, context.lookupFragment);
347
328
  if (!fragment && selection.kind === graphql_1.Kind.FRAGMENT_SPREAD) {
348
- throw (0, invariant_1.newInvariantError)(113, selection.name.value);
329
+ throw (0, invariant_1.newInvariantError)(114, selection.name.value);
349
330
  }
350
331
  if (fragment && policies.fragmentMatches(fragment, typename)) {
351
332
  const isDeferBoundary = (0, internal_1.isDeferredFragment)(selection, context.variables);
@@ -379,7 +360,8 @@ class StoreReader {
379
360
  if (execResult.missing) {
380
361
  missing = missingMerger.merge(missing, execResult.missing);
381
362
  }
382
- if (isDeferBoundary && nextDataState === "partial") {
363
+ if (isDeferBoundary &&
364
+ (nextDataState === "partial" || nextDataState === "empty")) {
383
365
  partialBoundaries.add(selection);
384
366
  }
385
367
  dataState = mergeDataState(dataState, isDeferBoundary ?
@@ -472,10 +454,12 @@ class StoreReader {
472
454
  }
473
455
  prunePartialBoundariesImpl({ boundaries, context, data, path, selectionSet, }) {
474
456
  const { variables, lookupFragment, policies } = context;
475
- if (data == null || !boundaries)
476
- return data;
457
+ if (data == null || !boundaries) {
458
+ return { result: data, dataState: "complete" };
459
+ }
477
460
  const merger = new internal_1.DeepMerger();
478
461
  let changed = false;
462
+ let dataState = "complete";
479
463
  const result = {};
480
464
  // __typename might not be part of the selection set, so preserve it when
481
465
  // available, otherwise it gets removed since it's never visited when
@@ -501,8 +485,9 @@ class StoreReader {
501
485
  context,
502
486
  path: path.concat(resultName),
503
487
  });
504
- changed ||= pruned !== fieldValue;
505
- result[resultName] = pruned;
488
+ changed ||= pruned.result !== fieldValue;
489
+ result[resultName] = pruned.result;
490
+ dataState = mergeDataState(dataState, pruned.dataState);
506
491
  }
507
492
  else if (!selection.selectionSet) {
508
493
  result[resultName] = fieldValue;
@@ -515,13 +500,14 @@ class StoreReader {
515
500
  context,
516
501
  path: path.concat(resultName),
517
502
  });
518
- changed ||= pruned !== fieldValue;
503
+ changed ||= pruned.result !== fieldValue;
504
+ dataState = mergeDataState(dataState, pruned.dataState);
519
505
  // A response key can be selected by more than one selection (e.g. a
520
506
  // field and an overlapping fragment), so merge their kept fields.
521
507
  result[resultName] =
522
508
  Object.hasOwn(result, resultName) ?
523
- merger.merge(result[resultName], pruned)
524
- : pruned;
509
+ merger.merge(result[resultName], pruned.result)
510
+ : pruned.result;
525
511
  }
526
512
  return;
527
513
  }
@@ -533,11 +519,19 @@ class StoreReader {
533
519
  // Object.keys(result).length check actually detects whether keys were
534
520
  // dropped or not.
535
521
  const fragment = (0, internal_1.getFragmentFromSelection)(selection, lookupFragment);
536
- if (fragment &&
537
- policies.fragmentMatches(fragment, data.__typename) &&
538
- !boundaries.has(selection) &&
539
- !context.deferInfo?.peekArray(path)) {
540
- fragment.selectionSet.selections.forEach(workSet.add, workSet);
522
+ let prune = false;
523
+ if (context.deferInfo && (0, internal_1.isDeferredFragment)(selection, variables)) {
524
+ const directive = selection.directives?.find((d) => d.name.value === "defer");
525
+ const label = directive && (0, internal_1.getDirectiveArgValue)(directive, "label", graphql_1.Kind.STRING);
526
+ prune = !!context.deferInfo.peekArray(path.concat(label || []));
527
+ }
528
+ if (fragment && policies.fragmentMatches(fragment, data.__typename)) {
529
+ if (boundaries.has(selection) || prune) {
530
+ dataState = mergeDataState(dataState, "streaming");
531
+ }
532
+ else {
533
+ fragment.selectionSet.selections.forEach(workSet.add, workSet);
534
+ }
541
535
  }
542
536
  });
543
537
  if (Object.keys(result).length !== Object.keys(data).length) {
@@ -550,18 +544,22 @@ class StoreReader {
550
544
  // actually dropped by the partial @defer fragment.
551
545
  changed = !(0, equality_1.equal)(result, data);
552
546
  }
553
- return changed ? result : data;
547
+ return { result: changed ? result : data, dataState };
554
548
  }
555
549
  prunePartialStreamArrayImpl({ field, array, boundaries, context, path, }) {
556
550
  if (!boundaries)
557
- return array;
551
+ return { result: array, dataState: "complete" };
558
552
  let changed = false;
553
+ let dataState = "complete";
559
554
  let pruned = [];
560
555
  const state = context.streamInfo?.peekArray(path)?.state;
561
556
  const length = Math.min(array.length, state?.truncate ? state.streamPosition : Number.MAX_SAFE_INTEGER);
562
557
  for (let i = 0; i < length; i++) {
563
558
  const item = array[i];
564
- let prunedItem = item;
559
+ let prunedResult = {
560
+ result: item,
561
+ dataState: "complete",
562
+ };
565
563
  const boundary = boundaries.getChild(i);
566
564
  if (boundary?.has(field)) {
567
565
  // The presence of streamInfo determines how we truncate partial
@@ -576,11 +574,12 @@ class StoreReader {
576
574
  }
577
575
  else {
578
576
  pruned = [];
577
+ dataState = "complete";
579
578
  }
580
579
  break;
581
580
  }
582
581
  if (Array.isArray(item)) {
583
- prunedItem = this.prunePartialStreamArray({
582
+ prunedResult = this.prunePartialStreamArray({
584
583
  field,
585
584
  array: item,
586
585
  boundaries: boundaries.getChild(i),
@@ -589,7 +588,7 @@ class StoreReader {
589
588
  });
590
589
  }
591
590
  else if (field.selectionSet) {
592
- prunedItem = this.prunePartialBoundaries({
591
+ prunedResult = this.prunePartialBoundaries({
593
592
  data: item,
594
593
  selectionSet: field.selectionSet,
595
594
  boundaries: boundaries.getChild(i),
@@ -597,11 +596,12 @@ class StoreReader {
597
596
  path: path.concat(i),
598
597
  });
599
598
  }
600
- pruned.push(prunedItem);
601
- changed ||= prunedItem !== item;
599
+ pruned.push(prunedResult.result);
600
+ changed ||= prunedResult.result !== item;
601
+ dataState = mergeDataState(dataState, prunedResult.dataState);
602
602
  }
603
603
  changed ||= pruned.length !== array.length;
604
- return changed ? pruned : array;
604
+ return { result: changed ? pruned : array, dataState };
605
605
  }
606
606
  }
607
607
  exports.StoreReader = StoreReader;
@@ -624,7 +624,7 @@ function assertSelectionSetForIdValue(store, field, fieldValue) {
624
624
  if ((0, internal_1.isNonNullObject)(value)) {
625
625
  (0, invariant_1.invariant)(
626
626
  !(0, utilities_1.isReference)(value),
627
- 114,
627
+ 115,
628
628
  (0, helpers_js_1.getTypenameFromStoreObject)(store, value),
629
629
  field.name.value
630
630
  );
@@ -675,6 +675,23 @@ class PartialBoundaries {
675
675
  return this;
676
676
  }
677
677
  }
678
+ function shouldPrune({ dataState }, context) {
679
+ if (dataState === "deferPartial" || dataState === "streamPartial") {
680
+ return true;
681
+ }
682
+ if (dataState === "complete" || dataState === "streaming") {
683
+ return !!(
684
+ // If the last cache write repaired a partial @stream array to a
685
+ // complete array, the stream array might contain stale entries after
686
+ // the last written value. We only want to deliver the results up to
687
+ // the index the network wrote so we need to prune it too.
688
+ (context.streamInfo ||
689
+ // The network hasn't delivered these @defer boundaries yet, so prune
690
+ // the (possibly complete) cached data sitting at them.
691
+ context.deferInfo));
692
+ }
693
+ return false;
694
+ }
678
695
  // Describes the data state transitions that change the running state when it's
679
696
  // combined with the next data state. Omitted object values represent
680
697
  // "impossible" merges where the data state should remain the same.