版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

1233 строки
32 KiB

  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. const GLOBAL_OPTIONS = {};
  5. const GLOBAL_OPTIONS_PROVIDE_KEY = Symbol('GLOBAL_OPTIONS_PROVIDE_KEY');
  6. const setGlobalOptions = config => {
  7. Object.keys(config).forEach(key => {
  8. GLOBAL_OPTIONS[key] = config[key];
  9. });
  10. };
  11. const getGlobalOptions = () => {
  12. return GLOBAL_OPTIONS;
  13. };
  14. const RequestConfig = vue.defineComponent({
  15. name: 'RequestConfig',
  16. props: {
  17. config: {
  18. type: Object,
  19. required: true
  20. }
  21. },
  22. setup(props, {
  23. slots
  24. }) {
  25. const {
  26. config
  27. } = props;
  28. vue.provide(GLOBAL_OPTIONS_PROVIDE_KEY, config);
  29. return () => {
  30. var _slots$default;
  31. return (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots);
  32. };
  33. }
  34. });
  35. const objectToString = Object.prototype.toString;
  36. const toTypeString = val => objectToString.call(val);
  37. const isString = val => toTypeString(val) === '[object String]';
  38. const isPlainObject = val => toTypeString(val) === '[object Object]';
  39. const isArray = val => Array.isArray(val);
  40. const isObject = val => val !== null && typeof val === 'object';
  41. const isPromise = fn => isObject(fn) && isFunction(fn.then) && isFunction(fn.catch);
  42. const isFunction = fn => fn instanceof Function;
  43. const isNil = val => val === null || val === undefined;
  44. const isServer = typeof window === 'undefined';
  45. const isDocumentVisibility = () => {
  46. var _window, _window$document;
  47. return !isServer && ((_window = window) === null || _window === void 0 ? void 0 : (_window$document = _window.document) === null || _window$document === void 0 ? void 0 : _window$document.visibilityState) === 'visible';
  48. };
  49. const isOnline = () => {
  50. var _ref, _window2, _window2$navigator;
  51. return (_ref = !isServer && ((_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$navigator = _window2.navigator) === null || _window2$navigator === void 0 ? void 0 : _window2$navigator.onLine)) !== null && _ref !== void 0 ? _ref : true;
  52. };
  53. const unRefObject = val => {
  54. const obj = {};
  55. Object.keys(val).forEach(key => {
  56. obj[key] = vue.unref(val[key]);
  57. });
  58. return obj;
  59. };
  60. const resolvedPromise = Promise.resolve(null);
  61. const requestProxy = async (...args) => {
  62. const res = await fetch(...args);
  63. if (res.ok) {
  64. return res.json();
  65. }
  66. throw new Error(res.statusText);
  67. };
  68. const get = (source, path, defaultValue = undefined) => {
  69. // a[3].b -> a.3.b
  70. const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.');
  71. let result = source;
  72. for (const p of paths) {
  73. result = Object(result)[p];
  74. if (result === undefined) {
  75. return defaultValue;
  76. }
  77. }
  78. return result;
  79. };
  80. function omit(object, keys) {
  81. const result = Object.assign({}, object);
  82. for (const key of keys) {
  83. delete result[key];
  84. }
  85. return result;
  86. }
  87. const warning = (message, throwError = false) => {
  88. const msg = `Warning: [vue-request] ${message}`;
  89. if (throwError) {
  90. return new Error(msg);
  91. } else {
  92. console.error(msg);
  93. }
  94. };
  95. const limitTrigger = (fn, timeInterval) => {
  96. let running = false;
  97. return (...args) => {
  98. if (running) return;
  99. running = true;
  100. fn(...args);
  101. setTimeout(() => {
  102. running = false;
  103. }, timeInterval);
  104. };
  105. };
  106. var _window;
  107. const FOCUS_LISTENER = new Set();
  108. const VISIBLE_LISTENER = new Set();
  109. const RECONNECT_LISTENER = new Set();
  110. const subscriber = (listenerType, event) => {
  111. let listeners;
  112. switch (listenerType) {
  113. case 'FOCUS_LISTENER':
  114. listeners = FOCUS_LISTENER;
  115. break;
  116. case 'RECONNECT_LISTENER':
  117. listeners = RECONNECT_LISTENER;
  118. break;
  119. case 'VISIBLE_LISTENER':
  120. listeners = VISIBLE_LISTENER;
  121. break;
  122. }
  123. if (listeners.has(event)) return;
  124. listeners.add(event);
  125. return () => {
  126. listeners.delete(event);
  127. };
  128. };
  129. const observer = listeners => {
  130. listeners.forEach(event => {
  131. event();
  132. });
  133. };
  134. /* istanbul ignore else */
  135. if (!isServer && (_window = window) !== null && _window !== void 0 && _window.addEventListener) {
  136. window.addEventListener('visibilitychange', () => {
  137. /* istanbul ignore else */
  138. if (isDocumentVisibility()) {
  139. observer(VISIBLE_LISTENER);
  140. }
  141. }, false);
  142. window.addEventListener('focus', () => observer(FOCUS_LISTENER), false);
  143. window.addEventListener('online', () => observer(RECONNECT_LISTENER), false);
  144. }
  145. /**
  146. * source by `lodash`
  147. * https://github.com/lodash/lodash.git
  148. */
  149. function debounce(func, wait, options) {
  150. let lastArgs, lastThis, maxWait, result, timerId, lastCallTime;
  151. let lastInvokeTime = 0;
  152. let leading = false;
  153. let maxing = false;
  154. let trailing = true; // Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
  155. const useRAF = !wait && wait !== 0 && typeof window.requestAnimationFrame === 'function';
  156. if (typeof func !== 'function') {
  157. throw new TypeError('Expected a function');
  158. }
  159. wait = +wait || 0;
  160. if (isObject(options)) {
  161. leading = !!options.leading;
  162. maxing = 'maxWait' in options;
  163. maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait;
  164. trailing = 'trailing' in options ? !!options.trailing : trailing;
  165. }
  166. function invokeFunc(time) {
  167. const args = lastArgs;
  168. const thisArg = lastThis;
  169. lastArgs = lastThis = undefined;
  170. lastInvokeTime = time;
  171. result = func.apply(thisArg, args);
  172. return result;
  173. }
  174. function startTimer(pendingFunc, wait) {
  175. if (useRAF) {
  176. window.cancelAnimationFrame(timerId);
  177. return window.requestAnimationFrame(pendingFunc);
  178. }
  179. return setTimeout(pendingFunc, wait);
  180. }
  181. function cancelTimer(id) {
  182. if (useRAF) {
  183. return window.cancelAnimationFrame(id);
  184. }
  185. clearTimeout(id);
  186. }
  187. function leadingEdge(time) {
  188. // Reset any `maxWait` timer.
  189. lastInvokeTime = time; // Start the timer for the trailing edge.
  190. timerId = startTimer(timerExpired, wait); // Invoke the leading edge.
  191. return leading ? invokeFunc(time) : result;
  192. }
  193. function remainingWait(time) {
  194. const timeSinceLastCall = time - lastCallTime;
  195. const timeSinceLastInvoke = time - lastInvokeTime;
  196. const timeWaiting = wait - timeSinceLastCall;
  197. return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
  198. }
  199. function shouldInvoke(time) {
  200. const timeSinceLastCall = time - lastCallTime;
  201. const timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
  202. // trailing edge, the system time has gone backwards and we're treating
  203. // it as the trailing edge, or we've hit the `maxWait` limit.
  204. return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
  205. }
  206. function timerExpired() {
  207. const time = Date.now();
  208. if (shouldInvoke(time)) {
  209. return trailingEdge(time);
  210. } // Restart the timer.
  211. timerId = startTimer(timerExpired, remainingWait(time));
  212. }
  213. function trailingEdge(time) {
  214. timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been
  215. // debounced at least once.
  216. if (trailing && lastArgs) {
  217. return invokeFunc(time);
  218. }
  219. lastArgs = lastThis = undefined;
  220. return result;
  221. }
  222. function cancel() {
  223. if (timerId !== undefined) {
  224. cancelTimer(timerId);
  225. }
  226. lastInvokeTime = 0;
  227. lastArgs = lastCallTime = lastThis = timerId = undefined;
  228. }
  229. function flush() {
  230. return timerId === undefined ? result : trailingEdge(Date.now());
  231. }
  232. function pending() {
  233. return timerId !== undefined;
  234. }
  235. function debounced(...args) {
  236. const time = Date.now();
  237. const isInvoking = shouldInvoke(time);
  238. lastArgs = args;
  239. lastThis = this;
  240. lastCallTime = time;
  241. if (isInvoking) {
  242. if (timerId === undefined) {
  243. return leadingEdge(lastCallTime);
  244. }
  245. if (maxing) {
  246. // Handle invocations in a tight loop.
  247. timerId = startTimer(timerExpired, wait);
  248. return invokeFunc(lastCallTime);
  249. }
  250. }
  251. if (timerId === undefined) {
  252. timerId = startTimer(timerExpired, wait);
  253. }
  254. return result;
  255. }
  256. debounced.cancel = cancel;
  257. debounced.flush = flush;
  258. debounced.pending = pending;
  259. return debounced;
  260. }
  261. function baseMerge(origin, target) {
  262. for (const key in target) {
  263. if (target[key] === undefined) {
  264. continue;
  265. }
  266. if (!isObject(target[key]) || // `target[key]` is not an object
  267. !isObject(origin[key]) || // `target[key]` is not an object
  268. !(key in origin) // `key` is not in the origin object
  269. ) {
  270. origin[key] = target[key];
  271. continue;
  272. }
  273. if (isPlainObject(target[key]) || isArray(target[key])) {
  274. baseMerge(origin[key], target[key]);
  275. }
  276. }
  277. }
  278. function merge(origin, ...others) {
  279. const result = Object.assign({}, origin);
  280. if (!others.length) return result;
  281. for (const item of others) {
  282. baseMerge(result, item);
  283. }
  284. return result;
  285. }
  286. /**
  287. * source by `lodash`
  288. * https://github.com/lodash/lodash.git
  289. */
  290. function throttle(func, wait, options) {
  291. let leading = true;
  292. let trailing = true;
  293. if (typeof func !== 'function') {
  294. throw new TypeError('Expected a function');
  295. }
  296. if (isObject(options)) {
  297. leading = 'leading' in options ? !!options.leading : leading;
  298. trailing = 'trailing' in options ? !!options.trailing : trailing;
  299. }
  300. return debounce(func, wait, {
  301. leading,
  302. trailing,
  303. maxWait: wait
  304. });
  305. }
  306. const setStateBind = (oldState, publicCb) => {
  307. return newState => {
  308. Object.keys(newState).forEach(key => {
  309. oldState[key].value = newState[key];
  310. });
  311. publicCb.forEach(fun => fun(oldState));
  312. };
  313. };
  314. const createQuery = (query, config, initialState) => {
  315. var _initialState$loading, _initialState$data, _initialState$params;
  316. const {
  317. initialAutoRunFlag,
  318. initialData,
  319. loadingDelay,
  320. pollingInterval,
  321. debounceInterval,
  322. debounceOptions,
  323. throttleInterval,
  324. throttleOptions,
  325. pollingWhenHidden,
  326. pollingWhenOffline,
  327. errorRetryCount,
  328. errorRetryInterval,
  329. stopPollingWhenHiddenOrOffline,
  330. refreshOnWindowFocus,
  331. refocusTimespan,
  332. updateCache,
  333. formatResult,
  334. onSuccess,
  335. onError,
  336. onBefore,
  337. onAfter
  338. } = config;
  339. const retriedCount = vue.ref(0);
  340. const loading = vue.ref((_initialState$loading = initialState === null || initialState === void 0 ? void 0 : initialState.loading) !== null && _initialState$loading !== void 0 ? _initialState$loading : false);
  341. const data = vue.ref((_initialState$data = initialState === null || initialState === void 0 ? void 0 : initialState.data) !== null && _initialState$data !== void 0 ? _initialState$data : initialData);
  342. const error = vue.ref(initialState === null || initialState === void 0 ? void 0 : initialState.error);
  343. const params = vue.ref((_initialState$params = initialState === null || initialState === void 0 ? void 0 : initialState.params) !== null && _initialState$params !== void 0 ? _initialState$params : []);
  344. const setState = setStateBind({
  345. loading,
  346. data,
  347. error,
  348. params
  349. }, [state => updateCache(state)]); // reset retried count
  350. const resetRetriedCount = () => {
  351. retriedCount.value = 0;
  352. };
  353. const count = vue.ref(0);
  354. const pollingTimer = vue.ref();
  355. const retryTimer = vue.ref();
  356. const delayLoadingTimer = vue.ref();
  357. const clearAllTimer = () => {
  358. // clear pollingTimer
  359. if (pollingTimer.value) {
  360. pollingTimer.value();
  361. } // clear delayLoadingTimer
  362. if (delayLoadingTimer.value) {
  363. delayLoadingTimer.value();
  364. } // clear retryTimer
  365. if (retryTimer.value) {
  366. retryTimer.value();
  367. }
  368. };
  369. const delayLoading = () => {
  370. let timerId;
  371. if (loadingDelay) {
  372. timerId = setTimeout(setState, loadingDelay, {
  373. loading: true
  374. });
  375. }
  376. return () => timerId && clearTimeout(timerId);
  377. };
  378. const polling = pollingFunc => {
  379. // if errorRetry is enabled, then skip this method
  380. if (error.value && errorRetryCount !== 0) return;
  381. let timerId;
  382. if (!isNil(pollingInterval) && pollingInterval >= 0) {
  383. if ((pollingWhenHidden || isDocumentVisibility()) && (pollingWhenOffline || isOnline())) {
  384. timerId = setTimeout(pollingFunc, pollingInterval);
  385. } else {
  386. // stop polling
  387. stopPollingWhenHiddenOrOffline.value = true;
  388. return;
  389. }
  390. }
  391. return () => timerId && clearTimeout(timerId);
  392. };
  393. const actualErrorRetryInterval = vue.computed(() => {
  394. if (errorRetryInterval) return errorRetryInterval;
  395. const baseTime = 1000;
  396. const minCoefficient = 1;
  397. const maxCoefficient = 9; // When retrying for the first time, in order to avoid the coefficient being 0
  398. // so replace 0 with 2, the coefficient range will become 1 - 2
  399. const coefficient = Math.floor(Math.random() * 2 ** Math.min(retriedCount.value, maxCoefficient) + minCoefficient);
  400. return baseTime * coefficient;
  401. });
  402. const errorRetryHooks = retryFunc => {
  403. let timerId;
  404. const isInfiniteRetry = errorRetryCount === -1;
  405. const hasRetryCount = retriedCount.value < errorRetryCount; // if errorRetryCount is -1, it will retry the request until it success
  406. if (error.value && (isInfiniteRetry || hasRetryCount)) {
  407. if (!isInfiniteRetry) retriedCount.value += 1;
  408. timerId = setTimeout(retryFunc, actualErrorRetryInterval.value);
  409. }
  410. return () => timerId && clearTimeout(timerId);
  411. };
  412. const _run = (...args) => {
  413. setState({
  414. loading: !loadingDelay,
  415. params: args
  416. });
  417. delayLoadingTimer.value = delayLoading();
  418. count.value += 1;
  419. const currentCount = count.value; // onBefore hooks
  420. onBefore === null || onBefore === void 0 ? void 0 : onBefore(args);
  421. return query(...args).then(res => {
  422. if (currentCount === count.value) {
  423. const formattedResult = formatResult ? formatResult(res) : res;
  424. setState({
  425. data: formattedResult,
  426. loading: false,
  427. error: undefined
  428. });
  429. if (onSuccess) {
  430. onSuccess(formattedResult, args);
  431. }
  432. resetRetriedCount();
  433. return formattedResult;
  434. }
  435. return resolvedPromise;
  436. }).catch(error => {
  437. if (currentCount === count.value) {
  438. setState({
  439. data: undefined,
  440. loading: false,
  441. error: error
  442. });
  443. if (onError) {
  444. onError(error, args);
  445. }
  446. console.error(error);
  447. }
  448. return resolvedPromise;
  449. }).finally(() => {
  450. if (currentCount === count.value) {
  451. // clear delayLoadingTimer
  452. delayLoadingTimer.value(); // retry
  453. retryTimer.value = errorRetryHooks(() => _run(...args)); // run for polling
  454. pollingTimer.value = polling(() => _run(...args)); // onAfter hooks
  455. onAfter === null || onAfter === void 0 ? void 0 : onAfter(args);
  456. }
  457. });
  458. };
  459. const debouncedRun = !isNil(debounceInterval) && debounce(_run, debounceInterval, debounceOptions);
  460. const throttledRun = !isNil(throttleInterval) && throttle(_run, throttleInterval, throttleOptions);
  461. const run = (...args) => {
  462. clearAllTimer(); // initial auto run should not debounce
  463. if (!initialAutoRunFlag.value && debouncedRun) {
  464. debouncedRun(...args);
  465. return resolvedPromise;
  466. }
  467. if (throttledRun) {
  468. throttledRun(...args);
  469. return resolvedPromise;
  470. }
  471. resetRetriedCount();
  472. return _run(...args);
  473. };
  474. const cancel = () => {
  475. count.value += 1;
  476. setState({
  477. loading: false
  478. });
  479. if (debouncedRun) {
  480. debouncedRun.cancel();
  481. }
  482. if (throttledRun) {
  483. throttledRun.cancel();
  484. }
  485. clearAllTimer();
  486. };
  487. const refresh = () => {
  488. return run(...params.value);
  489. };
  490. const mutate = x => {
  491. const mutateData = isFunction(x) ? x(data.value) : x;
  492. setState({
  493. data: mutateData
  494. });
  495. }; // collect subscribers, in order to unsubscribe when the component unmounted
  496. const unsubscribeList = [];
  497. const addUnsubscribeList = event => {
  498. event && unsubscribeList.push(event);
  499. };
  500. const rePolling = () => {
  501. if (stopPollingWhenHiddenOrOffline.value && (pollingWhenHidden || isDocumentVisibility()) && (pollingWhenOffline || isOnline())) {
  502. refresh();
  503. stopPollingWhenHiddenOrOffline.value = false;
  504. }
  505. }; // subscribe polling
  506. if (!pollingWhenHidden) {
  507. addUnsubscribeList(subscriber('VISIBLE_LISTENER', rePolling));
  508. } // subscribe online when pollingWhenOffline is false
  509. if (!pollingWhenOffline) {
  510. addUnsubscribeList(subscriber('RECONNECT_LISTENER', rePolling));
  511. }
  512. const limitRefresh = limitTrigger(refresh, refocusTimespan); // subscribe window focus or visible
  513. if (refreshOnWindowFocus) {
  514. addUnsubscribeList(subscriber('VISIBLE_LISTENER', limitRefresh));
  515. addUnsubscribeList(subscriber('FOCUS_LISTENER', limitRefresh));
  516. }
  517. const unmount = () => {
  518. unsubscribeList.forEach(unsubscribe => unsubscribe());
  519. };
  520. return {
  521. loading,
  522. data,
  523. error,
  524. params,
  525. run,
  526. cancel,
  527. refresh,
  528. mutate,
  529. unmount
  530. };
  531. };
  532. const CACHE_MAP = new Map();
  533. const getCache = cacheKey => {
  534. if (isNil(cacheKey)) return;
  535. const data = CACHE_MAP.get(cacheKey);
  536. if (!data) return;
  537. return {
  538. data: data.data,
  539. cacheTime: data.cacheTime
  540. };
  541. };
  542. const setCache = (cacheKey, data, cacheTime) => {
  543. const oldCache = CACHE_MAP.get(cacheKey);
  544. if (oldCache !== null && oldCache !== void 0 && oldCache.timer) {
  545. clearTimeout(oldCache.timer);
  546. }
  547. const timer = setTimeout(() => CACHE_MAP.delete(cacheKey), cacheTime);
  548. CACHE_MAP.set(cacheKey, {
  549. data,
  550. timer,
  551. cacheTime: new Date().getTime()
  552. });
  553. };
  554. const QUERY_DEFAULT_KEY = '__QUERY_DEFAULT_KEY__';
  555. function useAsyncQuery(query, options) {
  556. const injectedGlobalOptions = vue.inject(GLOBAL_OPTIONS_PROVIDE_KEY, {});
  557. const {
  558. cacheKey,
  559. defaultParams = [],
  560. manual = false,
  561. ready = vue.ref(true),
  562. refreshDeps = [],
  563. loadingDelay = 0,
  564. pollingWhenHidden = false,
  565. pollingWhenOffline = false,
  566. refreshOnWindowFocus = false,
  567. refocusTimespan = 5000,
  568. cacheTime = 600000,
  569. staleTime = 0,
  570. errorRetryCount = 0,
  571. errorRetryInterval = 0,
  572. queryKey,
  573. ...rest
  574. } = { ...getGlobalOptions(),
  575. ...injectedGlobalOptions,
  576. ...options
  577. };
  578. const stopPollingWhenHiddenOrOffline = vue.ref(false); // skip debounce when initail run
  579. const initialAutoRunFlag = vue.ref(false);
  580. const updateCache = state => {
  581. var _getCache, _queryKey;
  582. if (!cacheKey) return;
  583. const cacheData = (_getCache = getCache(cacheKey)) === null || _getCache === void 0 ? void 0 : _getCache.data;
  584. const cacheQueries = cacheData === null || cacheData === void 0 ? void 0 : cacheData.queries;
  585. const queryData = unRefObject(state);
  586. const currentQueryKey = (_queryKey = queryKey === null || queryKey === void 0 ? void 0 : queryKey(...state.params.value)) !== null && _queryKey !== void 0 ? _queryKey : QUERY_DEFAULT_KEY;
  587. setCache(cacheKey, {
  588. queries: { ...cacheQueries,
  589. [currentQueryKey]: { ...(cacheQueries === null || cacheQueries === void 0 ? void 0 : cacheQueries[currentQueryKey]),
  590. ...queryData
  591. }
  592. },
  593. latestQueriesKey: currentQueryKey
  594. }, cacheTime);
  595. };
  596. const config = {
  597. initialAutoRunFlag,
  598. loadingDelay,
  599. pollingWhenHidden,
  600. pollingWhenOffline,
  601. stopPollingWhenHiddenOrOffline,
  602. cacheKey,
  603. errorRetryCount,
  604. errorRetryInterval,
  605. refreshOnWindowFocus,
  606. refocusTimespan,
  607. updateCache,
  608. ...omit(rest, ['pagination', 'listKey'])
  609. };
  610. const loading = vue.ref(false);
  611. const data = vue.ref();
  612. const error = vue.ref();
  613. const params = vue.ref();
  614. const queries = vue.reactive({
  615. [QUERY_DEFAULT_KEY]: vue.reactive(createQuery(query, config))
  616. });
  617. const latestQueriesKey = vue.ref(QUERY_DEFAULT_KEY);
  618. const latestQuery = vue.computed(() => {
  619. var _queries$latestQuerie;
  620. return (_queries$latestQuerie = queries[latestQueriesKey.value]) !== null && _queries$latestQuerie !== void 0 ? _queries$latestQuerie : {};
  621. }); // sync state
  622. vue.watch(latestQuery, queryData => {
  623. loading.value = queryData.loading;
  624. data.value = queryData.data;
  625. error.value = queryData.error;
  626. params.value = queryData.params;
  627. }, {
  628. immediate: true,
  629. deep: true
  630. }); // init queries from cache
  631. if (cacheKey) {
  632. var _cache$data;
  633. const cache = getCache(cacheKey);
  634. if (cache !== null && cache !== void 0 && (_cache$data = cache.data) !== null && _cache$data !== void 0 && _cache$data.queries) {
  635. Object.keys(cache.data.queries).forEach(key => {
  636. const cacheQuery = cache.data.queries[key];
  637. queries[key] = vue.reactive(createQuery(query, config, {
  638. loading: cacheQuery.loading,
  639. params: cacheQuery.params,
  640. data: cacheQuery.data,
  641. error: cacheQuery.error
  642. }));
  643. });
  644. /* istanbul ignore else */
  645. if (cache.data.latestQueriesKey) {
  646. latestQueriesKey.value = cache.data.latestQueriesKey;
  647. }
  648. }
  649. }
  650. const tempReadyParams = vue.ref();
  651. const hasTriggerReady = vue.ref(false);
  652. const run = (...args) => {
  653. var _queryKey2;
  654. if (!ready.value && !hasTriggerReady.value) {
  655. tempReadyParams.value = args;
  656. return resolvedPromise;
  657. }
  658. const newKey = (_queryKey2 = queryKey === null || queryKey === void 0 ? void 0 : queryKey(...args)) !== null && _queryKey2 !== void 0 ? _queryKey2 : QUERY_DEFAULT_KEY;
  659. if (!queries[newKey]) {
  660. queries[newKey] = vue.reactive(createQuery(query, config));
  661. }
  662. latestQueriesKey.value = newKey;
  663. return latestQuery.value.run(...args);
  664. };
  665. const reset = () => {
  666. unmountQueries();
  667. latestQueriesKey.value = QUERY_DEFAULT_KEY;
  668. queries[QUERY_DEFAULT_KEY] = vue.reactive(createQuery(query, config));
  669. }; // unmount queries
  670. const unmountQueries = () => {
  671. Object.keys(queries).forEach(key => {
  672. queries[key].cancel();
  673. queries[key].unmount();
  674. delete queries[key];
  675. });
  676. };
  677. const cancel = () => latestQuery.value.cancel();
  678. const refresh = () => latestQuery.value.refresh();
  679. const mutate = arg => latestQuery.value.mutate(arg); // initial run
  680. if (!manual) {
  681. var _cache$data$queries;
  682. initialAutoRunFlag.value = true; // TODO: need refactor
  683. const cache = getCache(cacheKey);
  684. const cacheQueries = (_cache$data$queries = cache === null || cache === void 0 ? void 0 : cache.data.queries) !== null && _cache$data$queries !== void 0 ? _cache$data$queries : {};
  685. const isFresh = cache && (staleTime === -1 || cache.cacheTime + staleTime > new Date().getTime());
  686. const hasCacheQueries = Object.keys(cacheQueries).length > 0;
  687. if (!isFresh) {
  688. if (hasCacheQueries) {
  689. Object.keys(queries).forEach(key => {
  690. var _queries$key;
  691. (_queries$key = queries[key]) === null || _queries$key === void 0 ? void 0 : _queries$key.refresh();
  692. });
  693. } else {
  694. run(...defaultParams);
  695. }
  696. }
  697. initialAutoRunFlag.value = false;
  698. } // watch ready
  699. const stopReady = vue.ref();
  700. stopReady.value = vue.watch(ready, val => {
  701. hasTriggerReady.value = true;
  702. if (val && tempReadyParams.value) {
  703. run(...tempReadyParams.value); // destroy current watch
  704. stopReady.value();
  705. }
  706. }, {
  707. flush: 'sync'
  708. }); // watch refreshDeps
  709. if (refreshDeps.length) {
  710. vue.watch(refreshDeps, () => {
  711. !manual && latestQuery.value.refresh();
  712. });
  713. }
  714. vue.onUnmounted(() => {
  715. unmountQueries();
  716. });
  717. return {
  718. loading,
  719. data,
  720. error,
  721. params,
  722. cancel,
  723. refresh,
  724. mutate,
  725. run,
  726. reset,
  727. queries
  728. };
  729. }
  730. const generateService = service => {
  731. return (...args) => {
  732. if (isFunction(service)) {
  733. return generateService(service(...args))();
  734. } else if (isPromise(service)) {
  735. return service;
  736. } else if (isPlainObject(service)) {
  737. const {
  738. url,
  739. ...rest
  740. } = service;
  741. return requestProxy(url, rest);
  742. } else if (isString(service)) {
  743. return requestProxy(service);
  744. } else {
  745. throw warning('Unknown service type', true);
  746. }
  747. };
  748. };
  749. function useLoadMore(service, options) {
  750. var _injectedGlobalOption;
  751. if (!isFunction(service)) {
  752. warning('useLoadMore only support function service');
  753. }
  754. const promiseQuery = generateService(service);
  755. const injectedGlobalOptions = vue.inject(GLOBAL_OPTIONS_PROVIDE_KEY, {});
  756. const {
  757. queryKey,
  758. isNoMore,
  759. listKey = 'list',
  760. ...restOptions
  761. } = Object.assign({
  762. listKey: (_injectedGlobalOption = injectedGlobalOptions.listKey) !== null && _injectedGlobalOption !== void 0 ? _injectedGlobalOption : getGlobalOptions().listKey
  763. }, options !== null && options !== void 0 ? options : {});
  764. if (queryKey) {
  765. warning('useLoadMore does not support concurrent request');
  766. }
  767. const refreshing = vue.ref(false);
  768. const loadingMore = vue.ref(false);
  769. const reloading = vue.ref(false);
  770. const initailIncreaseQueryKey = 0;
  771. const increaseQueryKey = vue.ref(initailIncreaseQueryKey);
  772. const {
  773. data,
  774. params,
  775. queries,
  776. run,
  777. reset,
  778. cancel: _cancel,
  779. ...rest
  780. } = useAsyncQuery(promiseQuery, { ...restOptions,
  781. onSuccess: (...p) => {
  782. var _restOptions$onSucces;
  783. loadingMore.value = false;
  784. increaseQueryKey.value++;
  785. restOptions === null || restOptions === void 0 ? void 0 : (_restOptions$onSucces = restOptions.onSuccess) === null || _restOptions$onSucces === void 0 ? void 0 : _restOptions$onSucces.call(restOptions, ...p);
  786. },
  787. onError: (...p) => {
  788. var _restOptions$onError;
  789. loadingMore.value = false;
  790. restOptions === null || restOptions === void 0 ? void 0 : (_restOptions$onError = restOptions.onError) === null || _restOptions$onError === void 0 ? void 0 : _restOptions$onError.call(restOptions, ...p);
  791. },
  792. queryKey: () => String(increaseQueryKey.value)
  793. });
  794. const latestData = vue.ref(data.value);
  795. vue.watchEffect(() => {
  796. if (data.value !== undefined) {
  797. latestData.value = data.value;
  798. }
  799. });
  800. const noMore = vue.computed(() => {
  801. return isNoMore && isFunction(isNoMore) ? isNoMore(latestData.value) : false;
  802. });
  803. const dataList = vue.computed(() => {
  804. let list = [];
  805. Object.values(queries).forEach(h => {
  806. const dataList = get(h.data, listKey);
  807. if (dataList && Array.isArray(dataList)) {
  808. list = list.concat(dataList);
  809. }
  810. });
  811. return list;
  812. });
  813. const loadMore = () => {
  814. if (noMore.value) {
  815. return;
  816. }
  817. loadingMore.value = true;
  818. const [, ...restParams] = params.value;
  819. const mergerParams = [{
  820. dataList: dataList.value,
  821. data: latestData.value
  822. }, ...restParams];
  823. run(...mergerParams);
  824. };
  825. const unmountQueries = () => {
  826. Object.keys(queries).forEach(key => {
  827. if (key !== initailIncreaseQueryKey.toString()) {
  828. queries[key].cancel();
  829. queries[key].unmount();
  830. delete queries[key];
  831. }
  832. });
  833. };
  834. const refresh = async () => {
  835. refreshing.value = true;
  836. const latestKey = increaseQueryKey.value - 1;
  837. const key = latestKey < initailIncreaseQueryKey ? initailIncreaseQueryKey : latestKey;
  838. latestData.value = queries[key].data;
  839. increaseQueryKey.value = initailIncreaseQueryKey;
  840. const [, ...restParams] = params.value;
  841. const mergerParams = [undefined, ...restParams];
  842. await run(...mergerParams);
  843. unmountQueries();
  844. refreshing.value = false;
  845. };
  846. const reload = async () => {
  847. reloading.value = true;
  848. reset();
  849. increaseQueryKey.value = initailIncreaseQueryKey;
  850. latestData.value = undefined;
  851. const [, ...restParams] = params.value;
  852. const mergerParams = [undefined, ...restParams];
  853. await run(...mergerParams);
  854. reloading.value = false;
  855. };
  856. const cancel = () => {
  857. _cancel();
  858. loadingMore.value = false;
  859. refreshing.value = false;
  860. };
  861. return {
  862. data: latestData,
  863. dataList: dataList,
  864. params,
  865. noMore,
  866. loadingMore,
  867. refreshing,
  868. reloading,
  869. run,
  870. reload,
  871. loadMore,
  872. reset,
  873. refresh,
  874. cancel,
  875. ...omit(rest, ['refresh', 'mutate'])
  876. };
  877. }
  878. function usePagination(service, options) {
  879. var _getGlobalOptions$pag, _injectedGlobalOption;
  880. const promiseQuery = generateService(service);
  881. const defaultOptions = {
  882. pagination: {
  883. currentKey: 'current',
  884. pageSizeKey: 'pageSize',
  885. totalKey: 'total',
  886. totalPageKey: 'totalPage'
  887. }
  888. };
  889. const injectedGlobalOptions = vue.inject(GLOBAL_OPTIONS_PROVIDE_KEY, {});
  890. const {
  891. pagination: {
  892. currentKey,
  893. pageSizeKey,
  894. totalKey,
  895. totalPageKey
  896. },
  897. queryKey,
  898. ...restOptions
  899. } = merge(defaultOptions, {
  900. pagination: (_getGlobalOptions$pag = getGlobalOptions().pagination) !== null && _getGlobalOptions$pag !== void 0 ? _getGlobalOptions$pag : {}
  901. }, {
  902. pagination: (_injectedGlobalOption = injectedGlobalOptions.pagination) !== null && _injectedGlobalOption !== void 0 ? _injectedGlobalOption : {}
  903. }, options !== null && options !== void 0 ? options : {});
  904. if (queryKey) {
  905. warning('usePagination does not support concurrent request');
  906. }
  907. const finallyOptions = merge({
  908. defaultParams: [{
  909. [currentKey]: 1,
  910. [pageSizeKey]: 10
  911. }]
  912. }, restOptions);
  913. const {
  914. data,
  915. params,
  916. queries,
  917. run,
  918. reset,
  919. ...rest
  920. } = useAsyncQuery(promiseQuery, finallyOptions);
  921. const paging = paginationParams => {
  922. const [oldPaginationParams, ...restParams] = params.value;
  923. const newPaginationParams = { ...oldPaginationParams,
  924. ...paginationParams
  925. };
  926. const mergerParams = [newPaginationParams, ...restParams];
  927. run(...mergerParams);
  928. }; // changeCurrent change current page (current: number) => void
  929. const changeCurrent = current => {
  930. paging({
  931. [currentKey]: current
  932. });
  933. }; // changePageSize change pageSize (pageSize: number) => void
  934. const changePageSize = pageSize => {
  935. paging({
  936. [pageSizeKey]: pageSize
  937. });
  938. }; // changePagination change current and pageSize (current: number, pageSize: number) => void
  939. const changePagination = (current, pageSize) => {
  940. paging({
  941. [currentKey]: current,
  942. [pageSizeKey]: pageSize
  943. });
  944. };
  945. const reloading = vue.ref(false);
  946. const reload = async () => {
  947. const {
  948. defaultParams,
  949. manual
  950. } = finallyOptions;
  951. reset();
  952. if (!manual) {
  953. reloading.value = true;
  954. await run(...defaultParams);
  955. reloading.value = false;
  956. }
  957. };
  958. const total = vue.computed(() => get(data.value, totalKey, 0));
  959. const current = vue.computed({
  960. get: () => {
  961. var _params$value$0$curre, _params$value$;
  962. return (_params$value$0$curre = (_params$value$ = params.value[0]) === null || _params$value$ === void 0 ? void 0 : _params$value$[currentKey]) !== null && _params$value$0$curre !== void 0 ? _params$value$0$curre : finallyOptions.defaultParams[0][currentKey];
  963. },
  964. set: val => {
  965. changeCurrent(val);
  966. }
  967. });
  968. const pageSize = vue.computed({
  969. get: () => {
  970. var _params$value$0$pageS, _params$value$2;
  971. return (_params$value$0$pageS = (_params$value$2 = params.value[0]) === null || _params$value$2 === void 0 ? void 0 : _params$value$2[pageSizeKey]) !== null && _params$value$0$pageS !== void 0 ? _params$value$0$pageS : finallyOptions.defaultParams[0][pageSizeKey];
  972. },
  973. set: val => {
  974. changePageSize(val);
  975. }
  976. });
  977. const totalPage = vue.computed(() => get(data.value, totalPageKey, Math.ceil(total.value / pageSize.value)));
  978. return {
  979. data,
  980. params,
  981. current,
  982. pageSize,
  983. total,
  984. totalPage,
  985. reloading,
  986. run,
  987. changeCurrent,
  988. changePageSize,
  989. changePagination,
  990. reload,
  991. ...rest
  992. };
  993. }
  994. function useRequest(service, options) {
  995. const promiseQuery = generateService(service);
  996. const {
  997. reset,
  998. run,
  999. ...rest
  1000. } = useAsyncQuery(promiseQuery, options !== null && options !== void 0 ? options : {});
  1001. const reloading = vue.ref(false);
  1002. const reload = async () => {
  1003. const {
  1004. defaultParams = [],
  1005. manual
  1006. } = options;
  1007. reset();
  1008. if (!manual) {
  1009. reloading.value = true;
  1010. await run(...defaultParams);
  1011. reloading.value = false;
  1012. }
  1013. };
  1014. return {
  1015. reload,
  1016. run,
  1017. reloading,
  1018. ...rest
  1019. };
  1020. }
  1021. exports.RequestConfig = RequestConfig;
  1022. exports.setGlobalOptions = setGlobalOptions;
  1023. exports.useLoadMore = useLoadMore;
  1024. exports.usePagination = usePagination;
  1025. exports.useRequest = useRequest;