apollo-client
Version:
A simple yet functional GraphQL client.
367 lines • 17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var apollo_utilities_1 = require("apollo-utilities");
var networkStatus_1 = require("./networkStatus");
var Observable_1 = require("../util/Observable");
var ApolloError_1 = require("../errors/ApolloError");
var types_1 = require("./types");
var ts_invariant_1 = require("ts-invariant");
var arrays_1 = require("../util/arrays");
exports.hasError = function (storeValue, policy) {
if (policy === void 0) { policy = 'none'; }
return storeValue && (storeValue.networkError ||
(policy === 'none' && arrays_1.isNonEmptyArray(storeValue.graphQLErrors)));
};
var ObservableQuery = (function (_super) {
tslib_1.__extends(ObservableQuery, _super);
function ObservableQuery(_a) {
var queryManager = _a.queryManager, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b;
var _this = _super.call(this, function (observer) {
return _this.onSubscribe(observer);
}) || this;
_this.observers = new Set();
_this.subscriptions = new Set();
_this.isTornDown = false;
_this.options = options;
_this.variables = options.variables || {};
_this.queryId = queryManager.generateQueryId();
_this.shouldSubscribe = shouldSubscribe;
var opDef = apollo_utilities_1.getOperationDefinition(options.query);
_this.queryName = opDef && opDef.name && opDef.name.value;
_this.queryManager = queryManager;
return _this;
}
ObservableQuery.prototype.result = function () {
var _this = this;
return new Promise(function (resolve, reject) {
var observer = {
next: function (result) {
resolve(result);
_this.observers.delete(observer);
if (!_this.observers.size) {
_this.queryManager.removeQuery(_this.queryId);
}
setTimeout(function () {
subscription.unsubscribe();
}, 0);
},
error: reject,
};
var subscription = _this.subscribe(observer);
});
};
ObservableQuery.prototype.currentResult = function () {
var result = this.getCurrentResult();
if (result.data === undefined) {
result.data = {};
}
return result;
};
ObservableQuery.prototype.getCurrentResult = function () {
if (this.isTornDown) {
var lastResult = this.lastResult;
return {
data: !this.lastError && lastResult && lastResult.data || void 0,
error: this.lastError,
loading: false,
networkStatus: networkStatus_1.NetworkStatus.error,
};
}
var _a = this.queryManager.getCurrentQueryResult(this), data = _a.data, partial = _a.partial;
var queryStoreValue = this.queryManager.queryStore.get(this.queryId);
var result;
var fetchPolicy = this.options.fetchPolicy;
var isNetworkFetchPolicy = fetchPolicy === 'network-only' ||
fetchPolicy === 'no-cache';
if (queryStoreValue) {
var networkStatus = queryStoreValue.networkStatus;
if (exports.hasError(queryStoreValue, this.options.errorPolicy)) {
return {
data: void 0,
loading: false,
networkStatus: networkStatus,
error: new ApolloError_1.ApolloError({
graphQLErrors: queryStoreValue.graphQLErrors,
networkError: queryStoreValue.networkError,
}),
};
}
if (queryStoreValue.variables) {
this.options.variables = tslib_1.__assign(tslib_1.__assign({}, this.options.variables), queryStoreValue.variables);
this.variables = this.options.variables;
}
result = {
data: data,
loading: networkStatus_1.isNetworkRequestInFlight(networkStatus),
networkStatus: networkStatus,
};
if (queryStoreValue.graphQLErrors && this.options.errorPolicy === 'all') {
result.errors = queryStoreValue.graphQLErrors;
}
}
else {
var loading = isNetworkFetchPolicy ||
(partial && fetchPolicy !== 'cache-only');
result = {
data: data,
loading: loading,
networkStatus: loading ? networkStatus_1.NetworkStatus.loading : networkStatus_1.NetworkStatus.ready,
};
}
if (!partial) {
this.updateLastResult(tslib_1.__assign(tslib_1.__assign({}, result), { stale: false }));
}
return tslib_1.__assign(tslib_1.__assign({}, result), { partial: partial });
};
ObservableQuery.prototype.isDifferentFromLastResult = function (newResult) {
var snapshot = this.lastResultSnapshot;
return !(snapshot &&
newResult &&
snapshot.networkStatus === newResult.networkStatus &&
snapshot.stale === newResult.stale &&
apollo_utilities_1.isEqual(snapshot.data, newResult.data));
};
ObservableQuery.prototype.getLastResult = function () {
return this.lastResult;
};
ObservableQuery.prototype.getLastError = function () {
return this.lastError;
};
ObservableQuery.prototype.resetLastResults = function () {
delete this.lastResult;
delete this.lastResultSnapshot;
delete this.lastError;
this.isTornDown = false;
};
ObservableQuery.prototype.resetQueryStoreErrors = function () {
var queryStore = this.queryManager.queryStore.get(this.queryId);
if (queryStore) {
queryStore.networkError = null;
queryStore.graphQLErrors = [];
}
};
ObservableQuery.prototype.refetch = function (variables) {
var fetchPolicy = this.options.fetchPolicy;
if (fetchPolicy === 'cache-only') {
return Promise.reject(new ts_invariant_1.InvariantError('cache-only fetchPolicy option should not be used together with query refetch.'));
}
if (fetchPolicy !== 'no-cache' &&
fetchPolicy !== 'cache-and-network') {
fetchPolicy = 'network-only';
}
if (!apollo_utilities_1.isEqual(this.variables, variables)) {
this.variables = tslib_1.__assign(tslib_1.__assign({}, this.variables), variables);
}
if (!apollo_utilities_1.isEqual(this.options.variables, this.variables)) {
this.options.variables = tslib_1.__assign(tslib_1.__assign({}, this.options.variables), this.variables);
}
return this.queryManager.fetchQuery(this.queryId, tslib_1.__assign(tslib_1.__assign({}, this.options), { fetchPolicy: fetchPolicy }), types_1.FetchType.refetch);
};
ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
var _this = this;
ts_invariant_1.invariant(fetchMoreOptions.updateQuery, 'updateQuery option is required. This function defines how to update the query data with the new results.');
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' });
var qid = this.queryManager.generateQueryId();
return this.queryManager
.fetchQuery(qid, combinedOptions, types_1.FetchType.normal, this.queryId)
.then(function (fetchMoreResult) {
_this.updateQuery(function (previousResult) {
return fetchMoreOptions.updateQuery(previousResult, {
fetchMoreResult: fetchMoreResult.data,
variables: combinedOptions.variables,
});
});
_this.queryManager.stopQuery(qid);
return fetchMoreResult;
}, function (error) {
_this.queryManager.stopQuery(qid);
throw error;
});
};
ObservableQuery.prototype.subscribeToMore = function (options) {
var _this = this;
var subscription = this.queryManager
.startGraphQLSubscription({
query: options.document,
variables: options.variables,
})
.subscribe({
next: function (subscriptionData) {
var updateQuery = options.updateQuery;
if (updateQuery) {
_this.updateQuery(function (previous, _a) {
var variables = _a.variables;
return updateQuery(previous, {
subscriptionData: subscriptionData,
variables: variables,
});
});
}
},
error: function (err) {
if (options.onError) {
options.onError(err);
return;
}
ts_invariant_1.invariant.error('Unhandled GraphQL subscription error', err);
},
});
this.subscriptions.add(subscription);
return function () {
if (_this.subscriptions.delete(subscription)) {
subscription.unsubscribe();
}
};
};
ObservableQuery.prototype.setOptions = function (opts) {
var oldFetchPolicy = this.options.fetchPolicy;
this.options = tslib_1.__assign(tslib_1.__assign({}, this.options), opts);
if (opts.pollInterval) {
this.startPolling(opts.pollInterval);
}
else if (opts.pollInterval === 0) {
this.stopPolling();
}
var fetchPolicy = opts.fetchPolicy;
return this.setVariables(this.options.variables, oldFetchPolicy !== fetchPolicy && (oldFetchPolicy === 'cache-only' ||
oldFetchPolicy === 'standby' ||
fetchPolicy === 'network-only'), opts.fetchResults);
};
ObservableQuery.prototype.setVariables = function (variables, tryFetch, fetchResults) {
if (tryFetch === void 0) { tryFetch = false; }
if (fetchResults === void 0) { fetchResults = true; }
this.isTornDown = false;
variables = variables || this.variables;
if (!tryFetch && apollo_utilities_1.isEqual(variables, this.variables)) {
return this.observers.size && fetchResults
? this.result()
: Promise.resolve();
}
this.variables = this.options.variables = variables;
if (!this.observers.size) {
return Promise.resolve();
}
return this.queryManager.fetchQuery(this.queryId, this.options);
};
ObservableQuery.prototype.updateQuery = function (mapFn) {
var queryManager = this.queryManager;
var _a = queryManager.getQueryWithPreviousResult(this.queryId), previousResult = _a.previousResult, variables = _a.variables, document = _a.document;
var newResult = apollo_utilities_1.tryFunctionOrLogError(function () {
return mapFn(previousResult, { variables: variables });
});
if (newResult) {
queryManager.dataStore.markUpdateQueryResult(document, variables, newResult);
queryManager.broadcastQueries();
}
};
ObservableQuery.prototype.stopPolling = function () {
this.queryManager.stopPollingQuery(this.queryId);
this.options.pollInterval = undefined;
};
ObservableQuery.prototype.startPolling = function (pollInterval) {
assertNotCacheFirstOrOnly(this);
this.options.pollInterval = pollInterval;
this.queryManager.startPollingQuery(this.options, this.queryId);
};
ObservableQuery.prototype.updateLastResult = function (newResult) {
var previousResult = this.lastResult;
this.lastResult = newResult;
this.lastResultSnapshot = this.queryManager.assumeImmutableResults
? newResult
: apollo_utilities_1.cloneDeep(newResult);
return previousResult;
};
ObservableQuery.prototype.onSubscribe = function (observer) {
var _this = this;
try {
var subObserver = observer._subscription._observer;
if (subObserver && !subObserver.error) {
subObserver.error = defaultSubscriptionObserverErrorCallback;
}
}
catch (_a) { }
var first = !this.observers.size;
this.observers.add(observer);
if (observer.next && this.lastResult)
observer.next(this.lastResult);
if (observer.error && this.lastError)
observer.error(this.lastError);
if (first) {
this.setUpQuery();
}
return function () {
if (_this.observers.delete(observer) && !_this.observers.size) {
_this.tearDownQuery();
}
};
};
ObservableQuery.prototype.setUpQuery = function () {
var _this = this;
var _a = this, queryManager = _a.queryManager, queryId = _a.queryId;
if (this.shouldSubscribe) {
queryManager.addObservableQuery(queryId, this);
}
if (this.options.pollInterval) {
assertNotCacheFirstOrOnly(this);
queryManager.startPollingQuery(this.options, queryId);
}
var onError = function (error) {
_this.updateLastResult(tslib_1.__assign(tslib_1.__assign({}, _this.lastResult), { errors: error.graphQLErrors, networkStatus: networkStatus_1.NetworkStatus.error, loading: false }));
iterateObserversSafely(_this.observers, 'error', _this.lastError = error);
};
queryManager.observeQuery(queryId, this.options, {
next: function (result) {
if (_this.lastError || _this.isDifferentFromLastResult(result)) {
var previousResult_1 = _this.updateLastResult(result);
var _a = _this.options, query_1 = _a.query, variables = _a.variables, fetchPolicy_1 = _a.fetchPolicy;
if (queryManager.transform(query_1).hasClientExports) {
queryManager.getLocalState().addExportedVariables(query_1, variables).then(function (variables) {
var previousVariables = _this.variables;
_this.variables = _this.options.variables = variables;
if (!result.loading &&
previousResult_1 &&
fetchPolicy_1 !== 'cache-only' &&
queryManager.transform(query_1).serverQuery &&
!apollo_utilities_1.isEqual(previousVariables, variables)) {
_this.refetch();
}
else {
iterateObserversSafely(_this.observers, 'next', result);
}
});
}
else {
iterateObserversSafely(_this.observers, 'next', result);
}
}
},
error: onError,
}).catch(onError);
};
ObservableQuery.prototype.tearDownQuery = function () {
var queryManager = this.queryManager;
this.isTornDown = true;
queryManager.stopPollingQuery(this.queryId);
this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
this.subscriptions.clear();
queryManager.removeObservableQuery(this.queryId);
queryManager.stopQuery(this.queryId);
this.observers.clear();
};
return ObservableQuery;
}(Observable_1.Observable));
exports.ObservableQuery = ObservableQuery;
function defaultSubscriptionObserverErrorCallback(error) {
ts_invariant_1.invariant.error('Unhandled error', error.message, error.stack);
}
function iterateObserversSafely(observers, method, argument) {
var observersWithMethod = [];
observers.forEach(function (obs) { return obs[method] && observersWithMethod.push(obs); });
observersWithMethod.forEach(function (obs) { return obs[method](argument); });
}
function assertNotCacheFirstOrOnly(obsQuery) {
var fetchPolicy = obsQuery.options.fetchPolicy;
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.');
}
//# sourceMappingURL=ObservableQuery.js.map