UNPKG

24.1 kBJavaScriptView Raw
1import { __assign } from "tslib";
2import { invariant, newInvariantError } from "../utilities/globals/index.js";
3import { ApolloLink, execute } from "../link/core/index.js";
4import { version } from "../version.js";
5import { HttpLink } from "../link/http/index.js";
6import { QueryManager } from "./QueryManager.js";
7import { LocalState } from "./LocalState.js";
8var hasSuggestedDevtools = false;
9// Though mergeOptions now resides in @apollo/client/utilities, it was
10// previously declared and exported from this module, and then reexported from
11// @apollo/client/core. Since we need to preserve that API anyway, the easiest
12// solution is to reexport mergeOptions where it was previously declared (here).
13import { mergeOptions } from "../utilities/index.js";
14import { getApolloClientMemoryInternals } from "../utilities/caching/getMemoryInternals.js";
15export { mergeOptions };
16/**
17 * This is the primary Apollo Client class. It is used to send GraphQL documents (i.e. queries
18 * and mutations) to a GraphQL spec-compliant server over an `ApolloLink` instance,
19 * receive results from the server and cache the results in a store. It also delivers updates
20 * to GraphQL queries through `Observable` instances.
21 */
22var ApolloClient = /** @class */ (function () {
23 /**
24 * Constructs an instance of `ApolloClient`.
25 *
26 * @example
27 * ```js
28 * import { ApolloClient, InMemoryCache } from '@apollo/client';
29 *
30 * const cache = new InMemoryCache();
31 *
32 * const client = new ApolloClient({
33 * // Provide required constructor fields
34 * cache: cache,
35 * uri: 'http://localhost:4000/',
36 *
37 * // Provide some optional constructor fields
38 * name: 'react-web-client',
39 * version: '1.3',
40 * queryDeduplication: false,
41 * defaultOptions: {
42 * watchQuery: {
43 * fetchPolicy: 'cache-and-network',
44 * },
45 * },
46 * });
47 * ```
48 */
49 function ApolloClient(options) {
50 var _this = this;
51 this.resetStoreCallbacks = [];
52 this.clearStoreCallbacks = [];
53 if (!options.cache) {
54 throw newInvariantError(15);
55 }
56 var uri = options.uri, credentials = options.credentials, headers = options.headers, cache = options.cache, documentTransform = options.documentTransform, _a = options.ssrMode, ssrMode = _a === void 0 ? false : _a, _b = options.ssrForceFetchDelay, ssrForceFetchDelay = _b === void 0 ? 0 : _b,
57 // Expose the client instance as window.__APOLLO_CLIENT__ and call
58 // onBroadcast in queryManager.broadcastQueries to enable browser
59 // devtools, but disable them by default in production.
60 connectToDevTools = options.connectToDevTools, _c = options.queryDeduplication, queryDeduplication = _c === void 0 ? true : _c, defaultOptions = options.defaultOptions, defaultContext = options.defaultContext, _d = options.assumeImmutableResults, assumeImmutableResults = _d === void 0 ? cache.assumeImmutableResults : _d, resolvers = options.resolvers, typeDefs = options.typeDefs, fragmentMatcher = options.fragmentMatcher, clientAwarenessName = options.name, clientAwarenessVersion = options.version, devtools = options.devtools;
61 var link = options.link;
62 if (!link) {
63 link =
64 uri ? new HttpLink({ uri: uri, credentials: credentials, headers: headers }) : ApolloLink.empty();
65 }
66 this.link = link;
67 this.cache = cache;
68 this.disableNetworkFetches = ssrMode || ssrForceFetchDelay > 0;
69 this.queryDeduplication = queryDeduplication;
70 this.defaultOptions = defaultOptions || Object.create(null);
71 this.typeDefs = typeDefs;
72 this.devtoolsConfig = __assign(__assign({}, devtools), { enabled: (devtools === null || devtools === void 0 ? void 0 : devtools.enabled) || connectToDevTools });
73 if (this.devtoolsConfig.enabled === undefined) {
74 this.devtoolsConfig.enabled = globalThis.__DEV__ !== false;
75 }
76 if (ssrForceFetchDelay) {
77 setTimeout(function () { return (_this.disableNetworkFetches = false); }, ssrForceFetchDelay);
78 }
79 this.watchQuery = this.watchQuery.bind(this);
80 this.query = this.query.bind(this);
81 this.mutate = this.mutate.bind(this);
82 this.watchFragment = this.watchFragment.bind(this);
83 this.resetStore = this.resetStore.bind(this);
84 this.reFetchObservableQueries = this.reFetchObservableQueries.bind(this);
85 this.version = version;
86 this.localState = new LocalState({
87 cache: cache,
88 client: this,
89 resolvers: resolvers,
90 fragmentMatcher: fragmentMatcher,
91 });
92 this.queryManager = new QueryManager({
93 cache: this.cache,
94 link: this.link,
95 defaultOptions: this.defaultOptions,
96 defaultContext: defaultContext,
97 documentTransform: documentTransform,
98 queryDeduplication: queryDeduplication,
99 ssrMode: ssrMode,
100 clientAwareness: {
101 name: clientAwarenessName,
102 version: clientAwarenessVersion,
103 },
104 localState: this.localState,
105 assumeImmutableResults: assumeImmutableResults,
106 onBroadcast: this.devtoolsConfig.enabled ?
107 function () {
108 if (_this.devToolsHookCb) {
109 _this.devToolsHookCb({
110 action: {},
111 state: {
112 queries: _this.queryManager.getQueryStore(),
113 mutations: _this.queryManager.mutationStore || {},
114 },
115 dataWithOptimisticResults: _this.cache.extract(true),
116 });
117 }
118 }
119 : void 0,
120 });
121 if (this.devtoolsConfig.enabled)
122 this.connectToDevTools();
123 }
124 ApolloClient.prototype.connectToDevTools = function () {
125 if (typeof window === "undefined") {
126 return;
127 }
128 var windowWithDevTools = window;
129 var devtoolsSymbol = Symbol.for("apollo.devtools");
130 (windowWithDevTools[devtoolsSymbol] =
131 windowWithDevTools[devtoolsSymbol] || []).push(this);
132 windowWithDevTools.__APOLLO_CLIENT__ = this;
133 /**
134 * Suggest installing the devtools for developers who don't have them
135 */
136 if (!hasSuggestedDevtools && globalThis.__DEV__ !== false) {
137 hasSuggestedDevtools = true;
138 if (window.document &&
139 window.top === window.self &&
140 /^(https?|file):$/.test(window.location.protocol)) {
141 setTimeout(function () {
142 if (!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__) {
143 var nav = window.navigator;
144 var ua = nav && nav.userAgent;
145 var url = void 0;
146 if (typeof ua === "string") {
147 if (ua.indexOf("Chrome/") > -1) {
148 url =
149 "https://chrome.google.com/webstore/detail/" +
150 "apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm";
151 }
152 else if (ua.indexOf("Firefox/") > -1) {
153 url =
154 "https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/";
155 }
156 }
157 if (url) {
158 globalThis.__DEV__ !== false && invariant.log("Download the Apollo DevTools for a better development " +
159 "experience: %s", url);
160 }
161 }
162 }, 10000);
163 }
164 }
165 };
166 Object.defineProperty(ApolloClient.prototype, "documentTransform", {
167 /**
168 * The `DocumentTransform` used to modify GraphQL documents before a request
169 * is made. If a custom `DocumentTransform` is not provided, this will be the
170 * default document transform.
171 */
172 get: function () {
173 return this.queryManager.documentTransform;
174 },
175 enumerable: false,
176 configurable: true
177 });
178 /**
179 * Call this method to terminate any active client processes, making it safe
180 * to dispose of this `ApolloClient` instance.
181 */
182 ApolloClient.prototype.stop = function () {
183 this.queryManager.stop();
184 };
185 /**
186 * This watches the cache store of the query according to the options specified and
187 * returns an `ObservableQuery`. We can subscribe to this `ObservableQuery` and
188 * receive updated results through an observer when the cache store changes.
189 *
190 * Note that this method is not an implementation of GraphQL subscriptions. Rather,
191 * it uses Apollo's store in order to reactively deliver updates to your query results.
192 *
193 * For example, suppose you call watchQuery on a GraphQL query that fetches a person's
194 * first and last name and this person has a particular object identifier, provided by
195 * dataIdFromObject. Later, a different query fetches that same person's
196 * first and last name and the first name has now changed. Then, any observers associated
197 * with the results of the first query will be updated with a new result object.
198 *
199 * Note that if the cache does not change, the subscriber will *not* be notified.
200 *
201 * See [here](https://medium.com/apollo-stack/the-concepts-of-graphql-bc68bd819be3#.3mb0cbcmc) for
202 * a description of store reactivity.
203 */
204 ApolloClient.prototype.watchQuery = function (options) {
205 if (this.defaultOptions.watchQuery) {
206 options = mergeOptions(this.defaultOptions.watchQuery, options);
207 }
208 // XXX Overwriting options is probably not the best way to do this long term...
209 if (this.disableNetworkFetches &&
210 (options.fetchPolicy === "network-only" ||
211 options.fetchPolicy === "cache-and-network")) {
212 options = __assign(__assign({}, options), { fetchPolicy: "cache-first" });
213 }
214 return this.queryManager.watchQuery(options);
215 };
216 /**
217 * This resolves a single query according to the options specified and
218 * returns a `Promise` which is either resolved with the resulting data
219 * or rejected with an error.
220 *
221 * @param options - An object of type `QueryOptions` that allows us to
222 * describe how this query should be treated e.g. whether it should hit the
223 * server at all or just resolve from the cache, etc.
224 */
225 ApolloClient.prototype.query = function (options) {
226 if (this.defaultOptions.query) {
227 options = mergeOptions(this.defaultOptions.query, options);
228 }
229 invariant(options.fetchPolicy !== "cache-and-network", 16);
230 if (this.disableNetworkFetches && options.fetchPolicy === "network-only") {
231 options = __assign(__assign({}, options), { fetchPolicy: "cache-first" });
232 }
233 return this.queryManager.query(options);
234 };
235 /**
236 * This resolves a single mutation according to the options specified and returns a
237 * Promise which is either resolved with the resulting data or rejected with an
238 * error. In some cases both `data` and `errors` might be undefined, for example
239 * when `errorPolicy` is set to `'ignore'`.
240 *
241 * It takes options as an object with the following keys and values:
242 */
243 ApolloClient.prototype.mutate = function (options) {
244 if (this.defaultOptions.mutate) {
245 options = mergeOptions(this.defaultOptions.mutate, options);
246 }
247 return this.queryManager.mutate(options);
248 };
249 /**
250 * This subscribes to a graphql subscription according to the options specified and returns an
251 * `Observable` which either emits received data or an error.
252 */
253 ApolloClient.prototype.subscribe = function (options) {
254 return this.queryManager.startGraphQLSubscription(options);
255 };
256 /**
257 * Tries to read some data from the store in the shape of the provided
258 * GraphQL query without making a network request. This method will start at
259 * the root query. To start at a specific id returned by `dataIdFromObject`
260 * use `readFragment`.
261 *
262 * @param optimistic - Set to `true` to allow `readQuery` to return
263 * optimistic results. Is `false` by default.
264 */
265 ApolloClient.prototype.readQuery = function (options, optimistic) {
266 if (optimistic === void 0) { optimistic = false; }
267 return this.cache.readQuery(options, optimistic);
268 };
269 /**
270 * Watches the cache store of the fragment according to the options specified
271 * and returns an `Observable`. We can subscribe to this
272 * `Observable` and receive updated results through an
273 * observer when the cache store changes.
274 *
275 * You must pass in a GraphQL document with a single fragment or a document
276 * with multiple fragments that represent what you are reading. If you pass
277 * in a document with multiple fragments then you must also specify a
278 * `fragmentName`.
279 *
280 * @since 3.10.0
281 * @param options - An object of type `WatchFragmentOptions` that allows
282 * the cache to identify the fragment and optionally specify whether to react
283 * to optimistic updates.
284 */
285 ApolloClient.prototype.watchFragment = function (options) {
286 return this.cache.watchFragment(options);
287 };
288 /**
289 * Tries to read some data from the store in the shape of the provided
290 * GraphQL fragment without making a network request. This method will read a
291 * GraphQL fragment from any arbitrary id that is currently cached, unlike
292 * `readQuery` which will only read from the root query.
293 *
294 * You must pass in a GraphQL document with a single fragment or a document
295 * with multiple fragments that represent what you are reading. If you pass
296 * in a document with multiple fragments then you must also specify a
297 * `fragmentName`.
298 *
299 * @param optimistic - Set to `true` to allow `readFragment` to return
300 * optimistic results. Is `false` by default.
301 */
302 ApolloClient.prototype.readFragment = function (options, optimistic) {
303 if (optimistic === void 0) { optimistic = false; }
304 return this.cache.readFragment(options, optimistic);
305 };
306 /**
307 * Writes some data in the shape of the provided GraphQL query directly to
308 * the store. This method will start at the root query. To start at a
309 * specific id returned by `dataIdFromObject` then use `writeFragment`.
310 */
311 ApolloClient.prototype.writeQuery = function (options) {
312 var ref = this.cache.writeQuery(options);
313 if (options.broadcast !== false) {
314 this.queryManager.broadcastQueries();
315 }
316 return ref;
317 };
318 /**
319 * Writes some data in the shape of the provided GraphQL fragment directly to
320 * the store. This method will write to a GraphQL fragment from any arbitrary
321 * id that is currently cached, unlike `writeQuery` which will only write
322 * from the root query.
323 *
324 * You must pass in a GraphQL document with a single fragment or a document
325 * with multiple fragments that represent what you are writing. If you pass
326 * in a document with multiple fragments then you must also specify a
327 * `fragmentName`.
328 */
329 ApolloClient.prototype.writeFragment = function (options) {
330 var ref = this.cache.writeFragment(options);
331 if (options.broadcast !== false) {
332 this.queryManager.broadcastQueries();
333 }
334 return ref;
335 };
336 ApolloClient.prototype.__actionHookForDevTools = function (cb) {
337 this.devToolsHookCb = cb;
338 };
339 ApolloClient.prototype.__requestRaw = function (payload) {
340 return execute(this.link, payload);
341 };
342 /**
343 * Resets your entire store by clearing out your cache and then re-executing
344 * all of your active queries. This makes it so that you may guarantee that
345 * there is no data left in your store from a time before you called this
346 * method.
347 *
348 * `resetStore()` is useful when your user just logged out. You’ve removed the
349 * user session, and you now want to make sure that any references to data you
350 * might have fetched while the user session was active is gone.
351 *
352 * It is important to remember that `resetStore()` *will* refetch any active
353 * queries. This means that any components that might be mounted will execute
354 * their queries again using your network interface. If you do not want to
355 * re-execute any queries then you should make sure to stop watching any
356 * active queries.
357 */
358 ApolloClient.prototype.resetStore = function () {
359 var _this = this;
360 return Promise.resolve()
361 .then(function () {
362 return _this.queryManager.clearStore({
363 discardWatches: false,
364 });
365 })
366 .then(function () { return Promise.all(_this.resetStoreCallbacks.map(function (fn) { return fn(); })); })
367 .then(function () { return _this.reFetchObservableQueries(); });
368 };
369 /**
370 * Remove all data from the store. Unlike `resetStore`, `clearStore` will
371 * not refetch any active queries.
372 */
373 ApolloClient.prototype.clearStore = function () {
374 var _this = this;
375 return Promise.resolve()
376 .then(function () {
377 return _this.queryManager.clearStore({
378 discardWatches: true,
379 });
380 })
381 .then(function () { return Promise.all(_this.clearStoreCallbacks.map(function (fn) { return fn(); })); });
382 };
383 /**
384 * Allows callbacks to be registered that are executed when the store is
385 * reset. `onResetStore` returns an unsubscribe function that can be used
386 * to remove registered callbacks.
387 */
388 ApolloClient.prototype.onResetStore = function (cb) {
389 var _this = this;
390 this.resetStoreCallbacks.push(cb);
391 return function () {
392 _this.resetStoreCallbacks = _this.resetStoreCallbacks.filter(function (c) { return c !== cb; });
393 };
394 };
395 /**
396 * Allows callbacks to be registered that are executed when the store is
397 * cleared. `onClearStore` returns an unsubscribe function that can be used
398 * to remove registered callbacks.
399 */
400 ApolloClient.prototype.onClearStore = function (cb) {
401 var _this = this;
402 this.clearStoreCallbacks.push(cb);
403 return function () {
404 _this.clearStoreCallbacks = _this.clearStoreCallbacks.filter(function (c) { return c !== cb; });
405 };
406 };
407 /**
408 * Refetches all of your active queries.
409 *
410 * `reFetchObservableQueries()` is useful if you want to bring the client back to proper state in case of a network outage
411 *
412 * It is important to remember that `reFetchObservableQueries()` *will* refetch any active
413 * queries. This means that any components that might be mounted will execute
414 * their queries again using your network interface. If you do not want to
415 * re-execute any queries then you should make sure to stop watching any
416 * active queries.
417 * Takes optional parameter `includeStandby` which will include queries in standby-mode when refetching.
418 */
419 ApolloClient.prototype.reFetchObservableQueries = function (includeStandby) {
420 return this.queryManager.reFetchObservableQueries(includeStandby);
421 };
422 /**
423 * Refetches specified active queries. Similar to "reFetchObservableQueries()" but with a specific list of queries.
424 *
425 * `refetchQueries()` is useful for use cases to imperatively refresh a selection of queries.
426 *
427 * It is important to remember that `refetchQueries()` *will* refetch specified active
428 * queries. This means that any components that might be mounted will execute
429 * their queries again using your network interface. If you do not want to
430 * re-execute any queries then you should make sure to stop watching any
431 * active queries.
432 */
433 ApolloClient.prototype.refetchQueries = function (options) {
434 var map = this.queryManager.refetchQueries(options);
435 var queries = [];
436 var results = [];
437 map.forEach(function (result, obsQuery) {
438 queries.push(obsQuery);
439 results.push(result);
440 });
441 var result = Promise.all(results);
442 // In case you need the raw results immediately, without awaiting
443 // Promise.all(results):
444 result.queries = queries;
445 result.results = results;
446 // If you decide to ignore the result Promise because you're using
447 // result.queries and result.results instead, you shouldn't have to worry
448 // about preventing uncaught rejections for the Promise.all result.
449 result.catch(function (error) {
450 globalThis.__DEV__ !== false && invariant.debug(17, error);
451 });
452 return result;
453 };
454 /**
455 * Get all currently active `ObservableQuery` objects, in a `Map` keyed by
456 * query ID strings.
457 *
458 * An "active" query is one that has observers and a `fetchPolicy` other than
459 * "standby" or "cache-only".
460 *
461 * You can include all `ObservableQuery` objects (including the inactive ones)
462 * by passing "all" instead of "active", or you can include just a subset of
463 * active queries by passing an array of query names or DocumentNode objects.
464 */
465 ApolloClient.prototype.getObservableQueries = function (include) {
466 if (include === void 0) { include = "active"; }
467 return this.queryManager.getObservableQueries(include);
468 };
469 /**
470 * Exposes the cache's complete state, in a serializable format for later restoration.
471 */
472 ApolloClient.prototype.extract = function (optimistic) {
473 return this.cache.extract(optimistic);
474 };
475 /**
476 * Replaces existing state in the cache (if any) with the values expressed by
477 * `serializedState`.
478 *
479 * Called when hydrating a cache (server side rendering, or offline storage),
480 * and also (potentially) during hot reloads.
481 */
482 ApolloClient.prototype.restore = function (serializedState) {
483 return this.cache.restore(serializedState);
484 };
485 /**
486 * Add additional local resolvers.
487 */
488 ApolloClient.prototype.addResolvers = function (resolvers) {
489 this.localState.addResolvers(resolvers);
490 };
491 /**
492 * Set (override existing) local resolvers.
493 */
494 ApolloClient.prototype.setResolvers = function (resolvers) {
495 this.localState.setResolvers(resolvers);
496 };
497 /**
498 * Get all registered local resolvers.
499 */
500 ApolloClient.prototype.getResolvers = function () {
501 return this.localState.getResolvers();
502 };
503 /**
504 * Set a custom local state fragment matcher.
505 */
506 ApolloClient.prototype.setLocalStateFragmentMatcher = function (fragmentMatcher) {
507 this.localState.setFragmentMatcher(fragmentMatcher);
508 };
509 /**
510 * Define a new ApolloLink (or link chain) that Apollo Client will use.
511 */
512 ApolloClient.prototype.setLink = function (newLink) {
513 this.link = this.queryManager.link = newLink;
514 };
515 Object.defineProperty(ApolloClient.prototype, "defaultContext", {
516 get: function () {
517 return this.queryManager.defaultContext;
518 },
519 enumerable: false,
520 configurable: true
521 });
522 return ApolloClient;
523}());
524export { ApolloClient };
525if (globalThis.__DEV__ !== false) {
526 ApolloClient.prototype.getMemoryInternals = getApolloClientMemoryInternals;
527}
528//# sourceMappingURL=ApolloClient.js.map
\No newline at end of file