@apollo/client 4.0.0-alpha.19 → 4.0.0-alpha.20

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 (50) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/__cjs/core/ApolloClient.cjs +2 -2
  3. package/__cjs/core/ApolloClient.cjs.map +1 -1
  4. package/__cjs/core/ApolloClient.d.cts +1 -1
  5. package/__cjs/core/ObservableQuery.cjs +51 -45
  6. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  7. package/__cjs/core/ObservableQuery.d.cts +16 -16
  8. package/__cjs/core/QueryInfo.cjs +27 -31
  9. package/__cjs/core/QueryInfo.cjs.map +1 -1
  10. package/__cjs/core/QueryInfo.d.cts +23 -6
  11. package/__cjs/core/QueryManager.cjs +66 -121
  12. package/__cjs/core/QueryManager.cjs.map +1 -1
  13. package/__cjs/core/QueryManager.d.cts +14 -8
  14. package/__cjs/react/hooks/useQuery.cjs +1 -1
  15. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  16. package/__cjs/react/hooks/useQuery.d.cts +2 -2
  17. package/__cjs/react/internal/cache/FragmentReference.cjs +4 -1
  18. package/__cjs/react/internal/cache/FragmentReference.cjs.map +1 -1
  19. package/__cjs/react/internal/cache/QueryReference.cjs +5 -18
  20. package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
  21. package/__cjs/react/internal/cache/QueryReference.d.cts +6 -43
  22. package/__cjs/react/query-preloader/createQueryPreloader.cjs +8 -2
  23. package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
  24. package/__cjs/react/query-preloader/createQueryPreloader.d.cts +38 -0
  25. package/__cjs/version.cjs +1 -1
  26. package/core/ApolloClient.d.ts +1 -1
  27. package/core/ApolloClient.js +2 -2
  28. package/core/ApolloClient.js.map +1 -1
  29. package/core/ObservableQuery.d.ts +16 -16
  30. package/core/ObservableQuery.js +51 -45
  31. package/core/ObservableQuery.js.map +1 -1
  32. package/core/QueryInfo.d.ts +23 -6
  33. package/core/QueryInfo.js +27 -31
  34. package/core/QueryInfo.js.map +1 -1
  35. package/core/QueryManager.d.ts +14 -8
  36. package/core/QueryManager.js +67 -122
  37. package/core/QueryManager.js.map +1 -1
  38. package/package.json +1 -1
  39. package/react/hooks/useQuery.d.ts +2 -2
  40. package/react/hooks/useQuery.js +2 -2
  41. package/react/hooks/useQuery.js.map +1 -1
  42. package/react/internal/cache/FragmentReference.js +4 -1
  43. package/react/internal/cache/FragmentReference.js.map +1 -1
  44. package/react/internal/cache/QueryReference.d.ts +6 -43
  45. package/react/internal/cache/QueryReference.js +5 -18
  46. package/react/internal/cache/QueryReference.js.map +1 -1
  47. package/react/query-preloader/createQueryPreloader.d.ts +38 -0
  48. package/react/query-preloader/createQueryPreloader.js +9 -3
  49. package/react/query-preloader/createQueryPreloader.js.map +1 -1
  50. package/version.js +1 -1
@@ -1,11 +1,11 @@
1
1
  import { equal } from "@wry/equality";
2
- import { Slot } from "optimism";
3
2
  import { BehaviorSubject, Observable, share, Subject, tap } from "rxjs";
4
3
  import { __DEV__ } from "@apollo/client/utilities/environment";
5
4
  import { compact, filterMap, getOperationDefinition, getQueryDefinition, preventUnhandledRejection, toQueryResult, } from "@apollo/client/utilities/internal";
6
5
  import { invariant } from "@apollo/client/utilities/invariant";
7
6
  import { equalByQuery } from "./equalByQuery.js";
8
7
  import { isNetworkRequestInFlight, NetworkStatus } from "./networkStatus.js";
8
+ import { QueryInfo } from "./QueryInfo.js";
9
9
  const { assign, hasOwnProperty } = Object;
10
10
  const uninitialized = {
11
11
  loading: true,
@@ -22,19 +22,14 @@ const empty = {
22
22
  partial: true,
23
23
  };
24
24
  export class ObservableQuery {
25
+ options;
26
+ queryName;
25
27
  /**
26
- * @internal
27
- * A slot used by the `useQuery` hook to indicate that `client.watchQuery`
28
- * should not register the query immediately, but instead wait for the query to
29
- * be started registered with the `QueryManager` when `useSyncExternalStore`
30
- * actively subscribes to it.
28
+ * @internal will be read and written from `QueryInfo`
31
29
  *
32
30
  * @deprecated This is an internal API and should not be used directly. This can be removed or changed at any time.
33
31
  */
34
- static inactiveOnCreation = new Slot();
35
- options;
36
- queryId;
37
- queryName;
32
+ _lastWrite;
38
33
  // The `query` computed property will always reflect the document transformed
39
34
  // by the last run query. `this.options.query` will always reflect the raw
40
35
  // untransformed query to ensure document transforms with runtime conditionals
@@ -51,7 +46,6 @@ export class ObservableQuery {
51
46
  unsubscribeFromCache;
52
47
  input;
53
48
  subject;
54
- observable;
55
49
  isTornDown;
56
50
  queryManager;
57
51
  subscriptions = new Set();
@@ -62,16 +56,12 @@ export class ObservableQuery {
62
56
  */
63
57
  waitForNetworkResult;
64
58
  lastQuery;
65
- queryInfo;
66
59
  linkSubscription;
67
60
  pollingInfo;
68
61
  get networkStatus() {
69
62
  return this.subject.getValue().result.networkStatus;
70
63
  }
71
- constructor({ queryManager, queryInfo, options, }) {
72
- let startedInactive = ObservableQuery.inactiveOnCreation.getValue();
73
- // related classes
74
- this.queryInfo = queryInfo;
64
+ constructor({ queryManager, options, transformedQuery = queryManager.transform(options.query), }) {
75
65
  this.queryManager = queryManager;
76
66
  // active state
77
67
  this.waitForNetworkResult = options.fetchPolicy === "network-only";
@@ -82,7 +72,7 @@ export class ObservableQuery {
82
72
  const { fetchPolicy = defaultFetchPolicy,
83
73
  // Make sure we don't store "standby" as the initialFetchPolicy.
84
74
  initialFetchPolicy = fetchPolicy === "standby" ? defaultFetchPolicy : (fetchPolicy), } = options;
85
- this.lastQuery = options.query;
75
+ this.lastQuery = transformedQuery;
86
76
  this.options = {
87
77
  ...options,
88
78
  // Remember the initial options.fetchPolicy so we can revert back to this
@@ -94,18 +84,23 @@ export class ObservableQuery {
94
84
  fetchPolicy,
95
85
  variables: this.getVariablesWithDefaults(options.variables),
96
86
  };
87
+ this.initializeObservablesQueue();
88
+ this["@@observable"] = () => this;
89
+ if (Symbol.observable) {
90
+ this[Symbol.observable] = () => this;
91
+ }
92
+ const opDef = getOperationDefinition(this.query);
93
+ this.queryName = opDef && opDef.name && opDef.name.value;
94
+ }
95
+ initializeObservablesQueue() {
97
96
  this.subject = new BehaviorSubject({
98
97
  query: this.query,
99
98
  variables: this.variables,
100
99
  result: uninitialized,
101
100
  meta: {},
102
101
  });
103
- this.observable = this.subject.pipe(tap({
102
+ const observable = this.subject.pipe(tap({
104
103
  subscribe: () => {
105
- if (startedInactive) {
106
- queryManager["queries"].set(this.queryId, queryInfo);
107
- startedInactive = false;
108
- }
109
104
  if (!this.subject.observed) {
110
105
  this.reobserve();
111
106
  // TODO: See if we can rework updatePolling to better handle this.
@@ -157,20 +152,13 @@ export class ObservableQuery {
157
152
  return current;
158
153
  }
159
154
  }, () => ({})));
160
- this["@@observable"] = () => this;
161
- if (Symbol.observable) {
162
- this[Symbol.observable] = () => this;
163
- }
164
- this.pipe = this.observable.pipe.bind(this.observable);
165
- this.subscribe = this.observable.subscribe.bind(this.observable);
155
+ this.pipe = observable.pipe.bind(observable);
156
+ this.subscribe = observable.subscribe.bind(observable);
166
157
  this.input = new Subject();
167
158
  // we want to feed many streams into `this.subject`, but none of them should
168
159
  // be able to close `this.input`
169
160
  this.input.complete = () => { };
170
161
  this.input.pipe(this.operator).subscribe(this.subject);
171
- this.queryId = queryInfo.queryId || queryManager.generateQueryId();
172
- const opDef = getOperationDefinition(this.query);
173
- this.queryName = opDef && opDef.name && opDef.name.value;
174
162
  }
175
163
  // We can't use Observable['subscribe'] here as the type as it conflicts with
176
164
  // the ability to infer T from Subscribable<T>. This limits the surface area
@@ -184,9 +172,6 @@ export class ObservableQuery {
184
172
  *
185
173
  * @deprecated This is an internal API and should not be used directly. This can be removed or changed at any time.
186
174
  */
187
- resetDiff() {
188
- this.queryInfo.resetDiff();
189
- }
190
175
  getCacheDiff({ optimistic = true } = {}) {
191
176
  return this.queryManager.cache.diff({
192
177
  query: this.query,
@@ -369,7 +354,7 @@ export class ObservableQuery {
369
354
  reobserveOptions.variables = this.options.variables =
370
355
  this.getVariablesWithDefaults({ ...this.variables, ...variables });
371
356
  }
372
- this.queryInfo.resetLastWrite();
357
+ this._lastWrite = undefined;
373
358
  return this._reobserve(reobserveOptions, {
374
359
  newNetworkStatus: NetworkStatus.refetch,
375
360
  });
@@ -397,7 +382,6 @@ export class ObservableQuery {
397
382
  notifyOnNetworkStatusChange: this.options.notifyOnNetworkStatusChange,
398
383
  };
399
384
  combinedOptions.query = this.transformDocument(combinedOptions.query);
400
- const qid = this.queryManager.generateQueryId();
401
385
  // If a temporary query is passed to `fetchMore`, we don't want to store
402
386
  // it as the last query result since it may be an optimized query for
403
387
  // pagination. We will however run the transforms on the original document
@@ -420,9 +404,8 @@ export class ObservableQuery {
420
404
  value: {},
421
405
  }, { shouldEmit: 3 /* EmitBehavior.networkStatusChange */ });
422
406
  return this.queryManager
423
- .fetchQuery(qid, combinedOptions, NetworkStatus.fetchMore)
407
+ .fetchQuery(combinedOptions, NetworkStatus.fetchMore)
424
408
  .then((fetchMoreResult) => {
425
- this.queryManager.removeQuery(qid);
426
409
  // disable the `fetchMore` override that is currently active
427
410
  // the next updates caused by this should not be `fetchMore` anymore,
428
411
  // but `ready` or whatever other calculated loading state is currently
@@ -684,8 +667,10 @@ export class ObservableQuery {
684
667
  // TODO Make sure we update the networkStatus (and infer fetchVariables)
685
668
  // before actually committing to the fetch.
686
669
  const initialFetchPolicy = this.options.fetchPolicy;
687
- const queryInfo = this.queryManager.getOrCreateQuery(this.queryId);
688
- queryInfo.setObservableQuery(this);
670
+ const queryInfo = new QueryInfo({
671
+ queryManager: this.queryManager,
672
+ observableQuery: this,
673
+ });
689
674
  options.context ??= {};
690
675
  let synchronouslyEmitted = false;
691
676
  const onCacheHit = () => {
@@ -706,7 +691,7 @@ export class ObservableQuery {
706
691
  });
707
692
  }
708
693
  finally {
709
- if (!synchronouslyEmitted && this.activeOperations.has(operation)) {
694
+ if (!synchronouslyEmitted) {
710
695
  operation.override = networkStatus;
711
696
  this.input.next({
712
697
  kind: "N",
@@ -735,7 +720,9 @@ export class ObservableQuery {
735
720
  // track query and variables from the start of the operation
736
721
  const { query, variables } = this;
737
722
  const operation = {
738
- abort: () => subscription.unsubscribe(),
723
+ abort: () => {
724
+ subscription.unsubscribe();
725
+ },
739
726
  query,
740
727
  variables,
741
728
  };
@@ -835,6 +822,7 @@ export class ObservableQuery {
835
822
  _reobserve(newOptions, internalOptions) {
836
823
  this.isTornDown = false;
837
824
  let { newNetworkStatus } = internalOptions || {};
825
+ this.queryManager.obsQueries.add(this);
838
826
  const useDisposableObservable =
839
827
  // Refetching uses a disposable Observable to allow refetches using different
840
828
  // options, without permanently altering the options of the
@@ -932,7 +920,16 @@ export class ObservableQuery {
932
920
  }
933
921
  this.linkSubscription = subscription;
934
922
  }
935
- const ret = Object.assign(preventUnhandledRejection(promise.then((result) => toQueryResult(this.maskResult(result)))), {
923
+ const ret = Object.assign(preventUnhandledRejection(promise
924
+ .then((result) => toQueryResult(this.maskResult(result)))
925
+ .finally(() => {
926
+ if (!this.hasObservers() && this.activeOperations.size === 0) {
927
+ // If `reobserve` was called on a query without any obervers,
928
+ // the teardown logic would never be called, so we need to
929
+ // call it here to ensure the query is properly torn down.
930
+ this.tearDownQuery();
931
+ }
932
+ })), {
936
933
  retain: () => {
937
934
  const subscription = observable.subscribe({});
938
935
  const unsubscribe = () => subscription.unsubscribe();
@@ -945,6 +942,14 @@ export class ObservableQuery {
945
942
  hasObservers() {
946
943
  return this.subject.observed;
947
944
  }
945
+ /**
946
+ * Tears down the `ObservableQuery` and stops all active operations by sending a `complete` notification.
947
+ */
948
+ stop() {
949
+ this.subject.complete();
950
+ this.initializeObservablesQueue();
951
+ this.tearDownQuery();
952
+ }
948
953
  tearDownQuery() {
949
954
  if (this.isTornDown)
950
955
  return;
@@ -958,9 +963,10 @@ export class ObservableQuery {
958
963
  // stop all active GraphQL subscriptions
959
964
  this.subscriptions.forEach((sub) => sub.unsubscribe());
960
965
  this.subscriptions.clear();
961
- this.queryManager.removeQuery(this.queryId);
966
+ this.queryManager.obsQueries.delete(this);
962
967
  this.isTornDown = true;
963
968
  this.abortActiveOperations();
969
+ this._lastWrite = undefined;
964
970
  }
965
971
  transformDocument(document) {
966
972
  return this.queryManager.transform(document);
@@ -973,7 +979,7 @@ export class ObservableQuery {
973
979
  document: this.query,
974
980
  data: result.data,
975
981
  fetchPolicy: this.options.fetchPolicy,
976
- id: this.queryId,
982
+ cause: this,
977
983
  }),
978
984
  }
979
985
  : result;