queryClient.mjs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. import { parseFilterArgs, parseQueryArgs, functionalUpdate, noop, hashQueryKey, partialMatchKey, hashQueryKeyByOptions } from './utils.mjs';
  2. import { QueryCache } from './queryCache.mjs';
  3. import { MutationCache } from './mutationCache.mjs';
  4. import { focusManager } from './focusManager.mjs';
  5. import { onlineManager } from './onlineManager.mjs';
  6. import { notifyManager } from './notifyManager.mjs';
  7. import { infiniteQueryBehavior } from './infiniteQueryBehavior.mjs';
  8. import { defaultLogger } from './logger.mjs';
  9. // CLASS
  10. class QueryClient {
  11. constructor(config = {}) {
  12. this.queryCache = config.queryCache || new QueryCache();
  13. this.mutationCache = config.mutationCache || new MutationCache();
  14. this.logger = config.logger || defaultLogger;
  15. this.defaultOptions = config.defaultOptions || {};
  16. this.queryDefaults = [];
  17. this.mutationDefaults = [];
  18. this.mountCount = 0;
  19. if (process.env.NODE_ENV !== 'production' && config.logger) {
  20. this.logger.error("Passing a custom logger has been deprecated and will be removed in the next major version.");
  21. }
  22. }
  23. mount() {
  24. this.mountCount++;
  25. if (this.mountCount !== 1) return;
  26. this.unsubscribeFocus = focusManager.subscribe(() => {
  27. if (focusManager.isFocused()) {
  28. this.resumePausedMutations();
  29. this.queryCache.onFocus();
  30. }
  31. });
  32. this.unsubscribeOnline = onlineManager.subscribe(() => {
  33. if (onlineManager.isOnline()) {
  34. this.resumePausedMutations();
  35. this.queryCache.onOnline();
  36. }
  37. });
  38. }
  39. unmount() {
  40. var _this$unsubscribeFocu, _this$unsubscribeOnli;
  41. this.mountCount--;
  42. if (this.mountCount !== 0) return;
  43. (_this$unsubscribeFocu = this.unsubscribeFocus) == null ? void 0 : _this$unsubscribeFocu.call(this);
  44. this.unsubscribeFocus = undefined;
  45. (_this$unsubscribeOnli = this.unsubscribeOnline) == null ? void 0 : _this$unsubscribeOnli.call(this);
  46. this.unsubscribeOnline = undefined;
  47. }
  48. isFetching(arg1, arg2) {
  49. const [filters] = parseFilterArgs(arg1, arg2);
  50. filters.fetchStatus = 'fetching';
  51. return this.queryCache.findAll(filters).length;
  52. }
  53. isMutating(filters) {
  54. return this.mutationCache.findAll({ ...filters,
  55. fetching: true
  56. }).length;
  57. }
  58. getQueryData(queryKey, filters) {
  59. var _this$queryCache$find;
  60. return (_this$queryCache$find = this.queryCache.find(queryKey, filters)) == null ? void 0 : _this$queryCache$find.state.data;
  61. }
  62. ensureQueryData(arg1, arg2, arg3) {
  63. const parsedOptions = parseQueryArgs(arg1, arg2, arg3);
  64. const cachedData = this.getQueryData(parsedOptions.queryKey);
  65. return cachedData ? Promise.resolve(cachedData) : this.fetchQuery(parsedOptions);
  66. }
  67. getQueriesData(queryKeyOrFilters) {
  68. return this.getQueryCache().findAll(queryKeyOrFilters).map(({
  69. queryKey,
  70. state
  71. }) => {
  72. const data = state.data;
  73. return [queryKey, data];
  74. });
  75. }
  76. setQueryData(queryKey, updater, options) {
  77. const query = this.queryCache.find(queryKey);
  78. const prevData = query == null ? void 0 : query.state.data;
  79. const data = functionalUpdate(updater, prevData);
  80. if (typeof data === 'undefined') {
  81. return undefined;
  82. }
  83. const parsedOptions = parseQueryArgs(queryKey);
  84. const defaultedOptions = this.defaultQueryOptions(parsedOptions);
  85. return this.queryCache.build(this, defaultedOptions).setData(data, { ...options,
  86. manual: true
  87. });
  88. }
  89. setQueriesData(queryKeyOrFilters, updater, options) {
  90. return notifyManager.batch(() => this.getQueryCache().findAll(queryKeyOrFilters).map(({
  91. queryKey
  92. }) => [queryKey, this.setQueryData(queryKey, updater, options)]));
  93. }
  94. getQueryState(queryKey, filters) {
  95. var _this$queryCache$find2;
  96. return (_this$queryCache$find2 = this.queryCache.find(queryKey, filters)) == null ? void 0 : _this$queryCache$find2.state;
  97. }
  98. removeQueries(arg1, arg2) {
  99. const [filters] = parseFilterArgs(arg1, arg2);
  100. const queryCache = this.queryCache;
  101. notifyManager.batch(() => {
  102. queryCache.findAll(filters).forEach(query => {
  103. queryCache.remove(query);
  104. });
  105. });
  106. }
  107. resetQueries(arg1, arg2, arg3) {
  108. const [filters, options] = parseFilterArgs(arg1, arg2, arg3);
  109. const queryCache = this.queryCache;
  110. const refetchFilters = {
  111. type: 'active',
  112. ...filters
  113. };
  114. return notifyManager.batch(() => {
  115. queryCache.findAll(filters).forEach(query => {
  116. query.reset();
  117. });
  118. return this.refetchQueries(refetchFilters, options);
  119. });
  120. }
  121. cancelQueries(arg1, arg2, arg3) {
  122. const [filters, cancelOptions = {}] = parseFilterArgs(arg1, arg2, arg3);
  123. if (typeof cancelOptions.revert === 'undefined') {
  124. cancelOptions.revert = true;
  125. }
  126. const promises = notifyManager.batch(() => this.queryCache.findAll(filters).map(query => query.cancel(cancelOptions)));
  127. return Promise.all(promises).then(noop).catch(noop);
  128. }
  129. invalidateQueries(arg1, arg2, arg3) {
  130. const [filters, options] = parseFilterArgs(arg1, arg2, arg3);
  131. return notifyManager.batch(() => {
  132. var _ref, _filters$refetchType;
  133. this.queryCache.findAll(filters).forEach(query => {
  134. query.invalidate();
  135. });
  136. if (filters.refetchType === 'none') {
  137. return Promise.resolve();
  138. }
  139. const refetchFilters = { ...filters,
  140. type: (_ref = (_filters$refetchType = filters.refetchType) != null ? _filters$refetchType : filters.type) != null ? _ref : 'active'
  141. };
  142. return this.refetchQueries(refetchFilters, options);
  143. });
  144. }
  145. refetchQueries(arg1, arg2, arg3) {
  146. const [filters, options] = parseFilterArgs(arg1, arg2, arg3);
  147. const promises = notifyManager.batch(() => this.queryCache.findAll(filters).filter(query => !query.isDisabled()).map(query => {
  148. var _options$cancelRefetc;
  149. return query.fetch(undefined, { ...options,
  150. cancelRefetch: (_options$cancelRefetc = options == null ? void 0 : options.cancelRefetch) != null ? _options$cancelRefetc : true,
  151. meta: {
  152. refetchPage: filters.refetchPage
  153. }
  154. });
  155. }));
  156. let promise = Promise.all(promises).then(noop);
  157. if (!(options != null && options.throwOnError)) {
  158. promise = promise.catch(noop);
  159. }
  160. return promise;
  161. }
  162. fetchQuery(arg1, arg2, arg3) {
  163. const parsedOptions = parseQueryArgs(arg1, arg2, arg3);
  164. const defaultedOptions = this.defaultQueryOptions(parsedOptions); // https://github.com/tannerlinsley/react-query/issues/652
  165. if (typeof defaultedOptions.retry === 'undefined') {
  166. defaultedOptions.retry = false;
  167. }
  168. const query = this.queryCache.build(this, defaultedOptions);
  169. return query.isStaleByTime(defaultedOptions.staleTime) ? query.fetch(defaultedOptions) : Promise.resolve(query.state.data);
  170. }
  171. prefetchQuery(arg1, arg2, arg3) {
  172. return this.fetchQuery(arg1, arg2, arg3).then(noop).catch(noop);
  173. }
  174. fetchInfiniteQuery(arg1, arg2, arg3) {
  175. const parsedOptions = parseQueryArgs(arg1, arg2, arg3);
  176. parsedOptions.behavior = infiniteQueryBehavior();
  177. return this.fetchQuery(parsedOptions);
  178. }
  179. prefetchInfiniteQuery(arg1, arg2, arg3) {
  180. return this.fetchInfiniteQuery(arg1, arg2, arg3).then(noop).catch(noop);
  181. }
  182. resumePausedMutations() {
  183. return this.mutationCache.resumePausedMutations();
  184. }
  185. getQueryCache() {
  186. return this.queryCache;
  187. }
  188. getMutationCache() {
  189. return this.mutationCache;
  190. }
  191. getLogger() {
  192. return this.logger;
  193. }
  194. getDefaultOptions() {
  195. return this.defaultOptions;
  196. }
  197. setDefaultOptions(options) {
  198. this.defaultOptions = options;
  199. }
  200. setQueryDefaults(queryKey, options) {
  201. const result = this.queryDefaults.find(x => hashQueryKey(queryKey) === hashQueryKey(x.queryKey));
  202. if (result) {
  203. result.defaultOptions = options;
  204. } else {
  205. this.queryDefaults.push({
  206. queryKey,
  207. defaultOptions: options
  208. });
  209. }
  210. }
  211. getQueryDefaults(queryKey) {
  212. if (!queryKey) {
  213. return undefined;
  214. } // Get the first matching defaults
  215. const firstMatchingDefaults = this.queryDefaults.find(x => partialMatchKey(queryKey, x.queryKey)); // Additional checks and error in dev mode
  216. if (process.env.NODE_ENV !== 'production') {
  217. // Retrieve all matching defaults for the given key
  218. const matchingDefaults = this.queryDefaults.filter(x => partialMatchKey(queryKey, x.queryKey)); // It is ok not having defaults, but it is error prone to have more than 1 default for a given key
  219. if (matchingDefaults.length > 1) {
  220. this.logger.error("[QueryClient] Several query defaults match with key '" + JSON.stringify(queryKey) + "'. The first matching query defaults are used. Please check how query defaults are registered. Order does matter here. cf. https://react-query.tanstack.com/reference/QueryClient#queryclientsetquerydefaults.");
  221. }
  222. }
  223. return firstMatchingDefaults == null ? void 0 : firstMatchingDefaults.defaultOptions;
  224. }
  225. setMutationDefaults(mutationKey, options) {
  226. const result = this.mutationDefaults.find(x => hashQueryKey(mutationKey) === hashQueryKey(x.mutationKey));
  227. if (result) {
  228. result.defaultOptions = options;
  229. } else {
  230. this.mutationDefaults.push({
  231. mutationKey,
  232. defaultOptions: options
  233. });
  234. }
  235. }
  236. getMutationDefaults(mutationKey) {
  237. if (!mutationKey) {
  238. return undefined;
  239. } // Get the first matching defaults
  240. const firstMatchingDefaults = this.mutationDefaults.find(x => partialMatchKey(mutationKey, x.mutationKey)); // Additional checks and error in dev mode
  241. if (process.env.NODE_ENV !== 'production') {
  242. // Retrieve all matching defaults for the given key
  243. const matchingDefaults = this.mutationDefaults.filter(x => partialMatchKey(mutationKey, x.mutationKey)); // It is ok not having defaults, but it is error prone to have more than 1 default for a given key
  244. if (matchingDefaults.length > 1) {
  245. this.logger.error("[QueryClient] Several mutation defaults match with key '" + JSON.stringify(mutationKey) + "'. The first matching mutation defaults are used. Please check how mutation defaults are registered. Order does matter here. cf. https://react-query.tanstack.com/reference/QueryClient#queryclientsetmutationdefaults.");
  246. }
  247. }
  248. return firstMatchingDefaults == null ? void 0 : firstMatchingDefaults.defaultOptions;
  249. }
  250. defaultQueryOptions(options) {
  251. if (options != null && options._defaulted) {
  252. return options;
  253. }
  254. const defaultedOptions = { ...this.defaultOptions.queries,
  255. ...this.getQueryDefaults(options == null ? void 0 : options.queryKey),
  256. ...options,
  257. _defaulted: true
  258. };
  259. if (!defaultedOptions.queryHash && defaultedOptions.queryKey) {
  260. defaultedOptions.queryHash = hashQueryKeyByOptions(defaultedOptions.queryKey, defaultedOptions);
  261. } // dependent default values
  262. if (typeof defaultedOptions.refetchOnReconnect === 'undefined') {
  263. defaultedOptions.refetchOnReconnect = defaultedOptions.networkMode !== 'always';
  264. }
  265. if (typeof defaultedOptions.useErrorBoundary === 'undefined') {
  266. defaultedOptions.useErrorBoundary = !!defaultedOptions.suspense;
  267. }
  268. return defaultedOptions;
  269. }
  270. defaultMutationOptions(options) {
  271. if (options != null && options._defaulted) {
  272. return options;
  273. }
  274. return { ...this.defaultOptions.mutations,
  275. ...this.getMutationDefaults(options == null ? void 0 : options.mutationKey),
  276. ...options,
  277. _defaulted: true
  278. };
  279. }
  280. clear() {
  281. this.queryCache.clear();
  282. this.mutationCache.clear();
  283. }
  284. }
  285. export { QueryClient };
  286. //# sourceMappingURL=queryClient.mjs.map