UNPKG

apollo-client

Version:
362 lines 17.1 kB
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 { ApolloLink, execute, } from 'apollo-link'; import { isProduction, removeConnectionDirectiveFromDocument, } from 'apollo-utilities'; import { QueryManager } from './core/QueryManager'; import { DataStore } from './data/store'; import { version } from './version'; var hasSuggestedDevtools = false; var supportedDirectives = new ApolloLink(function (operation, forward) { operation.query = removeConnectionDirectiveFromDocument(operation.query); return forward(operation); }); /** * This is the primary Apollo Client class. It is used to send GraphQL documents (i.e. queries * and mutations) to a GraphQL spec-compliant server over a {@link NetworkInterface} instance, * receive results from the server and cache the results in a store. It also delivers updates * to GraphQL queries through {@link Observable} instances. */ var ApolloClient = /** @class */ (function () { /** * Constructs an instance of {@link ApolloClient}. * * @param link The {@link ApolloLink} over which GraphQL documents will be resolved into a response. * * @param cache The initial cache to use in the data store. * * @param ssrMode Determines whether this is being run in Server Side Rendering (SSR) mode. * * @param ssrForceFetchDelay Determines the time interval before we force fetch queries for a * server side render. * * @param queryDeduplication If set to false, a query will still be sent to the server even if a query * with identical parameters (query, variables, operationName) is already in flight. * */ function ApolloClient(options) { var _this = this; this.defaultOptions = {}; this.resetStoreCallbacks = []; var link = options.link, cache = options.cache, _a = options.ssrMode, ssrMode = _a === void 0 ? false : _a, _b = options.ssrForceFetchDelay, ssrForceFetchDelay = _b === void 0 ? 0 : _b, connectToDevTools = options.connectToDevTools, _c = options.queryDeduplication, queryDeduplication = _c === void 0 ? true : _c, defaultOptions = options.defaultOptions; if (!link || !cache) { throw new Error("\n In order to initialize Apollo Client, you must specify link & cache properties on the config object.\n This is part of the required upgrade when migrating from Apollo Client 1.0 to Apollo Client 2.0.\n For more information, please visit:\n https://www.apollographql.com/docs/react/basics/setup.html\n to help you get started.\n "); } // remove apollo-client supported directives this.link = supportedDirectives.concat(link); this.cache = cache; this.store = new DataStore(cache); this.disableNetworkFetches = ssrMode || ssrForceFetchDelay > 0; this.queryDeduplication = queryDeduplication; this.ssrMode = ssrMode; this.defaultOptions = defaultOptions || {}; if (ssrForceFetchDelay) { setTimeout(function () { return (_this.disableNetworkFetches = false); }, ssrForceFetchDelay); } this.watchQuery = this.watchQuery.bind(this); this.query = this.query.bind(this); this.mutate = this.mutate.bind(this); this.resetStore = this.resetStore.bind(this); this.reFetchObservableQueries = this.reFetchObservableQueries.bind(this); // Attach the client instance to window to let us be found by chrome devtools, but only in // development mode var defaultConnectToDevTools = !isProduction() && typeof window !== 'undefined' && !window.__APOLLO_CLIENT__; if (typeof connectToDevTools === 'undefined' ? defaultConnectToDevTools : connectToDevTools && typeof window !== 'undefined') { window.__APOLLO_CLIENT__ = this; } /** * Suggest installing the devtools for developers who don't have them */ if (!hasSuggestedDevtools && !isProduction()) { hasSuggestedDevtools = true; if (typeof window !== 'undefined' && window.document && window.top === window.self) { // First check if devtools is not installed if (typeof window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { // Only for Chrome if (window.navigator && window.navigator.userAgent.indexOf('Chrome') > -1) { // tslint:disable-next-line console.debug('Download the Apollo DevTools ' + 'for a better development experience: ' + 'https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm'); } } } } this.version = version; } /** * This watches the results of the query according to the options specified and * returns an {@link ObservableQuery}. We can subscribe to this {@link ObservableQuery} and * receive updated results through a GraphQL observer. * <p /><p /> * Note that this method is not an implementation of GraphQL subscriptions. Rather, * it uses Apollo's store in order to reactively deliver updates to your query results. * <p /><p /> * For example, suppose you call watchQuery on a GraphQL query that fetches an person's * first name and last name and this person has a particular object identifer, provided by * dataIdFromObject. Later, a different query fetches that same person's * first and last name and his/her first name has now changed. Then, any observers associated * with the results of the first query will be updated with a new result object. * <p /><p /> * See [here](https://medium.com/apollo-stack/the-concepts-of-graphql-bc68bd819be3#.3mb0cbcmc) for * a description of store reactivity. * */ ApolloClient.prototype.watchQuery = function (options) { this.initQueryManager(); if (this.defaultOptions.watchQuery) { options = __assign({}, this.defaultOptions.watchQuery, options); } // XXX Overwriting options is probably not the best way to do this long term... if (this.disableNetworkFetches && (options.fetchPolicy === 'network-only' || options.fetchPolicy === 'cache-and-network')) { options = __assign({}, options, { fetchPolicy: 'cache-first' }); } return this.queryManager.watchQuery(options); }; /** * This resolves a single query according to the options specified and * returns a {@link Promise} which is either resolved with the resulting data * or rejected with an error. * * @param options An object of type {@link QueryOptions} that allows us to * describe how this query should be treated e.g. whether it should hit the * server at all or just resolve from the cache, etc. */ ApolloClient.prototype.query = function (options) { this.initQueryManager(); if (this.defaultOptions.query) { options = __assign({}, this.defaultOptions.query, options); } if (options.fetchPolicy === 'cache-and-network') { throw new Error('cache-and-network fetchPolicy can only be used with watchQuery'); } // XXX Overwriting options is probably not the best way to do this long // term... if (this.disableNetworkFetches && options.fetchPolicy === 'network-only') { options = __assign({}, options, { fetchPolicy: 'cache-first' }); } return this.queryManager.query(options); }; /** * This resolves a single mutation according to the options specified and returns a * {@link Promise} which is either resolved with the resulting data or rejected with an * error. * * It takes options as an object with the following keys and values: */ ApolloClient.prototype.mutate = function (options) { this.initQueryManager(); if (this.defaultOptions.mutate) { options = __assign({}, this.defaultOptions.mutate, options); } return this.queryManager.mutate(options); }; /** * This subscribes to a graphql subscription according to the options specified and returns an * {@link Observable} which either emits received data or an error. */ ApolloClient.prototype.subscribe = function (options) { this.initQueryManager(); return this.queryManager.startGraphQLSubscription(options); }; /** * Tries to read some data from the store in the shape of the provided * GraphQL query without making a network request. This method will start at * the root query. To start at a specific id returned by `dataIdFromObject` * use `readFragment`. */ ApolloClient.prototype.readQuery = function (options) { return this.initProxy().readQuery(options); }; /** * Tries to read some data from the store in the shape of the provided * GraphQL fragment without making a network request. This method will read a * GraphQL fragment from any arbitrary id that is currently cached, unlike * `readQuery` which will only read from the root query. * * You must pass in a GraphQL document with a single fragment or a document * with multiple fragments that represent what you are reading. If you pass * in a document with multiple fragments then you must also specify a * `fragmentName`. */ ApolloClient.prototype.readFragment = function (options) { return this.initProxy().readFragment(options); }; /** * Writes some data in the shape of the provided GraphQL query directly to * the store. This method will start at the root query. To start at a a * specific id returned by `dataIdFromObject` then use `writeFragment`. */ ApolloClient.prototype.writeQuery = function (options) { var result = this.initProxy().writeQuery(options); this.queryManager.broadcastQueries(); return result; }; /** * Writes some data in the shape of the provided GraphQL fragment directly to * the store. This method will write to a GraphQL fragment from any arbitrary * id that is currently cached, unlike `writeQuery` which will only write * from the root query. * * You must pass in a GraphQL document with a single fragment or a document * with multiple fragments that represent what you are writing. If you pass * in a document with multiple fragments then you must also specify a * `fragmentName`. */ ApolloClient.prototype.writeFragment = function (options) { var result = this.initProxy().writeFragment(options); this.queryManager.broadcastQueries(); return result; }; /** * Sugar for writeQuery & writeFragment * This method will construct a query from the data object passed in. * If no id is supplied, writeData will write the data to the root. * If an id is supplied, writeData will write a fragment to the object * specified by the id in the store. * * Since you aren't passing in a query to check the shape of the data, * you must pass in an object that conforms to the shape of valid GraphQL data. */ ApolloClient.prototype.writeData = function (options) { var result = this.initProxy().writeData(options); this.queryManager.broadcastQueries(); return result; }; ApolloClient.prototype.__actionHookForDevTools = function (cb) { this.devToolsHookCb = cb; }; ApolloClient.prototype.__requestRaw = function (payload) { return execute(this.link, payload); }; /** * This initializes the query manager that tracks queries and the cache */ ApolloClient.prototype.initQueryManager = function () { var _this = this; if (this.queryManager) return; this.queryManager = new QueryManager({ link: this.link, store: this.store, queryDeduplication: this.queryDeduplication, ssrMode: this.ssrMode, onBroadcast: function () { if (_this.devToolsHookCb) { _this.devToolsHookCb({ action: {}, state: { queries: _this.queryManager.queryStore.getStore(), mutations: _this.queryManager.mutationStore.getStore(), }, dataWithOptimisticResults: _this.cache.extract(true), }); } }, }); }; /** * Resets your entire store by clearing out your cache and then re-executing * all of your active queries. This makes it so that you may guarantee that * there is no data left in your store from a time before you called this * method. * * `resetStore()` is useful when your user just logged out. You’ve removed the * user session, and you now want to make sure that any references to data you * might have fetched while the user session was active is gone. * * It is important to remember that `resetStore()` *will* refetch any active * queries. This means that any components that might be mounted will execute * their queries again using your network interface. If you do not want to * re-execute any queries then you should make sure to stop watching any * active queries. */ ApolloClient.prototype.resetStore = function () { var _this = this; return Promise.resolve() .then(function () { return _this.queryManager ? _this.queryManager.clearStore() : Promise.resolve(null); }) .then(function () { return Promise.all(_this.resetStoreCallbacks.map(function (fn) { return fn(); })); }) .then(function () { return _this.queryManager && _this.queryManager.reFetchObservableQueries ? _this.queryManager.reFetchObservableQueries() : Promise.resolve(null); }); }; /** * Allows callbacks to be registered that are executed with the store is reset. * onResetStore returns an unsubscribe function for removing your registered callbacks. */ ApolloClient.prototype.onResetStore = function (cb) { var _this = this; this.resetStoreCallbacks.push(cb); return function () { _this.resetStoreCallbacks = _this.resetStoreCallbacks.filter(function (c) { return c !== cb; }); }; }; /** * Refetches all of your active queries. * * `reFetchObservableQueries()` is useful if you want to bring the client back to proper state in case of a network outage * * It is important to remember that `reFetchObservableQueries()` *will* refetch any active * queries. This means that any components that might be mounted will execute * their queries again using your network interface. If you do not want to * re-execute any queries then you should make sure to stop watching any * active queries. * Takes optional parameter `includeStandby` which will include queries in standby-mode when refetching. */ ApolloClient.prototype.reFetchObservableQueries = function (includeStandby) { return this.queryManager ? this.queryManager.reFetchObservableQueries(includeStandby) : Promise.resolve(null); }; /** * Exposes the cache's complete state, in a serializable format for later restoration. */ ApolloClient.prototype.extract = function (optimistic) { return this.initProxy().extract(optimistic); }; /** * Replaces existing state in the cache (if any) with the values expressed by * `serializedState`. * * Called when hydrating a cache (server side rendering, or offline storage), * and also (potentially) during hot reloads. */ ApolloClient.prototype.restore = function (serializedState) { return this.initProxy().restore(serializedState); }; /** * Initializes a data proxy for this client instance if one does not already * exist and returns either a previously initialized proxy instance or the * newly initialized instance. */ ApolloClient.prototype.initProxy = function () { if (!this.proxy) { this.initQueryManager(); this.proxy = this.cache; } return this.proxy; }; return ApolloClient; }()); export default ApolloClient; //# sourceMappingURL=ApolloClient.js.map