apollo-client-cors-hack
Version:
A simple yet functional GraphQL client.
715 lines • 33.1 kB
JavaScript
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
import { Deduplicator, } from '../transport/Deduplicator';
import { isEqual } from '../util/isEqual';
import { assign } from '../util/assign';
import { FetchType, } from './types';
import { NetworkStatus, isNetworkRequestInFlight, } from '../queries/networkStatus';
import { getDataWithOptimisticResults, } from '../store';
import { getQueryDefinition, getOperationDefinition, getOperationName, getDefaultValues, getMutationDefinition, } from '../queries/getFromAST';
import { addTypenameToDocument, } from '../queries/queryTransform';
import { createStoreReducer, } from '../data/resultReducers';
import { HeuristicFragmentMatcher, } from '../data/fragmentMatcher';
import { isProduction, } from '../util/environment';
import maybeDeepFreeze from '../util/maybeDeepFreeze';
import { print } from 'graphql/language/printer';
import { readQueryFromStore, } from '../data/readFromStore';
import { diffQueryAgainstStore, } from '../data/readFromStore';
import { QueryScheduler, } from '../scheduler/scheduler';
import { Observable, } from '../util/Observable';
import { isApolloError, ApolloError, } from '../errors/ApolloError';
import { ObservableQuery } from './ObservableQuery';
var QueryManager = (function () {
function QueryManager(_a) {
var networkInterface = _a.networkInterface, store = _a.store, reduxRootSelector = _a.reduxRootSelector, _b = _a.reducerConfig, reducerConfig = _b === void 0 ? { mutationBehaviorReducers: {} } : _b, fragmentMatcher = _a.fragmentMatcher, _c = _a.addTypename, addTypename = _c === void 0 ? true : _c, _d = _a.queryDeduplication, queryDeduplication = _d === void 0 ? false : _d, _e = _a.ssrMode, ssrMode = _e === void 0 ? false : _e;
var _this = this;
this.idCounter = 1;
this.networkInterface = networkInterface;
this.deduplicator = new Deduplicator(networkInterface);
this.store = store;
this.reduxRootSelector = reduxRootSelector;
this.reducerConfig = reducerConfig;
this.pollingTimers = {};
this.queryListeners = {};
this.queryDocuments = {};
this.addTypename = addTypename;
this.queryDeduplication = queryDeduplication;
this.ssrMode = ssrMode;
if (typeof fragmentMatcher === 'undefined') {
this.fragmentMatcher = new HeuristicFragmentMatcher();
}
else {
this.fragmentMatcher = fragmentMatcher;
}
this.scheduler = new QueryScheduler({
queryManager: this,
});
this.fetchQueryPromises = {};
this.observableQueries = {};
this.queryIdsByName = {};
if (this.store['subscribe']) {
var currentStoreData_1;
this.store['subscribe'](function () {
var previousStoreData = currentStoreData_1 || {};
var previousStoreHasData = Object.keys(previousStoreData).length;
currentStoreData_1 = _this.getApolloState();
if (isEqual(previousStoreData, currentStoreData_1) && previousStoreHasData) {
return;
}
_this.broadcastQueries();
});
}
}
QueryManager.prototype.broadcastNewStore = function (store) {
this.broadcastQueries();
};
QueryManager.prototype.mutate = function (_a) {
var _this = this;
var mutation = _a.mutation, variables = _a.variables, optimisticResponse = _a.optimisticResponse, updateQueriesByName = _a.updateQueries, _b = _a.refetchQueries, refetchQueries = _b === void 0 ? [] : _b, updateWithProxyFn = _a.update;
var mutationId = this.generateQueryId();
if (this.addTypename) {
mutation = addTypenameToDocument(mutation);
}
variables = assign({}, getDefaultValues(getMutationDefinition(mutation)), variables);
var mutationString = print(mutation);
var request = {
query: mutation,
variables: variables,
operationName: getOperationName(mutation),
};
this.queryDocuments[mutationId] = mutation;
var updateQueries = {};
if (updateQueriesByName) {
Object.keys(updateQueriesByName).forEach(function (queryName) { return (_this.queryIdsByName[queryName] || []).forEach(function (queryId) {
updateQueries[queryId] = updateQueriesByName[queryName];
}); });
}
this.store.dispatch({
type: 'APOLLO_MUTATION_INIT',
mutationString: mutationString,
mutation: mutation,
variables: variables || {},
operationName: getOperationName(mutation),
mutationId: mutationId,
optimisticResponse: optimisticResponse,
extraReducers: this.getExtraReducers(),
updateQueries: updateQueries,
update: updateWithProxyFn,
});
return new Promise(function (resolve, reject) {
_this.networkInterface.query(request)
.then(function (result) {
if (result.errors) {
var error = new ApolloError({
graphQLErrors: result.errors,
});
_this.store.dispatch({
type: 'APOLLO_MUTATION_ERROR',
error: error,
mutationId: mutationId,
});
delete _this.queryDocuments[mutationId];
reject(error);
return;
}
_this.store.dispatch({
type: 'APOLLO_MUTATION_RESULT',
result: result,
mutationId: mutationId,
document: mutation,
operationName: getOperationName(mutation),
variables: variables || {},
extraReducers: _this.getExtraReducers(),
updateQueries: updateQueries,
update: updateWithProxyFn,
});
var reducerError = _this.getApolloState().reducerError;
if (reducerError && reducerError.mutationId === mutationId) {
reject(reducerError.error);
return;
}
if (typeof refetchQueries[0] === 'string') {
refetchQueries.forEach(function (name) { _this.refetchQueryByName(name); });
}
else {
refetchQueries.forEach(function (pureQuery) {
_this.query({
query: pureQuery.query,
variables: pureQuery.variables,
fetchPolicy: 'network-only',
});
});
}
delete _this.queryDocuments[mutationId];
resolve(result);
})
.catch(function (err) {
_this.store.dispatch({
type: 'APOLLO_MUTATION_ERROR',
error: err,
mutationId: mutationId,
});
delete _this.queryDocuments[mutationId];
reject(new ApolloError({
networkError: err,
}));
});
});
};
QueryManager.prototype.fetchQuery = function (queryId, options, fetchType, fetchMoreForQueryId) {
var _this = this;
var _a = options.variables, variables = _a === void 0 ? {} : _a, _b = options.metadata, metadata = _b === void 0 ? null : _b, _c = options.fetchPolicy, fetchPolicy = _c === void 0 ? 'cache-first' : _c;
var queryDoc = this.transformQueryDocument(options).queryDoc;
var queryString = print(queryDoc);
var storeResult;
var needToFetch = fetchPolicy === 'network-only';
if ((fetchType !== FetchType.refetch && fetchPolicy !== 'network-only')) {
var _d = diffQueryAgainstStore({
query: queryDoc,
store: this.reduxRootSelector(this.store.getState()).data,
variables: variables,
returnPartialData: true,
fragmentMatcherFunction: this.fragmentMatcher.match,
config: this.reducerConfig,
}), isMissing = _d.isMissing, result = _d.result;
needToFetch = isMissing || fetchPolicy === 'cache-and-network';
storeResult = result;
}
var shouldFetch = needToFetch && fetchPolicy !== 'cache-only' && fetchPolicy !== 'standby';
var requestId = this.generateRequestId();
this.queryDocuments[queryId] = queryDoc;
this.store.dispatch({
type: 'APOLLO_QUERY_INIT',
queryString: queryString,
document: queryDoc,
variables: variables,
fetchPolicy: fetchPolicy,
queryId: queryId,
requestId: requestId,
storePreviousVariables: shouldFetch,
isPoll: fetchType === FetchType.poll,
isRefetch: fetchType === FetchType.refetch,
fetchMoreForQueryId: fetchMoreForQueryId,
metadata: metadata,
});
var shouldDispatchClientResult = !shouldFetch || fetchPolicy === 'cache-and-network';
if (shouldDispatchClientResult) {
this.store.dispatch({
type: 'APOLLO_QUERY_RESULT_CLIENT',
result: { data: storeResult },
variables: variables,
document: queryDoc,
complete: !shouldFetch,
queryId: queryId,
requestId: requestId,
});
}
if (shouldFetch) {
var networkResult = this.fetchRequest({
requestId: requestId,
queryId: queryId,
document: queryDoc,
options: options,
fetchMoreForQueryId: fetchMoreForQueryId,
}).catch(function (error) {
if (isApolloError(error)) {
throw error;
}
else {
_this.store.dispatch({
type: 'APOLLO_QUERY_ERROR',
error: error,
queryId: queryId,
requestId: requestId,
fetchMoreForQueryId: fetchMoreForQueryId,
});
_this.removeFetchQueryPromise(requestId);
throw new ApolloError({
networkError: error,
});
}
});
if (fetchPolicy !== 'cache-and-network') {
return networkResult;
}
}
return Promise.resolve({ data: storeResult });
};
QueryManager.prototype.queryListenerForObserver = function (queryId, options, observer) {
var _this = this;
var lastResult;
var previouslyHadError = false;
return function (queryStoreValue) {
if (!queryStoreValue) {
return;
}
queryStoreValue = _this.getApolloState().queries[queryId];
var storedQuery = _this.observableQueries[queryId];
var fetchPolicy = storedQuery ? storedQuery.observableQuery.options.fetchPolicy : options.fetchPolicy;
if (fetchPolicy === 'standby') {
return;
}
var shouldNotifyIfLoading = queryStoreValue.previousVariables ||
fetchPolicy === 'cache-only' || fetchPolicy === 'cache-and-network';
var networkStatusChanged = lastResult && queryStoreValue.networkStatus !== lastResult.networkStatus;
if (!isNetworkRequestInFlight(queryStoreValue.networkStatus) ||
(networkStatusChanged && options.notifyOnNetworkStatusChange) ||
shouldNotifyIfLoading) {
if ((queryStoreValue.graphQLErrors && queryStoreValue.graphQLErrors.length > 0) ||
queryStoreValue.networkError) {
var apolloError_1 = new ApolloError({
graphQLErrors: queryStoreValue.graphQLErrors,
networkError: queryStoreValue.networkError,
});
previouslyHadError = true;
if (observer.error) {
try {
observer.error(apolloError_1);
}
catch (e) {
setTimeout(function () { throw e; }, 0);
}
}
else {
setTimeout(function () { throw apolloError_1; }, 0);
if (!isProduction()) {
console.info('An unhandled error was thrown because no error handler is registered ' +
'for the query ' + queryStoreValue.queryString);
}
}
}
else {
try {
var _a = diffQueryAgainstStore({
store: _this.getDataWithOptimisticResults(),
query: _this.queryDocuments[queryId],
variables: queryStoreValue.previousVariables || queryStoreValue.variables,
config: _this.reducerConfig,
fragmentMatcherFunction: _this.fragmentMatcher.match,
previousResult: lastResult && lastResult.data,
}), data = _a.result, isMissing = _a.isMissing;
var resultFromStore = void 0;
if (isMissing && fetchPolicy !== 'cache-only') {
resultFromStore = {
data: lastResult && lastResult.data,
loading: isNetworkRequestInFlight(queryStoreValue.networkStatus),
networkStatus: queryStoreValue.networkStatus,
stale: true,
};
}
else {
resultFromStore = {
data: data,
loading: isNetworkRequestInFlight(queryStoreValue.networkStatus),
networkStatus: queryStoreValue.networkStatus,
stale: false,
};
}
if (observer.next) {
var isDifferentResult = !(lastResult &&
resultFromStore &&
lastResult.networkStatus === resultFromStore.networkStatus &&
lastResult.stale === resultFromStore.stale &&
lastResult.data === resultFromStore.data);
if (isDifferentResult || previouslyHadError) {
lastResult = resultFromStore;
try {
observer.next(maybeDeepFreeze(resultFromStore));
}
catch (e) {
setTimeout(function () { throw e; }, 0);
}
}
}
previouslyHadError = false;
}
catch (error) {
previouslyHadError = true;
if (observer.error) {
observer.error(new ApolloError({
networkError: error,
}));
}
return;
}
}
}
};
};
QueryManager.prototype.watchQuery = function (options, shouldSubscribe) {
if (shouldSubscribe === void 0) { shouldSubscribe = true; }
if (options.returnPartialData) {
throw new Error('returnPartialData option is no longer supported since Apollo Client 1.0.');
}
if (options.forceFetch) {
throw new Error('forceFetch option is no longer supported since Apollo Client 1.0. Use fetchPolicy instead.');
}
if (options.noFetch) {
throw new Error('noFetch option is no longer supported since Apollo Client 1.0. Use fetchPolicy instead.');
}
if (options.fetchPolicy === 'standby') {
throw new Error('client.watchQuery cannot be called with fetchPolicy set to "standby"');
}
var queryDefinition = getQueryDefinition(options.query);
if (queryDefinition.variableDefinitions && queryDefinition.variableDefinitions.length) {
var defaultValues = getDefaultValues(queryDefinition);
options.variables = assign({}, defaultValues, options.variables);
}
if (typeof options.notifyOnNetworkStatusChange === 'undefined') {
options.notifyOnNetworkStatusChange = false;
}
var transformedOptions = __assign({}, options);
var observableQuery = new ObservableQuery({
scheduler: this.scheduler,
options: transformedOptions,
shouldSubscribe: shouldSubscribe,
});
return observableQuery;
};
QueryManager.prototype.query = function (options) {
var _this = this;
if (!options.query) {
throw new Error('query option is required. You must specify your GraphQL document in the query option.');
}
if (options.query.kind !== 'Document') {
throw new Error('You must wrap the query string in a "gql" tag.');
}
if (options.returnPartialData) {
throw new Error('returnPartialData option only supported on watchQuery.');
}
if (options.pollInterval) {
throw new Error('pollInterval option only supported on watchQuery.');
}
if (options.forceFetch) {
throw new Error('forceFetch option is no longer supported since Apollo Client 1.0. Use fetchPolicy instead.');
}
if (options.noFetch) {
throw new Error('noFetch option is no longer supported since Apollo Client 1.0. Use fetchPolicy instead.');
}
if (typeof options.notifyOnNetworkStatusChange !== 'undefined') {
throw new Error('Cannot call "query" with "notifyOnNetworkStatusChange" option. Only "watchQuery" has that option.');
}
options.notifyOnNetworkStatusChange = false;
var requestId = this.idCounter;
var resPromise = new Promise(function (resolve, reject) {
_this.addFetchQueryPromise(requestId, resPromise, resolve, reject);
return _this.watchQuery(options, false).result().then(function (result) {
_this.removeFetchQueryPromise(requestId);
resolve(result);
}).catch(function (error) {
_this.removeFetchQueryPromise(requestId);
reject(error);
});
});
return resPromise;
};
QueryManager.prototype.generateQueryId = function () {
var queryId = this.idCounter.toString();
this.idCounter++;
return queryId;
};
QueryManager.prototype.stopQueryInStore = function (queryId) {
this.store.dispatch({
type: 'APOLLO_QUERY_STOP',
queryId: queryId,
});
};
QueryManager.prototype.getApolloState = function () {
return this.reduxRootSelector(this.store.getState());
};
QueryManager.prototype.selectApolloState = function (store) {
return this.reduxRootSelector(store.getState());
};
QueryManager.prototype.getInitialState = function () {
return { data: this.getApolloState().data };
};
QueryManager.prototype.getDataWithOptimisticResults = function () {
return getDataWithOptimisticResults(this.getApolloState());
};
QueryManager.prototype.addQueryListener = function (queryId, listener) {
this.queryListeners[queryId] = this.queryListeners[queryId] || [];
this.queryListeners[queryId].push(listener);
};
QueryManager.prototype.addFetchQueryPromise = function (requestId, promise, resolve, reject) {
this.fetchQueryPromises[requestId.toString()] = { promise: promise, resolve: resolve, reject: reject };
};
QueryManager.prototype.removeFetchQueryPromise = function (requestId) {
delete this.fetchQueryPromises[requestId.toString()];
};
QueryManager.prototype.addObservableQuery = function (queryId, observableQuery) {
this.observableQueries[queryId] = { observableQuery: observableQuery };
var queryDef = getQueryDefinition(observableQuery.options.query);
if (queryDef.name && queryDef.name.value) {
var queryName = queryDef.name.value;
this.queryIdsByName[queryName] = this.queryIdsByName[queryName] || [];
this.queryIdsByName[queryName].push(observableQuery.queryId);
}
};
QueryManager.prototype.removeObservableQuery = function (queryId) {
var observableQuery = this.observableQueries[queryId].observableQuery;
var definition = getQueryDefinition(observableQuery.options.query);
var queryName = definition.name ? definition.name.value : null;
delete this.observableQueries[queryId];
if (queryName) {
this.queryIdsByName[queryName] = this.queryIdsByName[queryName].filter(function (val) {
return !(observableQuery.queryId === val);
});
}
};
QueryManager.prototype.resetStore = function () {
var _this = this;
Object.keys(this.fetchQueryPromises).forEach(function (key) {
var reject = _this.fetchQueryPromises[key].reject;
reject(new Error('Store reset while query was in flight.'));
});
this.store.dispatch({
type: 'APOLLO_STORE_RESET',
observableQueryIds: Object.keys(this.observableQueries),
});
Object.keys(this.observableQueries).forEach(function (queryId) {
var storeQuery = _this.reduxRootSelector(_this.store.getState()).queries[queryId];
var fetchPolicy = _this.observableQueries[queryId].observableQuery.options.fetchPolicy;
if (fetchPolicy !== 'cache-only' && fetchPolicy !== 'standby') {
_this.observableQueries[queryId].observableQuery.refetch();
}
});
};
QueryManager.prototype.startQuery = function (queryId, options, listener) {
this.addQueryListener(queryId, listener);
this.fetchQuery(queryId, options)
.catch(function (error) { return undefined; });
return queryId;
};
QueryManager.prototype.startGraphQLSubscription = function (options) {
var _this = this;
var query = options.query;
var transformedDoc = query;
if (this.addTypename) {
transformedDoc = addTypenameToDocument(transformedDoc);
}
var variables = assign({}, getDefaultValues(getOperationDefinition(query)), options.variables);
var request = {
query: transformedDoc,
variables: variables,
operationName: getOperationName(transformedDoc),
};
var subId;
var observers = [];
return new Observable(function (observer) {
observers.push(observer);
if (observers.length === 1) {
var handler = function (error, result) {
if (error) {
observers.forEach(function (obs) {
if (obs.error) {
obs.error(error);
}
});
}
else {
_this.store.dispatch({
type: 'APOLLO_SUBSCRIPTION_RESULT',
document: transformedDoc,
operationName: getOperationName(transformedDoc),
result: { data: result },
variables: variables,
subscriptionId: subId,
extraReducers: _this.getExtraReducers(),
});
observers.forEach(function (obs) {
if (obs.next) {
obs.next(result);
}
});
}
};
subId = _this.networkInterface.subscribe(request, handler);
}
return {
unsubscribe: function () {
observers = observers.filter(function (obs) { return obs !== observer; });
if (observers.length === 0) {
_this.networkInterface.unsubscribe(subId);
}
},
_networkSubscriptionId: subId,
};
});
};
QueryManager.prototype.removeQuery = function (queryId) {
delete this.queryListeners[queryId];
delete this.queryDocuments[queryId];
};
QueryManager.prototype.stopQuery = function (queryId) {
this.removeQuery(queryId);
this.stopQueryInStore(queryId);
};
QueryManager.prototype.getCurrentQueryResult = function (observableQuery, isOptimistic) {
if (isOptimistic === void 0) { isOptimistic = false; }
var _a = this.getQueryParts(observableQuery), variables = _a.variables, document = _a.document;
var lastResult = observableQuery.getLastResult();
var queryOptions = observableQuery.options;
var readOptions = {
store: isOptimistic ? this.getDataWithOptimisticResults() : this.getApolloState().data,
query: document,
variables: variables,
config: this.reducerConfig,
previousResult: lastResult ? lastResult.data : undefined,
fragmentMatcherFunction: this.fragmentMatcher.match,
};
try {
var data = readQueryFromStore(readOptions);
return maybeDeepFreeze({ data: data, partial: false });
}
catch (e) {
return maybeDeepFreeze({ data: {}, partial: true });
}
};
QueryManager.prototype.getQueryWithPreviousResult = function (queryIdOrObservable, isOptimistic) {
if (isOptimistic === void 0) { isOptimistic = false; }
var observableQuery;
if (typeof queryIdOrObservable === 'string') {
if (!this.observableQueries[queryIdOrObservable]) {
throw new Error("ObservableQuery with this id doesn't exist: " + queryIdOrObservable);
}
observableQuery = this.observableQueries[queryIdOrObservable].observableQuery;
}
else {
observableQuery = queryIdOrObservable;
}
var _a = this.getQueryParts(observableQuery), variables = _a.variables, document = _a.document;
var data = this.getCurrentQueryResult(observableQuery, isOptimistic).data;
return {
previousResult: data,
variables: variables,
document: document,
};
};
QueryManager.prototype.getQueryParts = function (observableQuery) {
var queryOptions = observableQuery.options;
var transformedDoc = observableQuery.options.query;
if (this.addTypename) {
transformedDoc = addTypenameToDocument(transformedDoc);
}
return {
variables: queryOptions.variables,
document: transformedDoc,
};
};
QueryManager.prototype.transformQueryDocument = function (options) {
var queryDoc = options.query;
if (this.addTypename) {
queryDoc = addTypenameToDocument(queryDoc);
}
return {
queryDoc: queryDoc,
};
};
QueryManager.prototype.getExtraReducers = function () {
var _this = this;
return Object.keys(this.observableQueries).map(function (obsQueryId) {
var query = _this.observableQueries[obsQueryId].observableQuery;
var queryOptions = query.options;
if (queryOptions.reducer) {
return createStoreReducer(queryOptions.reducer, _this.addTypename ? addTypenameToDocument(queryOptions.query) : queryOptions.query, query.variables || {}, _this.reducerConfig);
}
return null;
}).filter(function (reducer) { return reducer !== null; });
};
QueryManager.prototype.fetchRequest = function (_a) {
var _this = this;
var requestId = _a.requestId, queryId = _a.queryId, document = _a.document, options = _a.options, fetchMoreForQueryId = _a.fetchMoreForQueryId;
var variables = options.variables;
var request = {
query: document,
variables: variables,
operationName: getOperationName(document),
};
var retPromise = new Promise(function (resolve, reject) {
_this.addFetchQueryPromise(requestId, retPromise, resolve, reject);
_this.deduplicator.query(request, _this.queryDeduplication)
.then(function (result) {
var extraReducers = _this.getExtraReducers();
_this.store.dispatch({
type: 'APOLLO_QUERY_RESULT',
document: document,
operationName: getOperationName(document),
result: result,
queryId: queryId,
requestId: requestId,
fetchMoreForQueryId: fetchMoreForQueryId,
extraReducers: extraReducers,
});
_this.removeFetchQueryPromise(requestId);
if (result.errors) {
throw new ApolloError({
graphQLErrors: result.errors,
});
}
return result;
}).then(function () {
var resultFromStore;
try {
resultFromStore = readQueryFromStore({
store: _this.getApolloState().data,
variables: variables,
query: document,
config: _this.reducerConfig,
fragmentMatcherFunction: _this.fragmentMatcher.match,
});
}
catch (e) { }
var reducerError = _this.getApolloState().reducerError;
if (reducerError && reducerError.queryId === queryId) {
return Promise.reject(reducerError.error);
}
_this.removeFetchQueryPromise(requestId);
resolve({ data: resultFromStore, loading: false, networkStatus: NetworkStatus.ready, stale: false });
return Promise.resolve();
}).catch(function (error) {
reject(error);
});
});
return retPromise;
};
QueryManager.prototype.refetchQueryByName = function (queryName) {
var _this = this;
var refetchedQueries = this.queryIdsByName[queryName];
if (refetchedQueries === undefined) {
console.warn("Warning: unknown query with name " + queryName + " asked to refetch");
return;
}
else {
return Promise.all(refetchedQueries.map(function (queryId) { return _this.observableQueries[queryId].observableQuery.refetch(); }));
}
};
QueryManager.prototype.broadcastQueries = function () {
var _this = this;
var queries = this.getApolloState().queries;
Object.keys(this.queryListeners).forEach(function (queryId) {
var listeners = _this.queryListeners[queryId];
if (listeners) {
listeners.forEach(function (listener) {
if (listener) {
var queryStoreValue = queries[queryId];
listener(queryStoreValue);
}
});
}
});
};
QueryManager.prototype.generateRequestId = function () {
var requestId = this.idCounter;
this.idCounter++;
return requestId;
};
return QueryManager;
}());
export { QueryManager };
//# sourceMappingURL=QueryManager.js.map