@apollo/client 4.3.0-alpha.6 → 4.3.0-alpha.7

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 (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/__cjs/cache/core/cache.cjs +1 -1
  3. package/__cjs/cache/inmemory/entityStore.cjs +3 -3
  4. package/__cjs/cache/inmemory/key-extractor.cjs +1 -1
  5. package/__cjs/cache/inmemory/policies.cjs +5 -5
  6. package/__cjs/cache/inmemory/readFromStore.cjs +3 -3
  7. package/__cjs/cache/inmemory/writeToStore.cjs +4 -4
  8. package/__cjs/core/ObservableQuery.cjs +166 -54
  9. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  10. package/__cjs/core/ObservableQuery.d.cts +3 -6
  11. package/__cjs/core/QueryInfo.cjs +11 -125
  12. package/__cjs/core/QueryInfo.cjs.map +1 -1
  13. package/__cjs/core/QueryInfo.d.cts +0 -24
  14. package/__cjs/core/QueryManager.cjs +12 -14
  15. package/__cjs/core/QueryManager.cjs.map +1 -1
  16. package/__cjs/core/RefetchEventManager.cjs +3 -3
  17. package/__cjs/invariantErrorCodes.cjs +52 -32
  18. package/__cjs/version.cjs +1 -1
  19. package/cache/core/cache.js +1 -1
  20. package/cache/inmemory/entityStore.js +3 -3
  21. package/cache/inmemory/key-extractor.js +1 -1
  22. package/cache/inmemory/policies.js +5 -5
  23. package/cache/inmemory/readFromStore.js +3 -3
  24. package/cache/inmemory/writeToStore.js +4 -4
  25. package/core/ObservableQuery.d.ts +3 -6
  26. package/core/ObservableQuery.js +162 -54
  27. package/core/ObservableQuery.js.map +1 -1
  28. package/core/QueryInfo.d.ts +1 -25
  29. package/core/QueryInfo.js +11 -125
  30. package/core/QueryInfo.js.map +1 -1
  31. package/core/QueryManager.js +12 -14
  32. package/core/QueryManager.js.map +1 -1
  33. package/core/RefetchEventManager.js +3 -3
  34. package/invariantErrorCodes.js +52 -32
  35. package/package.json +1 -1
  36. package/version.js +1 -1
@@ -16,12 +16,6 @@ export declare const enum CacheWriteBehavior {
16
16
  OVERWRITE = 1,
17
17
  MERGE = 2
18
18
  }
19
- interface LastWrite {
20
- result: FormattedExecutionResult<any, ExtensionsWithStreamInfo>;
21
- variables: ApolloClient.WatchQueryOptions["variables"];
22
- dmCount: number | undefined;
23
- hasNext: boolean;
24
- }
25
19
  interface OperationInfo<TData, TVariables extends OperationVariables, AllowedCacheWriteBehavior = CacheWriteBehavior> {
26
20
  document: DocumentNode | TypedDocumentNode<TData, TVariables>;
27
21
  variables: TVariables;
@@ -39,24 +33,6 @@ export declare class QueryInfo<TData, TVariables extends OperationVariables = Op
39
33
  private readonly observableQuery?;
40
34
  private incremental?;
41
35
  constructor(queryManager: QueryManager, observableQuery?: ObservableQuery<any, any>);
42
- /**
43
- * @internal
44
- * Tracks the last result written to the cache so that `shouldWrite` can skip
45
- * an identical write. Since a `QueryInfo` only ever represents a single
46
- * network request, this is shared by all `QueryInfo` instances of an
47
- * `ObservableQuery`. A standalone `QueryInfo` keeps a local version.
48
- *
49
- * A network result that was explicitly asked for always takes precedence over
50
- * what is already cached, so `ObservableQuery.refetch` and polling clear this
51
- * value before starting their request.
52
- *
53
- * @deprecated This is an internal API and should not be used directly. This can be removed or changed at any time.
54
- */
55
- _lastWrite?: LastWrite;
56
- private get lastWrite();
57
- private set lastWrite(value);
58
- resetLastWrite(): void;
59
- private shouldWrite;
60
36
  get hasNext(): boolean;
61
37
  get incrementalHandler(): Incremental.Handler<Record<string, unknown>>;
62
38
  private maybeHandleIncrementalResult;
@@ -86,4 +62,4 @@ export declare class QueryInfo<TData, TVariables extends OperationVariables = Op
86
62
  markSubscriptionResult(result: FormattedExecutionResult<TData>, { document, variables, errorPolicy, cacheWriteBehavior, }: OperationInfo<TData, TVariables, CacheWriteBehavior.FORBID | CacheWriteBehavior.MERGE>): void;
87
63
  }
88
64
  export {};
89
- //# sourceMappingURL=QueryInfo.d.ts.map
65
+ //# sourceMappingURL=QueryInfo.d.ts.map
package/core/QueryInfo.js CHANGED
@@ -1,27 +1,9 @@
1
- import { equal } from "@wry/equality";
2
1
  import { Trie } from "@wry/trie";
3
2
  import { __DEV__ } from "@apollo/client/utilities/environment";
4
3
  import { getOperationName, graphQLResultHasError, handleIncrementalSymbol, hasDirectives, toDiffWithDataState, } from "@apollo/client/utilities/internal";
5
4
  import { invariant } from "@apollo/client/utilities/invariant";
6
5
  import { NetworkStatus } from "./networkStatus.js";
7
6
  const IGNORE = {};
8
- const destructiveMethodCounts = new WeakMap();
9
- function wrapDestructiveCacheMethod(cache, methodName) {
10
- const original = cache[methodName];
11
- if (typeof original === "function") {
12
- // @ts-expect-error this is just too generic to be typed correctly
13
- cache[methodName] = function () {
14
- destructiveMethodCounts.set(cache,
15
- // The %1e15 allows the count to wrap around to 0 safely every
16
- // quadrillion evictions, so there's no risk of overflow. To be
17
- // clear, this is more of a pedantic principle than something
18
- // that matters in any conceivable practical scenario.
19
- (destructiveMethodCounts.get(cache) + 1) % 1e15);
20
- // @ts-expect-error this is just too generic to be typed correctly
21
- return original.apply(this, arguments);
22
- };
23
- }
24
- }
25
7
  const queryInfoIds = new WeakMap();
26
8
  // A QueryInfo object represents a single network request, either initiated
27
9
  // from the QueryManager or from an ObservableQuery.
@@ -35,60 +17,12 @@ export class QueryInfo {
35
17
  observableQuery;
36
18
  incremental;
37
19
  constructor(queryManager, observableQuery) {
38
- const cache = (this.cache = queryManager.cache);
20
+ this.cache = queryManager.cache;
39
21
  const id = (queryInfoIds.get(queryManager) || 0) + 1;
40
22
  queryInfoIds.set(queryManager, id);
41
23
  this.id = id + "";
42
24
  this.observableQuery = observableQuery;
43
25
  this.queryManager = queryManager;
44
- // Track how often cache.evict is called, since we want eviction to
45
- // override the write-skipping logic in `shouldWrite`, by causing it to
46
- // return true. Wrapping the cache.evict method is a bit of a hack, but it
47
- // saves us from having to make eviction counting an official part of the
48
- // ApolloCache API.
49
- if (!destructiveMethodCounts.has(cache)) {
50
- destructiveMethodCounts.set(cache, 0);
51
- wrapDestructiveCacheMethod(cache, "evict");
52
- wrapDestructiveCacheMethod(cache, "modify");
53
- wrapDestructiveCacheMethod(cache, "reset");
54
- }
55
- }
56
- /**
57
- * @internal
58
- * Tracks the last result written to the cache so that `shouldWrite` can skip
59
- * an identical write. Since a `QueryInfo` only ever represents a single
60
- * network request, this is shared by all `QueryInfo` instances of an
61
- * `ObservableQuery`. A standalone `QueryInfo` keeps a local version.
62
- *
63
- * A network result that was explicitly asked for always takes precedence over
64
- * what is already cached, so `ObservableQuery.refetch` and polling clear this
65
- * value before starting their request.
66
- *
67
- * @deprecated This is an internal API and should not be used directly. This can be removed or changed at any time.
68
- */
69
- _lastWrite;
70
- get lastWrite() {
71
- return (this.observableQuery || this)._lastWrite;
72
- }
73
- set lastWrite(value) {
74
- (this.observableQuery || this)._lastWrite = value;
75
- }
76
- resetLastWrite() {
77
- this.lastWrite = void 0;
78
- }
79
- shouldWrite(result, variables) {
80
- const { lastWrite } = this;
81
- return (!lastWrite ||
82
- // If cache.evict has been called since the last time we wrote this
83
- // data into the cache, there's a chance writing this result into
84
- // the cache will repair what was evicted.
85
- lastWrite.dmCount !== destructiveMethodCounts.get(this.cache) ||
86
- !equal(variables, lastWrite.variables) ||
87
- !equal(result.data, lastWrite.result.data) ||
88
- // We have to compare these values because its possible the final chunk
89
- // emitted in the incremental result is just `hasNext: false`. This
90
- // ensures we trigger a cache write when we get `isLastChunk: true`.
91
- lastWrite.hasNext !== this.hasNext);
92
26
  }
93
27
  get hasNext() {
94
28
  return this.incremental ? this.incremental.hasNext : false;
@@ -155,14 +89,9 @@ export class QueryInfo {
155
89
  hasDirectives(["defer"], query))) {
156
90
  result.dataState = "streaming";
157
91
  }
158
- if (skipCache) {
159
- return result;
160
- }
161
- if (!shouldWriteResult(result, errorPolicy)) {
162
- this.lastWrite = void 0;
92
+ if (skipCache || !shouldWriteResult(result, errorPolicy)) {
163
93
  return result;
164
94
  }
165
- let written = false;
166
95
  // Using a transaction here so we have a chance to read the result
167
96
  // back from the cache before the watch callback fires as a result
168
97
  // of writeQuery, so we can store the new diff quietly and ignore
@@ -178,55 +107,13 @@ export class QueryInfo {
178
107
  }
179
108
  },
180
109
  update: (cache) => {
181
- const shouldWrite = this.shouldWrite(result, variables);
182
- // If result is the same as the last result we received from
183
- // the network (and the variables match too), avoid writing
184
- // result into the cache again. The wisdom of skipping this
185
- // cache write is far from obvious, since any cache write
186
- // could be the one that puts the cache back into a desired
187
- // state, fixing corruption or missing data. However, if we
188
- // always write every network result into the cache, we enable
189
- // feuds between queries competing to update the same data in
190
- // incompatible ways, which can lead to an endless cycle of
191
- // cache broadcasts and useless network requests. As with any
192
- // feud, eventually one side must step back from the brink,
193
- // letting the other side(s) have the last word(s). There may
194
- // be other points where we could break this cycle, such as
195
- // silencing the broadcast for cache.writeQuery (not a good
196
- // idea, since it just delays the feud a bit) or somehow
197
- // avoiding the network request that just happened (also bad,
198
- // because the server could return useful new data). All
199
- // options considered, skipping this cache write seems to be
200
- // the least damaging place to break the cycle, because it
201
- // reflects the intuition that we recently wrote this exact
202
- // result into the cache, so the cache *should* already/still
203
- // contain this data. If some other query has clobbered that
204
- // data in the meantime, that's too bad, but there will be no
205
- // winners if every query blindly reverts to its own version
206
- // of the data. This approach also gives the network a chance
207
- // to return new data, which will be written into the cache as
208
- // usual, notifying only those queries that are directly
209
- // affected by the cache updates, as usual. In the future, an
210
- // even more sophisticated cache could perhaps prevent or
211
- // mitigate the clobbering somehow, but that would make this
212
- // particular cache write even less important, and thus
213
- // skipping it would be even safer than it is today.
214
- if (shouldWrite) {
215
- cache.writeQuery({
216
- query,
217
- data: result.data,
218
- variables,
219
- overwrite: cacheWriteBehavior === 1 /* CacheWriteBehavior.OVERWRITE */,
220
- extensions: result.extensions,
221
- });
222
- this.lastWrite = {
223
- result,
224
- variables,
225
- dmCount: destructiveMethodCounts.get(this.cache),
226
- hasNext: this.hasNext,
227
- };
228
- written = true;
229
- }
110
+ cache.writeQuery({
111
+ query,
112
+ data: result.data,
113
+ variables,
114
+ overwrite: cacheWriteBehavior === 1 /* CacheWriteBehavior.OVERWRITE */,
115
+ extensions: result.extensions,
116
+ });
230
117
  const { dataState, result: diffResult } = this.getDiff({
231
118
  ...diffOptions,
232
119
  returnPartialData: returnPartialData &&
@@ -236,11 +123,10 @@ export class QueryInfo {
236
123
  }, this.getIncrementalInfo({ prune }));
237
124
  if (dataState === "complete" ||
238
125
  dataState === "streaming" ||
239
- (returnPartialData && dataState === "partial" && shouldWrite)) {
126
+ (returnPartialData && dataState === "partial")) {
240
127
  result = { ...result, data: diffResult, dataState };
241
128
  }
242
129
  else if (__DEV__ &&
243
- written &&
244
130
  // A result that is still streaming is expected to read back
245
131
  // incomplete until the remaining chunks arrive.
246
132
  !this.hasNext) {
@@ -477,7 +363,7 @@ export class QueryInfo {
477
363
  }
478
364
  function warnAboutPartialCacheResult(query, networkResult, diff) {
479
365
  __DEV__ && invariant.warn(
480
- 89,
366
+ 90,
481
367
  getOperationName(query, "(anonymous)"),
482
368
  diff.missing?.missing,
483
369
  networkResult,