@apollo/client 4.0.0-alpha.8 → 4.0.0-alpha.9
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.
- package/.changeset/forty-tomatoes-punch.md +5 -0
- package/.changeset/fuzzy-tips-sit.md +5 -0
- package/.changeset/khaki-keys-deliver.md +5 -0
- package/.changeset/large-plants-know.md +5 -0
- package/.changeset/mean-lizards-think.md +5 -0
- package/.changeset/pre.json +6 -0
- package/.changeset/thin-peas-hear.md +16 -0
- package/CHANGELOG.md +29 -0
- package/__cjs/core/ObservableQuery.cjs +91 -28
- package/__cjs/core/ObservableQuery.cjs.map +1 -1
- package/__cjs/core/ObservableQuery.d.cts +2 -1
- package/__cjs/core/QueryManager.cjs +2 -2
- package/__cjs/core/QueryManager.cjs.map +1 -1
- package/__cjs/core/watchQueryOptions.d.cts +2 -2
- package/__cjs/react/hooks/useLazyQuery.cjs +17 -20
- package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useLazyQuery.d.cts +1 -1
- package/__cjs/react/hooks/useMutation.d.cts +1 -1
- package/__cjs/react/hooks/useQuery.d.cts +1 -1
- package/__cjs/react/query-preloader/createQueryPreloader.cjs +1 -0
- package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
- package/__cjs/react/types/types.documentation.d.cts +2 -2
- package/__cjs/testing/matchers/arrayWithLength.cjs +15 -0
- package/__cjs/testing/matchers/arrayWithLength.cjs.map +1 -0
- package/__cjs/testing/matchers/arrayWithLength.d.cts +3 -0
- package/__cjs/testing/matchers/index.cjs +2 -0
- package/__cjs/testing/matchers/index.cjs.map +1 -1
- package/__cjs/version.cjs +1 -1
- package/core/ObservableQuery.d.ts +2 -1
- package/core/ObservableQuery.js +91 -28
- package/core/ObservableQuery.js.map +1 -1
- package/core/QueryManager.js +2 -2
- package/core/QueryManager.js.map +1 -1
- package/core/watchQueryOptions.d.ts +2 -2
- package/package.json +1 -1
- package/react/hooks/useLazyQuery.d.ts +1 -1
- package/react/hooks/useLazyQuery.js +17 -20
- package/react/hooks/useLazyQuery.js.map +1 -1
- package/react/hooks/useMutation.d.ts +1 -1
- package/react/hooks/useQuery.d.ts +1 -1
- package/react/query-preloader/createQueryPreloader.js +1 -0
- package/react/query-preloader/createQueryPreloader.js.map +1 -1
- package/react/types/types.documentation.d.ts +2 -2
- package/testing/matchers/arrayWithLength.d.ts +3 -0
- package/testing/matchers/arrayWithLength.js +11 -0
- package/testing/matchers/arrayWithLength.js.map +1 -0
- package/testing/matchers/index.js +2 -0
- package/testing/matchers/index.js.map +1 -1
- package/version.js +1 -1
package/core/ObservableQuery.js
CHANGED
|
@@ -9,6 +9,7 @@ import { equalByQuery } from "./equalByQuery.js";
|
|
|
9
9
|
import { isNetworkRequestInFlight, NetworkStatus } from "./networkStatus.js";
|
|
10
10
|
const { assign, hasOwnProperty } = Object;
|
|
11
11
|
const newNetworkStatusSymbol = Symbol();
|
|
12
|
+
const uninitialized = {};
|
|
12
13
|
export class ObservableQuery {
|
|
13
14
|
/**
|
|
14
15
|
* @internal
|
|
@@ -38,7 +39,6 @@ export class ObservableQuery {
|
|
|
38
39
|
}
|
|
39
40
|
subject;
|
|
40
41
|
observable;
|
|
41
|
-
initialResult;
|
|
42
42
|
isTornDown;
|
|
43
43
|
queryManager;
|
|
44
44
|
subscriptions = new Set();
|
|
@@ -52,14 +52,8 @@ export class ObservableQuery {
|
|
|
52
52
|
networkStatus;
|
|
53
53
|
constructor({ queryManager, queryInfo, options, }) {
|
|
54
54
|
this.networkStatus = NetworkStatus.loading;
|
|
55
|
-
this.initialResult = {
|
|
56
|
-
data: undefined,
|
|
57
|
-
loading: true,
|
|
58
|
-
networkStatus: this.networkStatus,
|
|
59
|
-
partial: true,
|
|
60
|
-
};
|
|
61
55
|
let startedInactive = ObservableQuery.inactiveOnCreation.getValue();
|
|
62
|
-
this.subject = new BehaviorSubject(
|
|
56
|
+
this.subject = new BehaviorSubject(uninitialized);
|
|
63
57
|
this.observable = this.subject.pipe(tap({
|
|
64
58
|
subscribe: () => {
|
|
65
59
|
if (startedInactive) {
|
|
@@ -67,6 +61,22 @@ export class ObservableQuery {
|
|
|
67
61
|
startedInactive = false;
|
|
68
62
|
}
|
|
69
63
|
if (!this.subject.observed) {
|
|
64
|
+
if (this.subject.value === uninitialized) {
|
|
65
|
+
// Emitting a value in the `subscribe` callback of `tap` gives
|
|
66
|
+
// the subject a chance to save this initial result without
|
|
67
|
+
// emitting the placeholder value since this callback is executed
|
|
68
|
+
// before `tap` subscribes to the source observable (the subject).
|
|
69
|
+
// `reobserve` also has the chance to update this value if it
|
|
70
|
+
// synchronously emits one (usually due to reporting a cache
|
|
71
|
+
// value).
|
|
72
|
+
//
|
|
73
|
+
// We don't initialize the `BehaviorSubject` with
|
|
74
|
+
// `getInitialResult` because its possible the cache might have
|
|
75
|
+
// updated between when the `ObservableQuery` was instantiated and
|
|
76
|
+
// when it is subscribed to. Updating the value here ensures we
|
|
77
|
+
// report the most up-to-date result from the cache.
|
|
78
|
+
this.subject.next(this.getInitialResult());
|
|
79
|
+
}
|
|
70
80
|
this.reobserve();
|
|
71
81
|
// TODO: See if we can rework updatePolling to better handle this.
|
|
72
82
|
// reobserve calls updatePolling but this `subscribe` callback is
|
|
@@ -81,19 +91,14 @@ export class ObservableQuery {
|
|
|
81
91
|
this.tearDownQuery();
|
|
82
92
|
}
|
|
83
93
|
},
|
|
84
|
-
}),
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// TODO: Remove this behavior when unifying loading state for notifyOnNetworkStatusChange
|
|
93
|
-
(this.options.fetchPolicy === "network-only" &&
|
|
94
|
-
!this.queryManager.prioritizeCacheValues &&
|
|
95
|
-
this.queryInfo.getDiff().complete) ||
|
|
96
|
-
result !== this.initialResult));
|
|
94
|
+
}), filter((result) => {
|
|
95
|
+
return (this.options.fetchPolicy !== "standby" &&
|
|
96
|
+
(this.options.notifyOnNetworkStatusChange ||
|
|
97
|
+
!result.loading ||
|
|
98
|
+
// data could be defined for cache-and-network fetch policies
|
|
99
|
+
// when emitting the cache result while loading the network result
|
|
100
|
+
!!result.data));
|
|
101
|
+
}));
|
|
97
102
|
this["@@observable"] = () => this;
|
|
98
103
|
if (Symbol.observable) {
|
|
99
104
|
this[Symbol.observable] = () => this;
|
|
@@ -138,6 +143,50 @@ export class ObservableQuery {
|
|
|
138
143
|
resetDiff() {
|
|
139
144
|
this.queryInfo.resetDiff();
|
|
140
145
|
}
|
|
146
|
+
getInitialResult() {
|
|
147
|
+
const fetchPolicy = this.queryManager.prioritizeCacheValues ?
|
|
148
|
+
"cache-first"
|
|
149
|
+
: this.options.fetchPolicy;
|
|
150
|
+
const defaultResult = {
|
|
151
|
+
data: undefined,
|
|
152
|
+
loading: true,
|
|
153
|
+
networkStatus: NetworkStatus.loading,
|
|
154
|
+
partial: true,
|
|
155
|
+
};
|
|
156
|
+
const cacheResult = () => {
|
|
157
|
+
const diff = this.queryInfo.getDiff();
|
|
158
|
+
return this.maskResult({
|
|
159
|
+
data:
|
|
160
|
+
// TODO: queryInfo.getDiff should handle this since cache.diff returns a
|
|
161
|
+
// null when returnPartialData is false
|
|
162
|
+
this.options.returnPartialData || diff.complete ?
|
|
163
|
+
diff.result ?? undefined
|
|
164
|
+
: undefined,
|
|
165
|
+
loading: !diff.complete,
|
|
166
|
+
networkStatus: diff.complete ? NetworkStatus.ready : NetworkStatus.loading,
|
|
167
|
+
partial: !diff.complete,
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
switch (fetchPolicy) {
|
|
171
|
+
case "cache-only":
|
|
172
|
+
case "cache-first":
|
|
173
|
+
return cacheResult();
|
|
174
|
+
case "cache-and-network":
|
|
175
|
+
return {
|
|
176
|
+
...cacheResult(),
|
|
177
|
+
loading: true,
|
|
178
|
+
networkStatus: NetworkStatus.loading,
|
|
179
|
+
};
|
|
180
|
+
case "standby":
|
|
181
|
+
return {
|
|
182
|
+
...defaultResult,
|
|
183
|
+
loading: false,
|
|
184
|
+
networkStatus: NetworkStatus.ready,
|
|
185
|
+
};
|
|
186
|
+
default:
|
|
187
|
+
return defaultResult;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
141
190
|
getCurrentFullResult(saveAsLastResult = true) {
|
|
142
191
|
// Use the last result as long as the variables match this.variables.
|
|
143
192
|
const lastResult = this.getLastResult(true);
|
|
@@ -313,6 +362,7 @@ export class ObservableQuery {
|
|
|
313
362
|
// fetchMore to provide an updateQuery callback that determines how
|
|
314
363
|
// the data gets written to the cache.
|
|
315
364
|
fetchPolicy: "no-cache",
|
|
365
|
+
notifyOnNetworkStatusChange: this.options.notifyOnNetworkStatusChange,
|
|
316
366
|
};
|
|
317
367
|
combinedOptions.query = this.transformDocument(combinedOptions.query);
|
|
318
368
|
const qid = this.queryManager.generateQueryId();
|
|
@@ -605,10 +655,7 @@ export class ObservableQuery {
|
|
|
605
655
|
}
|
|
606
656
|
const { pollingInfo, options: { pollInterval }, } = this;
|
|
607
657
|
if (!pollInterval || !this.hasObservers()) {
|
|
608
|
-
|
|
609
|
-
clearTimeout(pollingInfo.timeout);
|
|
610
|
-
delete this.pollingInfo;
|
|
611
|
-
}
|
|
658
|
+
this.cancelPolling();
|
|
612
659
|
return;
|
|
613
660
|
}
|
|
614
661
|
if (pollingInfo && pollingInfo.interval === pollInterval) {
|
|
@@ -646,6 +693,13 @@ export class ObservableQuery {
|
|
|
646
693
|
};
|
|
647
694
|
poll();
|
|
648
695
|
}
|
|
696
|
+
// This differs from stopPolling in that it does not set pollInterval to 0
|
|
697
|
+
cancelPolling() {
|
|
698
|
+
if (this.pollingInfo) {
|
|
699
|
+
clearTimeout(this.pollingInfo.timeout);
|
|
700
|
+
delete this.pollingInfo;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
649
703
|
updateLastResult(newResult, variables = this.variables) {
|
|
650
704
|
let error = this.getLastError();
|
|
651
705
|
// Preserve this.last.error unless the variables have changed.
|
|
@@ -697,6 +751,7 @@ export class ObservableQuery {
|
|
|
697
751
|
// We want to ensure we can re-run the custom document transforms the next
|
|
698
752
|
// time a request is made against the original query.
|
|
699
753
|
const query = this.transformDocument(options.query);
|
|
754
|
+
const { fetchPolicy } = options;
|
|
700
755
|
this.lastQuery = query;
|
|
701
756
|
if (!useDisposableObservable) {
|
|
702
757
|
// We can skip calling updatePolling if we're not changing this.options.
|
|
@@ -707,10 +762,10 @@ export class ObservableQuery {
|
|
|
707
762
|
newOptions.variables &&
|
|
708
763
|
!equal(newOptions.variables, oldVariables) &&
|
|
709
764
|
// Don't mess with the fetchPolicy if it's currently "standby".
|
|
710
|
-
|
|
765
|
+
fetchPolicy !== "standby" &&
|
|
711
766
|
// If we're changing the fetchPolicy anyway, don't try to change it here
|
|
712
767
|
// using applyNextFetchPolicy. The explicit options.fetchPolicy wins.
|
|
713
|
-
(
|
|
768
|
+
(fetchPolicy === oldFetchPolicy ||
|
|
714
769
|
// A `nextFetchPolicy` function has even higher priority, though,
|
|
715
770
|
// so in that case `applyNextFetchPolicy` must be called.
|
|
716
771
|
typeof options.nextFetchPolicy === "function")) {
|
|
@@ -728,6 +783,14 @@ export class ObservableQuery {
|
|
|
728
783
|
!equal(newOptions.variables, oldVariables)) {
|
|
729
784
|
newNetworkStatus = NetworkStatus.setVariables;
|
|
730
785
|
}
|
|
786
|
+
// QueryManager does not emit any values for standby fetch policies so we
|
|
787
|
+
// want ensure that the networkStatus remains ready.
|
|
788
|
+
if (fetchPolicy === "standby") {
|
|
789
|
+
newNetworkStatus = NetworkStatus.ready;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (fetchPolicy === "standby") {
|
|
793
|
+
this.cancelPolling();
|
|
731
794
|
}
|
|
732
795
|
this.networkStatus = newNetworkStatus;
|
|
733
796
|
this.waitForOwnResult &&= skipCacheDataFor(options.fetchPolicy);
|
|
@@ -737,7 +800,7 @@ export class ObservableQuery {
|
|
|
737
800
|
}
|
|
738
801
|
};
|
|
739
802
|
const variables = options.variables && { ...options.variables };
|
|
740
|
-
const { notifyOnNetworkStatusChange =
|
|
803
|
+
const { notifyOnNetworkStatusChange = true } = options;
|
|
741
804
|
const { observable, fromLink } = this.fetch(options, newNetworkStatus, notifyOnNetworkStatusChange &&
|
|
742
805
|
oldNetworkStatus !== newNetworkStatus &&
|
|
743
806
|
isNetworkRequestInFlight(newNetworkStatus), query);
|