UNPKG

21.9 kBJavaScriptView Raw
1import { __assign, __extends } from "tslib";
2import { invariant } from "../utilities/globals/index.js";
3import { equal } from '@wry/equality';
4import { NetworkStatus, isNetworkRequestInFlight } from "./networkStatus.js";
5import { cloneDeep, compact, getOperationDefinition, Observable, iterateObserversSafely, isNonEmptyArray, fixObservableSubclass, getQueryDefinition, } from "../utilities/index.js";
6var assign = Object.assign, hasOwnProperty = Object.hasOwnProperty;
7var 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));
479export { ObservableQuery };
480fixObservableSubclass(ObservableQuery);
481export 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}
498function defaultSubscriptionObserverErrorCallback(error) {
499 __DEV__ && invariant.error('Unhandled error', error.message, error.stack);
500}
501export function logMissingFieldErrors(missing) {
502 if (__DEV__ && missing) {
503 __DEV__ && invariant.debug("Missing cache result fields: ".concat(JSON.stringify(missing)), missing);
504 }
505}
506//# sourceMappingURL=ObservableQuery.js.map
\No newline at end of file