1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var tslib_1 = require("tslib");
|
4 | var apollo_utilities_1 = require("apollo-utilities");
|
5 | var networkStatus_1 = require("./networkStatus");
|
6 | var Observable_1 = require("../util/Observable");
|
7 | var ApolloError_1 = require("../errors/ApolloError");
|
8 | var types_1 = require("./types");
|
9 | var ts_invariant_1 = require("ts-invariant");
|
10 | var arrays_1 = require("../util/arrays");
|
11 | exports.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 | };
|
16 | var 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));
|
354 | exports.ObservableQuery = ObservableQuery;
|
355 | function defaultSubscriptionObserverErrorCallback(error) {
|
356 | ts_invariant_1.invariant.error('Unhandled error', error.message, error.stack);
|
357 | }
|
358 | function 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 | }
|
363 | function 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 |
|
\ | No newline at end of file |