1 | import { __assign, __extends } from "tslib";
|
2 | import { invariant } from "../utilities/globals/index.js";
|
3 | import { equal } from '@wry/equality';
|
4 | import { NetworkStatus, isNetworkRequestInFlight } from "./networkStatus.js";
|
5 | import { cloneDeep, compact, getOperationDefinition, Observable, iterateObserversSafely, isNonEmptyArray, fixObservableSubclass, getQueryDefinition, } from "../utilities/index.js";
|
6 | var assign = Object.assign, hasOwnProperty = Object.hasOwnProperty;
|
7 | var ObservableQuery = (function (_super) {
|
8 | __extends(ObservableQuery, _super);
|
9 | function ObservableQuery(_a) {
|
10 | var queryManager = _a.queryManager, queryInfo = _a.queryInfo, options = _a.options;
|
11 | var _this = _super.call(this, function (observer) {
|
12 | try {
|
13 | var subObserver = observer._subscription._observer;
|
14 | if (subObserver && !subObserver.error) {
|
15 | subObserver.error = defaultSubscriptionObserverErrorCallback;
|
16 | }
|
17 | }
|
18 | catch (_a) { }
|
19 | var first = !_this.observers.size;
|
20 | _this.observers.add(observer);
|
21 | var last = _this.last;
|
22 | if (last && last.error) {
|
23 | observer.error && observer.error(last.error);
|
24 | }
|
25 | else if (last && last.result) {
|
26 | observer.next && observer.next(last.result);
|
27 | }
|
28 | if (first) {
|
29 | _this.reobserve().catch(function () { });
|
30 | }
|
31 | return function () {
|
32 | if (_this.observers.delete(observer) && !_this.observers.size) {
|
33 | _this.tearDownQuery();
|
34 | }
|
35 | };
|
36 | }) || this;
|
37 | _this.observers = new Set();
|
38 | _this.subscriptions = new Set();
|
39 | _this.queryInfo = queryInfo;
|
40 | _this.queryManager = queryManager;
|
41 | _this.isTornDown = false;
|
42 | var _b = queryManager.defaultOptions.watchQuery, _c = _b === void 0 ? {} : _b, _d = _c.fetchPolicy, defaultFetchPolicy = _d === void 0 ? "cache-first" : _d;
|
43 | var _e = options.fetchPolicy, fetchPolicy = _e === void 0 ? defaultFetchPolicy : _e, _f = options.initialFetchPolicy, initialFetchPolicy = _f === void 0 ? (fetchPolicy === "standby" ? defaultFetchPolicy : fetchPolicy) : _f;
|
44 | _this.options = __assign(__assign({}, options), { initialFetchPolicy: initialFetchPolicy, fetchPolicy: fetchPolicy });
|
45 | _this.queryId = queryInfo.queryId || queryManager.generateQueryId();
|
46 | var opDef = getOperationDefinition(_this.query);
|
47 | _this.queryName = opDef && opDef.name && opDef.name.value;
|
48 | return _this;
|
49 | }
|
50 | Object.defineProperty(ObservableQuery.prototype, "query", {
|
51 | get: function () {
|
52 | return this.queryManager.transform(this.options.query).document;
|
53 | },
|
54 | enumerable: false,
|
55 | configurable: true
|
56 | });
|
57 | Object.defineProperty(ObservableQuery.prototype, "variables", {
|
58 | get: function () {
|
59 | return this.options.variables;
|
60 | },
|
61 | enumerable: false,
|
62 | configurable: true
|
63 | });
|
64 | ObservableQuery.prototype.result = function () {
|
65 | var _this = this;
|
66 | return new Promise(function (resolve, reject) {
|
67 | var observer = {
|
68 | next: function (result) {
|
69 | resolve(result);
|
70 | _this.observers.delete(observer);
|
71 | if (!_this.observers.size) {
|
72 | _this.queryManager.removeQuery(_this.queryId);
|
73 | }
|
74 | setTimeout(function () {
|
75 | subscription.unsubscribe();
|
76 | }, 0);
|
77 | },
|
78 | error: reject,
|
79 | };
|
80 | var subscription = _this.subscribe(observer);
|
81 | });
|
82 | };
|
83 | ObservableQuery.prototype.getCurrentResult = function (saveAsLastResult) {
|
84 | if (saveAsLastResult === void 0) { saveAsLastResult = true; }
|
85 | var lastResult = this.getLastResult(true);
|
86 | var networkStatus = this.queryInfo.networkStatus ||
|
87 | (lastResult && lastResult.networkStatus) ||
|
88 | NetworkStatus.ready;
|
89 | var result = __assign(__assign({}, lastResult), { loading: isNetworkRequestInFlight(networkStatus), networkStatus: networkStatus });
|
90 | var _a = this.options.fetchPolicy, fetchPolicy = _a === void 0 ? "cache-first" : _a;
|
91 | if (fetchPolicy === 'network-only' ||
|
92 | fetchPolicy === 'no-cache' ||
|
93 | fetchPolicy === 'standby' ||
|
94 | this.queryManager.transform(this.options.query).hasForcedResolvers) {
|
95 | }
|
96 | else {
|
97 | var diff = this.queryInfo.getDiff();
|
98 | if (diff.complete || this.options.returnPartialData) {
|
99 | result.data = diff.result;
|
100 | }
|
101 | if (equal(result.data, {})) {
|
102 | result.data = void 0;
|
103 | }
|
104 | if (diff.complete) {
|
105 | delete result.partial;
|
106 | if (diff.complete &&
|
107 | result.networkStatus === NetworkStatus.loading &&
|
108 | (fetchPolicy === 'cache-first' ||
|
109 | fetchPolicy === 'cache-only')) {
|
110 | result.networkStatus = NetworkStatus.ready;
|
111 | result.loading = false;
|
112 | }
|
113 | }
|
114 | else {
|
115 | result.partial = true;
|
116 | }
|
117 | if (__DEV__ &&
|
118 | !diff.complete &&
|
119 | !this.options.partialRefetch &&
|
120 | !result.loading &&
|
121 | !result.data &&
|
122 | !result.error) {
|
123 | logMissingFieldErrors(diff.missing);
|
124 | }
|
125 | }
|
126 | if (saveAsLastResult) {
|
127 | this.updateLastResult(result);
|
128 | }
|
129 | return result;
|
130 | };
|
131 | ObservableQuery.prototype.isDifferentFromLastResult = function (newResult, variables) {
|
132 | return (!this.last ||
|
133 | !equal(this.last.result, newResult) ||
|
134 | (variables && !equal(this.last.variables, variables)));
|
135 | };
|
136 | ObservableQuery.prototype.getLast = function (key, variablesMustMatch) {
|
137 | var last = this.last;
|
138 | if (last &&
|
139 | last[key] &&
|
140 | (!variablesMustMatch || equal(last.variables, this.variables))) {
|
141 | return last[key];
|
142 | }
|
143 | };
|
144 | ObservableQuery.prototype.getLastResult = function (variablesMustMatch) {
|
145 | return this.getLast("result", variablesMustMatch);
|
146 | };
|
147 | ObservableQuery.prototype.getLastError = function (variablesMustMatch) {
|
148 | return this.getLast("error", variablesMustMatch);
|
149 | };
|
150 | ObservableQuery.prototype.resetLastResults = function () {
|
151 | delete this.last;
|
152 | this.isTornDown = false;
|
153 | };
|
154 | ObservableQuery.prototype.resetQueryStoreErrors = function () {
|
155 | this.queryManager.resetErrors(this.queryId);
|
156 | };
|
157 | ObservableQuery.prototype.refetch = function (variables) {
|
158 | var _a;
|
159 | var reobserveOptions = {
|
160 | pollInterval: 0,
|
161 | };
|
162 | var fetchPolicy = this.options.fetchPolicy;
|
163 | if (fetchPolicy === 'cache-and-network') {
|
164 | reobserveOptions.fetchPolicy = fetchPolicy;
|
165 | }
|
166 | else if (fetchPolicy === 'no-cache') {
|
167 | reobserveOptions.fetchPolicy = 'no-cache';
|
168 | }
|
169 | else {
|
170 | reobserveOptions.fetchPolicy = 'network-only';
|
171 | }
|
172 | if (__DEV__ && variables && hasOwnProperty.call(variables, "variables")) {
|
173 | var queryDef = getQueryDefinition(this.query);
|
174 | var vars = queryDef.variableDefinitions;
|
175 | if (!vars || !vars.some(function (v) { return v.variable.name.value === "variables"; })) {
|
176 | __DEV__ && invariant.warn("Called refetch(".concat(JSON.stringify(variables), ") for query ").concat(((_a = queryDef.name) === null || _a === void 0 ? void 0 : _a.value) || JSON.stringify(queryDef), ", which does not declare a $variables variable.\nDid you mean to call refetch(variables) instead of refetch({ variables })?"));
|
177 | }
|
178 | }
|
179 | if (variables && !equal(this.options.variables, variables)) {
|
180 | reobserveOptions.variables = this.options.variables = __assign(__assign({}, this.options.variables), variables);
|
181 | }
|
182 | this.queryInfo.resetLastWrite();
|
183 | return this.reobserve(reobserveOptions, NetworkStatus.refetch);
|
184 | };
|
185 | ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
|
186 | var _this = this;
|
187 | var combinedOptions = __assign(__assign({}, (fetchMoreOptions.query ? fetchMoreOptions : __assign(__assign(__assign(__assign({}, this.options), { query: this.query }), fetchMoreOptions), { variables: __assign(__assign({}, this.options.variables), fetchMoreOptions.variables) }))), { fetchPolicy: "no-cache" });
|
188 | var qid = this.queryManager.generateQueryId();
|
189 | var queryInfo = this.queryInfo;
|
190 | var originalNetworkStatus = queryInfo.networkStatus;
|
191 | queryInfo.networkStatus = NetworkStatus.fetchMore;
|
192 | if (combinedOptions.notifyOnNetworkStatusChange) {
|
193 | this.observe();
|
194 | }
|
195 | var updatedQuerySet = new Set();
|
196 | return this.queryManager.fetchQuery(qid, combinedOptions, NetworkStatus.fetchMore).then(function (fetchMoreResult) {
|
197 | _this.queryManager.removeQuery(qid);
|
198 | if (queryInfo.networkStatus === NetworkStatus.fetchMore) {
|
199 | queryInfo.networkStatus = originalNetworkStatus;
|
200 | }
|
201 | _this.queryManager.cache.batch({
|
202 | update: function (cache) {
|
203 | var updateQuery = fetchMoreOptions.updateQuery;
|
204 | if (updateQuery) {
|
205 | cache.updateQuery({
|
206 | query: _this.query,
|
207 | variables: _this.variables,
|
208 | returnPartialData: true,
|
209 | optimistic: false,
|
210 | }, function (previous) { return updateQuery(previous, {
|
211 | fetchMoreResult: fetchMoreResult.data,
|
212 | variables: combinedOptions.variables,
|
213 | }); });
|
214 | }
|
215 | else {
|
216 | cache.writeQuery({
|
217 | query: combinedOptions.query,
|
218 | variables: combinedOptions.variables,
|
219 | data: fetchMoreResult.data,
|
220 | });
|
221 | }
|
222 | },
|
223 | onWatchUpdated: function (watch) {
|
224 | updatedQuerySet.add(watch.query);
|
225 | },
|
226 | });
|
227 | return fetchMoreResult;
|
228 | }).finally(function () {
|
229 | if (!updatedQuerySet.has(_this.query)) {
|
230 | reobserveCacheFirst(_this);
|
231 | }
|
232 | });
|
233 | };
|
234 | ObservableQuery.prototype.subscribeToMore = function (options) {
|
235 | var _this = this;
|
236 | var subscription = this.queryManager
|
237 | .startGraphQLSubscription({
|
238 | query: options.document,
|
239 | variables: options.variables,
|
240 | context: options.context,
|
241 | })
|
242 | .subscribe({
|
243 | next: function (subscriptionData) {
|
244 | var updateQuery = options.updateQuery;
|
245 | if (updateQuery) {
|
246 | _this.updateQuery(function (previous, _a) {
|
247 | var variables = _a.variables;
|
248 | return updateQuery(previous, {
|
249 | subscriptionData: subscriptionData,
|
250 | variables: variables,
|
251 | });
|
252 | });
|
253 | }
|
254 | },
|
255 | error: function (err) {
|
256 | if (options.onError) {
|
257 | options.onError(err);
|
258 | return;
|
259 | }
|
260 | __DEV__ && invariant.error('Unhandled GraphQL subscription error', err);
|
261 | },
|
262 | });
|
263 | this.subscriptions.add(subscription);
|
264 | return function () {
|
265 | if (_this.subscriptions.delete(subscription)) {
|
266 | subscription.unsubscribe();
|
267 | }
|
268 | };
|
269 | };
|
270 | ObservableQuery.prototype.setOptions = function (newOptions) {
|
271 | return this.reobserve(newOptions);
|
272 | };
|
273 | ObservableQuery.prototype.setVariables = function (variables) {
|
274 | if (equal(this.variables, variables)) {
|
275 | return this.observers.size
|
276 | ? this.result()
|
277 | : Promise.resolve();
|
278 | }
|
279 | this.options.variables = variables;
|
280 | if (!this.observers.size) {
|
281 | return Promise.resolve();
|
282 | }
|
283 | return this.reobserve({
|
284 | fetchPolicy: this.options.initialFetchPolicy,
|
285 | variables: variables,
|
286 | }, NetworkStatus.setVariables);
|
287 | };
|
288 | ObservableQuery.prototype.updateQuery = function (mapFn) {
|
289 | var queryManager = this.queryManager;
|
290 | var result = queryManager.cache.diff({
|
291 | query: this.options.query,
|
292 | variables: this.variables,
|
293 | returnPartialData: true,
|
294 | optimistic: false,
|
295 | }).result;
|
296 | var newResult = mapFn(result, {
|
297 | variables: this.variables,
|
298 | });
|
299 | if (newResult) {
|
300 | queryManager.cache.writeQuery({
|
301 | query: this.options.query,
|
302 | data: newResult,
|
303 | variables: this.variables,
|
304 | });
|
305 | queryManager.broadcastQueries();
|
306 | }
|
307 | };
|
308 | ObservableQuery.prototype.startPolling = function (pollInterval) {
|
309 | this.options.pollInterval = pollInterval;
|
310 | this.updatePolling();
|
311 | };
|
312 | ObservableQuery.prototype.stopPolling = function () {
|
313 | this.options.pollInterval = 0;
|
314 | this.updatePolling();
|
315 | };
|
316 | ObservableQuery.prototype.applyNextFetchPolicy = function (reason, options) {
|
317 | if (options.nextFetchPolicy) {
|
318 | var _a = options.fetchPolicy, fetchPolicy = _a === void 0 ? "cache-first" : _a, _b = options.initialFetchPolicy, initialFetchPolicy = _b === void 0 ? fetchPolicy : _b;
|
319 | if (fetchPolicy === "standby") {
|
320 | }
|
321 | else if (typeof options.nextFetchPolicy === "function") {
|
322 | options.fetchPolicy = options.nextFetchPolicy(fetchPolicy, {
|
323 | reason: reason,
|
324 | options: options,
|
325 | observable: this,
|
326 | initialFetchPolicy: initialFetchPolicy,
|
327 | });
|
328 | }
|
329 | else if (reason === "variables-changed") {
|
330 | options.fetchPolicy = initialFetchPolicy;
|
331 | }
|
332 | else {
|
333 | options.fetchPolicy = options.nextFetchPolicy;
|
334 | }
|
335 | }
|
336 | return options.fetchPolicy;
|
337 | };
|
338 | ObservableQuery.prototype.fetch = function (options, newNetworkStatus) {
|
339 | this.queryManager.setObservableQuery(this);
|
340 | return this.queryManager['fetchConcastWithInfo'](this.queryId, options, newNetworkStatus);
|
341 | };
|
342 | ObservableQuery.prototype.updatePolling = function () {
|
343 | var _this = this;
|
344 | if (this.queryManager.ssrMode) {
|
345 | return;
|
346 | }
|
347 | var _a = this, pollingInfo = _a.pollingInfo, pollInterval = _a.options.pollInterval;
|
348 | if (!pollInterval) {
|
349 | if (pollingInfo) {
|
350 | clearTimeout(pollingInfo.timeout);
|
351 | delete this.pollingInfo;
|
352 | }
|
353 | return;
|
354 | }
|
355 | if (pollingInfo &&
|
356 | pollingInfo.interval === pollInterval) {
|
357 | return;
|
358 | }
|
359 | __DEV__ ? invariant(pollInterval, 'Attempted to start a polling query without a polling interval.') : invariant(pollInterval, 13);
|
360 | var info = pollingInfo || (this.pollingInfo = {});
|
361 | info.interval = pollInterval;
|
362 | var maybeFetch = function () {
|
363 | if (_this.pollingInfo) {
|
364 | if (!isNetworkRequestInFlight(_this.queryInfo.networkStatus)) {
|
365 | _this.reobserve({
|
366 | fetchPolicy: _this.options.initialFetchPolicy === 'no-cache' ? 'no-cache' : 'network-only',
|
367 | }, NetworkStatus.poll).then(poll, poll);
|
368 | }
|
369 | else {
|
370 | poll();
|
371 | }
|
372 | }
|
373 | ;
|
374 | };
|
375 | var poll = function () {
|
376 | var info = _this.pollingInfo;
|
377 | if (info) {
|
378 | clearTimeout(info.timeout);
|
379 | info.timeout = setTimeout(maybeFetch, info.interval);
|
380 | }
|
381 | };
|
382 | poll();
|
383 | };
|
384 | ObservableQuery.prototype.updateLastResult = function (newResult, variables) {
|
385 | if (variables === void 0) { variables = this.variables; }
|
386 | this.last = __assign(__assign({}, this.last), { result: this.queryManager.assumeImmutableResults
|
387 | ? newResult
|
388 | : cloneDeep(newResult), variables: variables });
|
389 | if (!isNonEmptyArray(newResult.errors)) {
|
390 | delete this.last.error;
|
391 | }
|
392 | return this.last;
|
393 | };
|
394 | ObservableQuery.prototype.reobserveAsConcast = function (newOptions, newNetworkStatus) {
|
395 | var _this = this;
|
396 | this.isTornDown = false;
|
397 | var useDisposableConcast = newNetworkStatus === NetworkStatus.refetch ||
|
398 | newNetworkStatus === NetworkStatus.fetchMore ||
|
399 | newNetworkStatus === NetworkStatus.poll;
|
400 | var oldVariables = this.options.variables;
|
401 | var oldFetchPolicy = this.options.fetchPolicy;
|
402 | var mergedOptions = compact(this.options, newOptions || {});
|
403 | var options = useDisposableConcast
|
404 | ? mergedOptions
|
405 | : assign(this.options, mergedOptions);
|
406 | if (!useDisposableConcast) {
|
407 | this.updatePolling();
|
408 | if (newOptions &&
|
409 | newOptions.variables &&
|
410 | !equal(newOptions.variables, oldVariables) &&
|
411 | options.fetchPolicy !== "standby" &&
|
412 | options.fetchPolicy === oldFetchPolicy) {
|
413 | this.applyNextFetchPolicy("variables-changed", options);
|
414 | if (newNetworkStatus === void 0) {
|
415 | newNetworkStatus = NetworkStatus.setVariables;
|
416 | }
|
417 | }
|
418 | }
|
419 | var variables = options.variables && __assign({}, options.variables);
|
420 | var _a = this.fetch(options, newNetworkStatus), concast = _a.concast, fromLink = _a.fromLink;
|
421 | var observer = {
|
422 | next: function (result) {
|
423 | _this.reportResult(result, variables);
|
424 | },
|
425 | error: function (error) {
|
426 | _this.reportError(error, variables);
|
427 | },
|
428 | };
|
429 | if (!useDisposableConcast && fromLink) {
|
430 | if (this.concast && this.observer) {
|
431 | this.concast.removeObserver(this.observer);
|
432 | }
|
433 | this.concast = concast;
|
434 | this.observer = observer;
|
435 | }
|
436 | concast.addObserver(observer);
|
437 | return concast;
|
438 | };
|
439 | ObservableQuery.prototype.reobserve = function (newOptions, newNetworkStatus) {
|
440 | return this.reobserveAsConcast(newOptions, newNetworkStatus).promise;
|
441 | };
|
442 | ObservableQuery.prototype.observe = function () {
|
443 | this.reportResult(this.getCurrentResult(false), this.variables);
|
444 | };
|
445 | ObservableQuery.prototype.reportResult = function (result, variables) {
|
446 | var lastError = this.getLastError();
|
447 | if (lastError || this.isDifferentFromLastResult(result, variables)) {
|
448 | if (lastError || !result.partial || this.options.returnPartialData) {
|
449 | this.updateLastResult(result, variables);
|
450 | }
|
451 | iterateObserversSafely(this.observers, 'next', result);
|
452 | }
|
453 | };
|
454 | ObservableQuery.prototype.reportError = function (error, variables) {
|
455 | var errorResult = __assign(__assign({}, this.getLastResult()), { error: error, errors: error.graphQLErrors, networkStatus: NetworkStatus.error, loading: false });
|
456 | this.updateLastResult(errorResult, variables);
|
457 | iterateObserversSafely(this.observers, 'error', this.last.error = error);
|
458 | };
|
459 | ObservableQuery.prototype.hasObservers = function () {
|
460 | return this.observers.size > 0;
|
461 | };
|
462 | ObservableQuery.prototype.tearDownQuery = function () {
|
463 | if (this.isTornDown)
|
464 | return;
|
465 | if (this.concast && this.observer) {
|
466 | this.concast.removeObserver(this.observer);
|
467 | delete this.concast;
|
468 | delete this.observer;
|
469 | }
|
470 | this.stopPolling();
|
471 | this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
|
472 | this.subscriptions.clear();
|
473 | this.queryManager.stopQuery(this.queryId);
|
474 | this.observers.clear();
|
475 | this.isTornDown = true;
|
476 | };
|
477 | return ObservableQuery;
|
478 | }(Observable));
|
479 | export { ObservableQuery };
|
480 | fixObservableSubclass(ObservableQuery);
|
481 | export function reobserveCacheFirst(obsQuery) {
|
482 | var _a = obsQuery.options, fetchPolicy = _a.fetchPolicy, nextFetchPolicy = _a.nextFetchPolicy;
|
483 | if (fetchPolicy === "cache-and-network" ||
|
484 | fetchPolicy === "network-only") {
|
485 | return obsQuery.reobserve({
|
486 | fetchPolicy: "cache-first",
|
487 | nextFetchPolicy: function () {
|
488 | this.nextFetchPolicy = nextFetchPolicy;
|
489 | if (typeof nextFetchPolicy === "function") {
|
490 | return nextFetchPolicy.apply(this, arguments);
|
491 | }
|
492 | return fetchPolicy;
|
493 | },
|
494 | });
|
495 | }
|
496 | return obsQuery.reobserve();
|
497 | }
|
498 | function defaultSubscriptionObserverErrorCallback(error) {
|
499 | __DEV__ && invariant.error('Unhandled error', error.message, error.stack);
|
500 | }
|
501 | export function logMissingFieldErrors(missing) {
|
502 | if (__DEV__ && missing) {
|
503 | __DEV__ && invariant.debug("Missing cache result fields: ".concat(JSON.stringify(missing)), missing);
|
504 | }
|
505 | }
|
506 |
|
\ | No newline at end of file |