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

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 (118) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/__cjs/cache/core/types/Cache.d.cts +25 -0
  3. package/__cjs/cache/index.cjs.map +1 -1
  4. package/__cjs/cache/index.d.cts +1 -1
  5. package/__cjs/cache/inmemory/inMemoryCache.cjs +4 -0
  6. package/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
  7. package/__cjs/cache/inmemory/inMemoryCache.d.cts +7 -3
  8. package/__cjs/cache/inmemory/readFromStore.cjs +453 -42
  9. package/__cjs/cache/inmemory/readFromStore.cjs.map +1 -1
  10. package/__cjs/cache/inmemory/readFromStore.d.cts +11 -2
  11. package/__cjs/cache/inmemory/types.d.cts +11 -1
  12. package/__cjs/cache/inmemory/writeToStore.cjs +1 -5
  13. package/__cjs/cache/inmemory/writeToStore.cjs.map +1 -1
  14. package/__cjs/core/QueryInfo.cjs +86 -172
  15. package/__cjs/core/QueryInfo.cjs.map +1 -1
  16. package/__cjs/core/QueryInfo.d.cts +8 -2
  17. package/__cjs/core/QueryManager.cjs +3 -1
  18. package/__cjs/core/QueryManager.cjs.map +1 -1
  19. package/__cjs/incremental/handlers/defer20220824.cjs.map +1 -1
  20. package/__cjs/incremental/handlers/defer20220824.d.cts +2 -4
  21. package/__cjs/incremental/handlers/graphql17Alpha9.cjs +20 -12
  22. package/__cjs/incremental/handlers/graphql17Alpha9.cjs.map +1 -1
  23. package/__cjs/incremental/handlers/graphql17Alpha9.d.cts +5 -5
  24. package/__cjs/incremental/types.d.cts +16 -3
  25. package/__cjs/utilities/caching/sizes.cjs.map +1 -1
  26. package/__cjs/utilities/caching/sizes.d.cts +39 -1
  27. package/__cjs/utilities/internal/StreamArrayState.cjs +27 -0
  28. package/__cjs/utilities/internal/StreamArrayState.cjs.map +1 -0
  29. package/__cjs/utilities/internal/StreamArrayState.d.cts +12 -0
  30. package/__cjs/utilities/internal/constants.cjs +20 -1
  31. package/__cjs/utilities/internal/constants.cjs.map +1 -1
  32. package/__cjs/utilities/internal/constants.d.cts +19 -0
  33. package/__cjs/utilities/internal/getFragmentFromSelection.cjs +1 -1
  34. package/__cjs/utilities/internal/getFragmentFromSelection.cjs.map +1 -1
  35. package/__cjs/utilities/internal/getMemoryInternals.cjs +6 -0
  36. package/__cjs/utilities/internal/getMemoryInternals.cjs.map +1 -1
  37. package/__cjs/utilities/internal/getMemoryInternals.d.cts +4 -0
  38. package/__cjs/utilities/internal/index.cjs +9 -4
  39. package/__cjs/utilities/internal/index.cjs.map +1 -1
  40. package/__cjs/utilities/internal/index.d.cts +5 -3
  41. package/__cjs/utilities/internal/isDeferredFragment.cjs +19 -4
  42. package/__cjs/utilities/internal/isDeferredFragment.cjs.map +1 -1
  43. package/__cjs/utilities/internal/isDeferredFragment.d.cts +6 -1
  44. package/__cjs/utilities/internal/isStreamField.cjs +37 -0
  45. package/__cjs/utilities/internal/isStreamField.cjs.map +1 -0
  46. package/__cjs/utilities/internal/isStreamField.d.cts +9 -0
  47. package/__cjs/utilities/internal/makeStreamInfoTrie.cjs +17 -0
  48. package/__cjs/utilities/internal/makeStreamInfoTrie.cjs.map +1 -0
  49. package/__cjs/utilities/internal/makeStreamInfoTrie.d.cts +8 -0
  50. package/__cjs/utilities/internal/types/DeferInfo.cjs +3 -0
  51. package/__cjs/utilities/internal/types/DeferInfo.cjs.map +1 -0
  52. package/__cjs/utilities/internal/types/DeferInfo.d.cts +10 -0
  53. package/__cjs/utilities/internal/types/StreamInfoTrie.d.cts +2 -0
  54. package/__cjs/version.cjs +1 -1
  55. package/cache/core/types/Cache.d.ts +25 -0
  56. package/cache/core/types/Cache.js.map +1 -1
  57. package/cache/index.d.ts +1 -1
  58. package/cache/index.js.map +1 -1
  59. package/cache/inmemory/inMemoryCache.d.ts +7 -3
  60. package/cache/inmemory/inMemoryCache.js +5 -1
  61. package/cache/inmemory/inMemoryCache.js.map +1 -1
  62. package/cache/inmemory/readFromStore.d.ts +11 -2
  63. package/cache/inmemory/readFromStore.js +454 -43
  64. package/cache/inmemory/readFromStore.js.map +1 -1
  65. package/cache/inmemory/types.d.ts +12 -2
  66. package/cache/inmemory/types.js.map +1 -1
  67. package/cache/inmemory/writeToStore.js +2 -6
  68. package/cache/inmemory/writeToStore.js.map +1 -1
  69. package/core/QueryInfo.d.ts +8 -2
  70. package/core/QueryInfo.js +87 -173
  71. package/core/QueryInfo.js.map +1 -1
  72. package/core/QueryManager.js +3 -1
  73. package/core/QueryManager.js.map +1 -1
  74. package/incremental/handlers/defer20220824.d.ts +2 -4
  75. package/incremental/handlers/defer20220824.js.map +1 -1
  76. package/incremental/handlers/graphql17Alpha9.d.ts +5 -5
  77. package/incremental/handlers/graphql17Alpha9.js +21 -13
  78. package/incremental/handlers/graphql17Alpha9.js.map +1 -1
  79. package/incremental/types.d.ts +16 -3
  80. package/incremental/types.js.map +1 -1
  81. package/package.json +1 -1
  82. package/utilities/caching/sizes.d.ts +39 -1
  83. package/utilities/caching/sizes.js.map +1 -1
  84. package/utilities/internal/StreamArrayState.d.ts +12 -0
  85. package/utilities/internal/StreamArrayState.js +23 -0
  86. package/utilities/internal/StreamArrayState.js.map +1 -0
  87. package/utilities/internal/constants.d.ts +19 -0
  88. package/utilities/internal/constants.js +19 -0
  89. package/utilities/internal/constants.js.map +1 -1
  90. package/utilities/internal/getFragmentFromSelection.js +1 -1
  91. package/utilities/internal/getFragmentFromSelection.js.map +1 -1
  92. package/utilities/internal/getMemoryInternals.d.ts +4 -0
  93. package/utilities/internal/getMemoryInternals.js +6 -0
  94. package/utilities/internal/getMemoryInternals.js.map +1 -1
  95. package/utilities/internal/index.d.ts +5 -3
  96. package/utilities/internal/index.js +4 -2
  97. package/utilities/internal/index.js.map +1 -1
  98. package/utilities/internal/isDeferredFragment.d.ts +7 -2
  99. package/utilities/internal/isDeferredFragment.js +19 -4
  100. package/utilities/internal/isDeferredFragment.js.map +1 -1
  101. package/utilities/internal/isStreamField.d.ts +9 -0
  102. package/utilities/internal/isStreamField.js +34 -0
  103. package/utilities/internal/isStreamField.js.map +1 -0
  104. package/utilities/internal/makeStreamInfoTrie.d.ts +8 -0
  105. package/utilities/internal/makeStreamInfoTrie.js +14 -0
  106. package/utilities/internal/makeStreamInfoTrie.js.map +1 -0
  107. package/utilities/internal/types/DeferInfo.d.ts +10 -0
  108. package/utilities/internal/types/DeferInfo.js +2 -0
  109. package/utilities/internal/types/DeferInfo.js.map +1 -0
  110. package/utilities/internal/types/StreamInfoTrie.d.ts +2 -0
  111. package/utilities/internal/types/StreamInfoTrie.js.map +1 -1
  112. package/version.js +1 -1
  113. package/__cjs/utilities/internal/collectSiblingFields.cjs +0 -61
  114. package/__cjs/utilities/internal/collectSiblingFields.cjs.map +0 -1
  115. package/__cjs/utilities/internal/collectSiblingFields.d.cts +0 -21
  116. package/utilities/internal/collectSiblingFields.d.ts +0 -21
  117. package/utilities/internal/collectSiblingFields.js +0 -58
  118. package/utilities/internal/collectSiblingFields.js.map +0 -1
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QueryInfo = void 0;
4
4
  const equality_1 = require("@wry/equality");
5
+ const trie_1 = require("@wry/trie");
5
6
  const internal_1 = require("@apollo/client/utilities/internal");
6
7
  const invariant_1 = require("@apollo/client/utilities/invariant");
8
+ const networkStatus_js_1 = require("./networkStatus.cjs");
7
9
  const IGNORE = {};
8
10
  const destructiveMethodCounts = new WeakMap();
9
11
  function wrapDestructiveCacheMethod(cache, methodName) {
@@ -98,38 +100,50 @@ class QueryInfo {
98
100
  }
99
101
  return incoming;
100
102
  }
101
- markQueryResult(incoming, { document: query, variables, errorPolicy, cacheWriteBehavior, returnPartialData, }) {
103
+ markQueryResult(incoming, { document: query, variables, errorPolicy, cacheWriteBehavior, returnPartialData, fetchPolicy, networkStatus, }) {
102
104
  const diffOptions = {
103
105
  query,
104
106
  variables,
105
- returnPartialData: true,
106
107
  optimistic: true,
107
108
  };
108
109
  // Cancel the pending notify timeout (if it exists) to prevent extraneous network
109
110
  // requests. To allow future notify timeouts, diff and dirty are reset as well.
110
111
  this.observableQuery?.["resetNotifications"]();
111
112
  const skipCache = cacheWriteBehavior === 0 /* CacheWriteBehavior.FORBID */;
112
- const lastDiff = skipCache ? undefined : this.cache.diff(diffOptions);
113
+ const lastDiff = skipCache ? undefined : (this.getDiff({
114
+ ...diffOptions,
115
+ // Always request partial data to ensure the network incremental
116
+ // result is merged with all existing data (especially true to
117
+ // maintain @stream arrays with partial list items in the right order)
118
+ returnPartialData: true,
119
+ }));
113
120
  const incrementalResult = this.maybeHandleIncrementalResult(lastDiff?.result, incoming, query);
114
121
  let result = {
115
122
  ...incrementalResult,
116
- dataState: incrementalResult.data == null ? "empty"
117
- : this.hasNext ? "streaming"
118
- : "complete",
123
+ dataState: incrementalResult.data == null ? "empty" : "complete",
119
124
  };
120
125
  if (skipCache) {
121
- return {
122
- ...result,
123
- dataState: result.data == null ? "empty"
124
- // Ww can simplify the checks for no-cache queries because the
125
- // result is purely server driven which means we can assume a
126
- // well-formed GraphQL response. In this case, `streaming` only
127
- // makes sense if we are using the `@defer` directive and there are
128
- // more chunks still streaming (i.e. this.hasNext is true). Purely
129
- // `@stream` queries should always be complete.
130
- : this.hasNext && (0, internal_1.hasDirectives)(["defer"], query) ? "streaming"
131
- : "complete",
132
- };
126
+ const hasPendingDefer = this.incremental?.pending?.some((pending) => this.incremental?.getPendingType?.(pending.id) === "defer");
127
+ if (hasPendingDefer ||
128
+ // The Defer20220824Handler cannot track pending/completed incremental
129
+ // chunks due to its data format so we naively set dataState to
130
+ // streaming if we are still processing chunks. The only case where
131
+ // streaming is incorrect and should actually be complete is when
132
+ // both a @defer and @stream boundary is present and the @defer chunk
133
+ // has completed before the `@stream` array.
134
+ //
135
+ // Assigning the naive "streaming" value avoids a much more expensive
136
+ // pass over `result.data` that would otherwise need to traverse the
137
+ // selection sets and evaluate the data object at each defer boundary
138
+ // to see if it fulfills the selection set. For such a narrow case where
139
+ // its incorrect on a format that is now outdated is not worth the
140
+ // fix so we are ok with reporting a `streaming` here.
141
+ (!this.incremental?.pending &&
142
+ this.hasNext &&
143
+ (0, internal_1.hasDirectives)(["defer"], query))) {
144
+ result.dataState = "streaming";
145
+ }
146
+ return result;
133
147
  }
134
148
  if (shouldWriteResult(result, errorPolicy)) {
135
149
  // Using a transaction here so we have a chance to read the result
@@ -147,7 +161,8 @@ class QueryInfo {
147
161
  }
148
162
  },
149
163
  update: (cache) => {
150
- if (this.shouldWrite(result, variables)) {
164
+ const shouldWrite = this.shouldWrite(result, variables);
165
+ if (shouldWrite) {
151
166
  cache.writeQuery({
152
167
  query,
153
168
  data: result.data,
@@ -207,34 +222,17 @@ class QueryInfo {
207
222
  // If the previous this.diff was incomplete, fall through to
208
223
  // re-reading the latest data with cache.diff, below.
209
224
  }
210
- const diff = cache.diff(diffOptions);
211
- // If we're allowed to write to the cache, and we can read a
212
- // complete result from the cache, update result.data to be the
213
- // result from the cache, rather than the raw network result.
214
- // Set without setDiff to avoid triggering a notify call, since
215
- // we have other ways of notifying for this result.
216
- if (diff.complete) {
217
- result = {
218
- ...result,
219
- data: diff.result,
220
- dataState: "complete",
221
- };
222
- }
223
- else if (this.hasNext && diff.result !== null) {
224
- const isPartial = isStreamingPartial(diff, query, variables);
225
- // If we tolerate partial results always apply `diff.result` to
226
- // ensure we return the result of any transforms in cache read
227
- // functions or custom scalars. If we don't tolerate partial
228
- // results, we only want to apply the diff result if the only hole
229
- // in the data is at a defer boundary (e.g.
230
- // `diff.complete === false && isStreamingPartial === false`)
231
- if (returnPartialData || !isPartial) {
232
- result = {
233
- ...result,
234
- data: diff.result,
235
- dataState: isPartial ? "partial" : "streaming",
236
- };
237
- }
225
+ const isNetworkOnly = fetchPolicy === "network-only" &&
226
+ networkStatus !== networkStatus_js_1.NetworkStatus.refetch;
227
+ const { dataState, result: diffResult } = this.getDiff({
228
+ ...diffOptions,
229
+ // Never deliver partial data for network-only requests
230
+ returnPartialData: returnPartialData && !isNetworkOnly,
231
+ }, this.getIncrementalInfo(result, { isNetworkOnly }));
232
+ if (dataState === "complete" ||
233
+ (returnPartialData && dataState === "partial" && shouldWrite) ||
234
+ (this.hasNext && dataState === "streaming")) {
235
+ result = { ...result, data: diffResult, dataState };
238
236
  }
239
237
  },
240
238
  });
@@ -244,6 +242,47 @@ class QueryInfo {
244
242
  }
245
243
  return result;
246
244
  }
245
+ getIncrementalInfo(result, { isNetworkOnly }) {
246
+ const pending = this.incremental?.pending ?? [];
247
+ const streamInfo = result.extensions?.[internal_1.streamInfoSymbol]?.deref();
248
+ const incrementalInfo = { streamInfo };
249
+ // We don't want to deliver stream items or complete defer boundaries
250
+ // for a network-only request if they haven't yet streamed from the
251
+ // network. We record all the still-pending paths so that cache.diff
252
+ // can prune complete defer/stream boundaries at those paths.
253
+ if (isNetworkOnly) {
254
+ for (const item of pending) {
255
+ const type = this.incremental?.getPendingType?.(item.id);
256
+ if (type === "defer") {
257
+ incrementalInfo.deferInfo ||= new trie_1.Trie(true, () => true);
258
+ incrementalInfo.deferInfo.lookupArray(item.path);
259
+ }
260
+ else if (streamInfo && type === "stream") {
261
+ streamInfo.lookupArray(item.path).state.truncate = true;
262
+ }
263
+ }
264
+ }
265
+ return incrementalInfo;
266
+ }
267
+ getDiff(options, incrementalInfo) {
268
+ if (this.cache[internal_1.handleIncrementalSymbol]) {
269
+ return this.cache.diff({
270
+ ...options,
271
+ [internal_1.handleIncrementalSymbol]: incrementalInfo || true,
272
+ });
273
+ }
274
+ // returnPartialData is overridden for backwards compatibility with caches
275
+ // that don't handle incremental results. Without this, in-flight
276
+ // incremental cache data would come back null when returnPartialData is
277
+ // false due to the partial result.
278
+ const diff = this.cache.diff({ ...options, returnPartialData: true });
279
+ return {
280
+ ...diff,
281
+ dataState: diff.complete ? "complete"
282
+ : diff.result === null ? "empty"
283
+ : "partial",
284
+ };
285
+ }
247
286
  markMutationResult(incoming, mutation, cache = this.cache) {
248
287
  const cacheWrites = [];
249
288
  const skipCache = mutation.cacheWriteBehavior === 0 /* CacheWriteBehavior.FORBID */;
@@ -447,129 +486,4 @@ function shouldWriteResult(result, errorPolicy = "none") {
447
486
  }
448
487
  return writeWithErrors;
449
488
  }
450
- function isStreamingPartial(diff, document, variables) {
451
- if (!diff.missing)
452
- return false;
453
- const fragmentMap = (0, internal_1.createFragmentMap)((0, internal_1.getFragmentDefinitions)(document));
454
- return isPartialInSelectionSet((0, internal_1.getMainDefinition)(document).selectionSet, diff.missing.missing, { fragmentMap, variables });
455
- }
456
- function isPartialInSelectionSet(selectionSet, missingTree, context) {
457
- if (typeof missingTree === "string")
458
- return true;
459
- if (missingTree === undefined)
460
- return false;
461
- const missingKeys = Object.keys(missingTree);
462
- if (missingKeys.length > 0 && missingKeys.every(isArrayIndex)) {
463
- return missingKeys.some((key) => {
464
- if (typeof missingTree[key] === "string")
465
- return true;
466
- return isPartialInSelectionSet(selectionSet, missingTree[key], context);
467
- });
468
- }
469
- const { fragmentMap, variables } = context;
470
- for (const selection of selectionSet.selections) {
471
- if ((0, internal_1.isField)(selection)) {
472
- if ((0, internal_1.isTypenameField)(selection))
473
- continue;
474
- const missing = missingTree[(0, internal_1.resultKeyNameFromField)(selection)];
475
- // If a missing entry is absent, we have a value for this field
476
- if (missing === undefined)
477
- continue;
478
- if (!selection.selectionSet ||
479
- isPartialInSelectionSet(selection.selectionSet, missing, context)) {
480
- return true;
481
- }
482
- }
483
- else {
484
- const fragment = (0, internal_1.getFragmentFromSelection)(selection, fragmentMap);
485
- if (!fragment)
486
- continue;
487
- if ((0, internal_1.isDeferredFragment)(selection, variables)) {
488
- // We need to know the non-deferred fields that might overlap with the
489
- // deferred selection set so that we accurately report the right
490
- // dataState when all the non-deferred fields are satisfied and only the
491
- // selections inside the fragment are missing.
492
- // For example:
493
- //
494
- // {
495
- // recipient {
496
- // name
497
- // }
498
- // ... @defer {
499
- // recipient {
500
- // name
501
- // email
502
- // }
503
- // }
504
- // }
505
- //
506
- // dataState should be `streaming`, not `partial` if `name` is present,
507
- // but `email` is absent since `name` is not deferred.
508
- if (isPartialDeferBoundary(fragment.selectionSet, missingTree, (0, internal_1.collectSiblingFields)(selectionSet, {
509
- ...context,
510
- exclude: selection,
511
- }), fragmentMap)) {
512
- return true;
513
- }
514
- }
515
- else if (isPartialInSelectionSet(fragment.selectionSet, missingTree, context)) {
516
- return true;
517
- }
518
- }
519
- }
520
- return false;
521
- }
522
- function isPartialDeferBoundary(selectionSet, missing, nonDeferredFields, fragmentMap) {
523
- // This flag tracks whether all fields in this selection set should contain
524
- // values or should all be missing. A defer boundary is only partial if some
525
- // fields are missing. The first selection node will set this value and all
526
- // sibling fields should match after that. As soon as we get a mismatch, we
527
- // have a partial defer boundary.
528
- let shouldContainValues;
529
- for (const selection of selectionSet.selections) {
530
- if ((0, internal_1.isField)(selection)) {
531
- if ((0, internal_1.isTypenameField)(selection))
532
- continue;
533
- const name = (0, internal_1.resultKeyNameFromField)(selection);
534
- const nonDeferredField = nonDeferredFields?.[name];
535
- // If this field is not exclusive to this selection set, we don't care
536
- // what the value is as far as the defer boundary is concerned. Ignore it
537
- // and continue checking other siblings.
538
- if (nonDeferredField === true)
539
- continue;
540
- // The value of missing means different things:
541
- // - undefined: The field is fully satisfied (i.e. it has a value for the field)
542
- // - string: the field is fully unsatisfied (no scalar value, or object is
543
- // missing all fields)
544
- // - object: The field has a selection set and is partially satisfied.
545
- const missingField = missing[name];
546
- if (typeof missingField !== "object") {
547
- const hasValue = missingField === undefined;
548
- if (shouldContainValues === undefined) {
549
- shouldContainValues = hasValue;
550
- }
551
- if (hasValue !== shouldContainValues) {
552
- return true;
553
- }
554
- continue;
555
- }
556
- if (selection.selectionSet &&
557
- isPartialDeferBoundary(selection.selectionSet, missingField, nonDeferredField, fragmentMap)) {
558
- return true;
559
- }
560
- }
561
- else {
562
- const fragment = (0, internal_1.getFragmentFromSelection)(selection, fragmentMap);
563
- if (!fragment)
564
- continue;
565
- if (isPartialDeferBoundary(fragment.selectionSet, missing, nonDeferredFields, fragmentMap)) {
566
- return true;
567
- }
568
- }
569
- }
570
- return false;
571
- }
572
- function isArrayIndex(key) {
573
- return /^\d+$/.test(key);
574
- }
575
489
  //# sourceMappingURL=QueryInfo.cjs.map