UNPKG

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