1 | var __extends = (this && this.__extends) || (function () {
|
2 | var extendStatics = function (d, b) {
|
3 | extendStatics = Object.setPrototypeOf ||
|
4 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
5 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
6 | return extendStatics(d, b);
|
7 | }
|
8 | return function (d, b) {
|
9 | extendStatics(d, b);
|
10 | function __() { this.constructor = d; }
|
11 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
12 | };
|
13 | })();
|
14 | var __assign = (this && this.__assign) || function () {
|
15 | __assign = Object.assign || function(t) {
|
16 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
17 | s = arguments[i];
|
18 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
19 | t[p] = s[p];
|
20 | }
|
21 | return t;
|
22 | };
|
23 | return __assign.apply(this, arguments);
|
24 | };
|
25 | import { isEqual, tryFunctionOrLogError, cloneDeep } from 'apollo-utilities';
|
26 | import { NetworkStatus, isNetworkRequestInFlight } from './networkStatus';
|
27 | import { Observable } from '../util/Observable';
|
28 | import { ApolloError } from '../errors/ApolloError';
|
29 | import { FetchType } from './types';
|
30 | export var hasError = function (storeValue, policy) {
|
31 | if (policy === void 0) { policy = 'none'; }
|
32 | return storeValue &&
|
33 | ((storeValue.graphQLErrors &&
|
34 | storeValue.graphQLErrors.length > 0 &&
|
35 | policy === 'none') ||
|
36 | storeValue.networkError);
|
37 | };
|
38 | var ObservableQuery = (function (_super) {
|
39 | __extends(ObservableQuery, _super);
|
40 | function ObservableQuery(_a) {
|
41 | var scheduler = _a.scheduler, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b;
|
42 | var _this = _super.call(this, function (observer) {
|
43 | return _this.onSubscribe(observer);
|
44 | }) || this;
|
45 | _this.isCurrentlyPolling = false;
|
46 | _this.isTornDown = false;
|
47 | _this.options = options;
|
48 | _this.variables = options.variables || {};
|
49 | _this.queryId = scheduler.queryManager.generateQueryId();
|
50 | _this.shouldSubscribe = shouldSubscribe;
|
51 | _this.scheduler = scheduler;
|
52 | _this.queryManager = scheduler.queryManager;
|
53 | _this.observers = [];
|
54 | _this.subscriptionHandles = [];
|
55 | return _this;
|
56 | }
|
57 | ObservableQuery.prototype.result = function () {
|
58 | var that = this;
|
59 | return new Promise(function (resolve, reject) {
|
60 | var subscription;
|
61 | var observer = {
|
62 | next: function (result) {
|
63 | resolve(result);
|
64 | if (!that.observers.some(function (obs) { return obs !== observer; })) {
|
65 | that.queryManager.removeQuery(that.queryId);
|
66 | }
|
67 | setTimeout(function () {
|
68 | subscription.unsubscribe();
|
69 | }, 0);
|
70 | },
|
71 | error: function (error) {
|
72 | reject(error);
|
73 | },
|
74 | };
|
75 | subscription = that.subscribe(observer);
|
76 | });
|
77 | };
|
78 | ObservableQuery.prototype.currentResult = function () {
|
79 | if (this.isTornDown) {
|
80 | return {
|
81 | data: this.lastError ? {} : this.lastResult ? this.lastResult.data : {},
|
82 | error: this.lastError,
|
83 | loading: false,
|
84 | networkStatus: NetworkStatus.error,
|
85 | };
|
86 | }
|
87 | var queryStoreValue = this.queryManager.queryStore.get(this.queryId);
|
88 | if (hasError(queryStoreValue, this.options.errorPolicy)) {
|
89 | return {
|
90 | data: {},
|
91 | loading: false,
|
92 | networkStatus: queryStoreValue.networkStatus,
|
93 | error: new ApolloError({
|
94 | graphQLErrors: queryStoreValue.graphQLErrors,
|
95 | networkError: queryStoreValue.networkError,
|
96 | }),
|
97 | };
|
98 | }
|
99 | var _a = this.queryManager.getCurrentQueryResult(this), data = _a.data, partial = _a.partial;
|
100 | var queryLoading = !queryStoreValue ||
|
101 | queryStoreValue.networkStatus === NetworkStatus.loading;
|
102 | var loading = (this.options.fetchPolicy === 'network-only' && queryLoading) ||
|
103 | (partial && this.options.fetchPolicy !== 'cache-only');
|
104 | var networkStatus;
|
105 | if (queryStoreValue) {
|
106 | networkStatus = queryStoreValue.networkStatus;
|
107 | }
|
108 | else {
|
109 | networkStatus = loading ? NetworkStatus.loading : NetworkStatus.ready;
|
110 | }
|
111 | var result = {
|
112 | data: data,
|
113 | loading: isNetworkRequestInFlight(networkStatus),
|
114 | networkStatus: networkStatus,
|
115 | };
|
116 | if (queryStoreValue &&
|
117 | queryStoreValue.graphQLErrors &&
|
118 | this.options.errorPolicy === 'all') {
|
119 | result.errors = queryStoreValue.graphQLErrors;
|
120 | }
|
121 | if (!partial) {
|
122 | this.lastResult = __assign({}, result, { stale: false });
|
123 | this.lastResultSnapshot = cloneDeep(this.lastResult);
|
124 | }
|
125 | return __assign({}, result, { partial: partial });
|
126 | };
|
127 | ObservableQuery.prototype.isDifferentFromLastResult = function (newResult) {
|
128 | var snapshot = this.lastResultSnapshot;
|
129 | return !(snapshot && newResult &&
|
130 | snapshot.networkStatus === newResult.networkStatus &&
|
131 | snapshot.stale === newResult.stale &&
|
132 | isEqual(snapshot.data, newResult.data));
|
133 | };
|
134 | ObservableQuery.prototype.getLastResult = function () {
|
135 | return this.lastResult;
|
136 | };
|
137 | ObservableQuery.prototype.getLastError = function () {
|
138 | return this.lastError;
|
139 | };
|
140 | ObservableQuery.prototype.resetLastResults = function () {
|
141 | delete this.lastResult;
|
142 | delete this.lastResultSnapshot;
|
143 | delete this.lastError;
|
144 | this.isTornDown = false;
|
145 | };
|
146 | ObservableQuery.prototype.refetch = function (variables) {
|
147 | var fetchPolicy = this.options.fetchPolicy;
|
148 | if (fetchPolicy === 'cache-only') {
|
149 | return Promise.reject(new Error('cache-only fetchPolicy option should not be used together with query refetch.'));
|
150 | }
|
151 | if (!isEqual(this.variables, variables)) {
|
152 | this.variables = Object.assign({}, this.variables, variables);
|
153 | }
|
154 | if (!isEqual(this.options.variables, this.variables)) {
|
155 | this.options.variables = Object.assign({}, this.options.variables, this.variables);
|
156 | }
|
157 | var isNetworkFetchPolicy = fetchPolicy === 'network-only' || fetchPolicy === 'no-cache';
|
158 | var combinedOptions = __assign({}, this.options, { fetchPolicy: isNetworkFetchPolicy ? fetchPolicy : 'network-only' });
|
159 | return this.queryManager
|
160 | .fetchQuery(this.queryId, combinedOptions, FetchType.refetch)
|
161 | .then(function (result) { return result; });
|
162 | };
|
163 | ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
|
164 | var _this = this;
|
165 | if (!fetchMoreOptions.updateQuery) {
|
166 | throw new Error('updateQuery option is required. This function defines how to update the query data with the new results.');
|
167 | }
|
168 | var combinedOptions;
|
169 | return Promise.resolve()
|
170 | .then(function () {
|
171 | var qid = _this.queryManager.generateQueryId();
|
172 | if (fetchMoreOptions.query) {
|
173 | combinedOptions = fetchMoreOptions;
|
174 | }
|
175 | else {
|
176 | combinedOptions = __assign({}, _this.options, fetchMoreOptions, { variables: Object.assign({}, _this.variables, fetchMoreOptions.variables) });
|
177 | }
|
178 | combinedOptions.fetchPolicy = 'network-only';
|
179 | return _this.queryManager.fetchQuery(qid, combinedOptions, FetchType.normal, _this.queryId);
|
180 | })
|
181 | .then(function (fetchMoreResult) {
|
182 | _this.updateQuery(function (previousResult) {
|
183 | return fetchMoreOptions.updateQuery(previousResult, {
|
184 | fetchMoreResult: fetchMoreResult.data,
|
185 | variables: combinedOptions.variables,
|
186 | });
|
187 | });
|
188 | return fetchMoreResult;
|
189 | });
|
190 | };
|
191 | ObservableQuery.prototype.subscribeToMore = function (options) {
|
192 | var _this = this;
|
193 | var subscription = this.queryManager
|
194 | .startGraphQLSubscription({
|
195 | query: options.document,
|
196 | variables: options.variables,
|
197 | })
|
198 | .subscribe({
|
199 | next: function (subscriptionData) {
|
200 | if (options.updateQuery) {
|
201 | _this.updateQuery(function (previous, _a) {
|
202 | var variables = _a.variables;
|
203 | return options.updateQuery(previous, {
|
204 | subscriptionData: subscriptionData,
|
205 | variables: variables,
|
206 | });
|
207 | });
|
208 | }
|
209 | },
|
210 | error: function (err) {
|
211 | if (options.onError) {
|
212 | options.onError(err);
|
213 | return;
|
214 | }
|
215 | console.error('Unhandled GraphQL subscription error', err);
|
216 | },
|
217 | });
|
218 | this.subscriptionHandles.push(subscription);
|
219 | return function () {
|
220 | var i = _this.subscriptionHandles.indexOf(subscription);
|
221 | if (i >= 0) {
|
222 | _this.subscriptionHandles.splice(i, 1);
|
223 | subscription.unsubscribe();
|
224 | }
|
225 | };
|
226 | };
|
227 | ObservableQuery.prototype.setOptions = function (opts) {
|
228 | var oldOptions = this.options;
|
229 | this.options = Object.assign({}, this.options, opts);
|
230 | if (opts.pollInterval) {
|
231 | this.startPolling(opts.pollInterval);
|
232 | }
|
233 | else if (opts.pollInterval === 0) {
|
234 | this.stopPolling();
|
235 | }
|
236 | var tryFetch = (oldOptions.fetchPolicy !== 'network-only' &&
|
237 | opts.fetchPolicy === 'network-only') ||
|
238 | (oldOptions.fetchPolicy === 'cache-only' &&
|
239 | opts.fetchPolicy !== 'cache-only') ||
|
240 | (oldOptions.fetchPolicy === 'standby' &&
|
241 | opts.fetchPolicy !== 'standby') ||
|
242 | false;
|
243 | return this.setVariables(this.options.variables, tryFetch, opts.fetchResults);
|
244 | };
|
245 | ObservableQuery.prototype.setVariables = function (variables, tryFetch, fetchResults) {
|
246 | if (tryFetch === void 0) { tryFetch = false; }
|
247 | if (fetchResults === void 0) { fetchResults = true; }
|
248 | this.isTornDown = false;
|
249 | var newVariables = variables ? variables : this.variables;
|
250 | if (isEqual(newVariables, this.variables) && !tryFetch) {
|
251 | if (this.observers.length === 0 || !fetchResults) {
|
252 | return new Promise(function (resolve) { return resolve(); });
|
253 | }
|
254 | return this.result();
|
255 | }
|
256 | else {
|
257 | this.variables = newVariables;
|
258 | this.options.variables = newVariables;
|
259 | if (this.observers.length === 0) {
|
260 | return new Promise(function (resolve) { return resolve(); });
|
261 | }
|
262 | return this.queryManager
|
263 | .fetchQuery(this.queryId, __assign({}, this.options, { variables: this.variables }))
|
264 | .then(function (result) { return result; });
|
265 | }
|
266 | };
|
267 | ObservableQuery.prototype.updateQuery = function (mapFn) {
|
268 | var _a = this.queryManager.getQueryWithPreviousResult(this.queryId), previousResult = _a.previousResult, variables = _a.variables, document = _a.document;
|
269 | var newResult = tryFunctionOrLogError(function () {
|
270 | return mapFn(previousResult, { variables: variables });
|
271 | });
|
272 | if (newResult) {
|
273 | this.queryManager.dataStore.markUpdateQueryResult(document, variables, newResult);
|
274 | this.queryManager.broadcastQueries();
|
275 | }
|
276 | };
|
277 | ObservableQuery.prototype.stopPolling = function () {
|
278 | if (this.isCurrentlyPolling) {
|
279 | this.scheduler.stopPollingQuery(this.queryId);
|
280 | this.options.pollInterval = undefined;
|
281 | this.isCurrentlyPolling = false;
|
282 | }
|
283 | };
|
284 | ObservableQuery.prototype.startPolling = function (pollInterval) {
|
285 | if (this.options.fetchPolicy === 'cache-first' ||
|
286 | this.options.fetchPolicy === 'cache-only') {
|
287 | throw new Error('Queries that specify the cache-first and cache-only fetchPolicies cannot also be polling queries.');
|
288 | }
|
289 | if (this.isCurrentlyPolling) {
|
290 | this.scheduler.stopPollingQuery(this.queryId);
|
291 | this.isCurrentlyPolling = false;
|
292 | }
|
293 | this.options.pollInterval = pollInterval;
|
294 | this.isCurrentlyPolling = true;
|
295 | this.scheduler.startPollingQuery(this.options, this.queryId);
|
296 | };
|
297 | ObservableQuery.prototype.onSubscribe = function (observer) {
|
298 | var _this = this;
|
299 | if (observer._subscription &&
|
300 | observer._subscription._observer &&
|
301 | !observer._subscription._observer.error) {
|
302 | observer._subscription._observer.error = function (error) {
|
303 | console.error('Unhandled error', error.message, error.stack);
|
304 | };
|
305 | }
|
306 | this.observers.push(observer);
|
307 | if (observer.next && this.lastResult)
|
308 | observer.next(this.lastResult);
|
309 | if (observer.error && this.lastError)
|
310 | observer.error(this.lastError);
|
311 | if (this.observers.length === 1)
|
312 | this.setUpQuery();
|
313 | return function () {
|
314 | _this.observers = _this.observers.filter(function (obs) { return obs !== observer; });
|
315 | if (_this.observers.length === 0) {
|
316 | _this.tearDownQuery();
|
317 | }
|
318 | };
|
319 | };
|
320 | ObservableQuery.prototype.setUpQuery = function () {
|
321 | var _this = this;
|
322 | if (this.shouldSubscribe) {
|
323 | this.queryManager.addObservableQuery(this.queryId, this);
|
324 | }
|
325 | if (!!this.options.pollInterval) {
|
326 | if (this.options.fetchPolicy === 'cache-first' ||
|
327 | this.options.fetchPolicy === 'cache-only') {
|
328 | throw new Error('Queries that specify the cache-first and cache-only fetchPolicies cannot also be polling queries.');
|
329 | }
|
330 | this.isCurrentlyPolling = true;
|
331 | this.scheduler.startPollingQuery(this.options, this.queryId);
|
332 | }
|
333 | var observer = {
|
334 | next: function (result) {
|
335 | _this.lastResult = result;
|
336 | _this.lastResultSnapshot = cloneDeep(result);
|
337 | _this.observers.forEach(function (obs) { return obs.next && obs.next(result); });
|
338 | },
|
339 | error: function (error) {
|
340 | _this.lastError = error;
|
341 | _this.observers.forEach(function (obs) { return obs.error && obs.error(error); });
|
342 | },
|
343 | };
|
344 | this.queryManager.startQuery(this.queryId, this.options, this.queryManager.queryListenerForObserver(this.queryId, this.options, observer));
|
345 | };
|
346 | ObservableQuery.prototype.tearDownQuery = function () {
|
347 | this.isTornDown = true;
|
348 | if (this.isCurrentlyPolling) {
|
349 | this.scheduler.stopPollingQuery(this.queryId);
|
350 | this.isCurrentlyPolling = false;
|
351 | }
|
352 | this.subscriptionHandles.forEach(function (sub) { return sub.unsubscribe(); });
|
353 | this.subscriptionHandles = [];
|
354 | this.queryManager.removeObservableQuery(this.queryId);
|
355 | this.queryManager.stopQuery(this.queryId);
|
356 | this.observers = [];
|
357 | };
|
358 | return ObservableQuery;
|
359 | }(Observable));
|
360 | export { ObservableQuery };
|
361 |
|
\ | No newline at end of file |