diff --git a/shared/components/Provider.tsx b/shared/components/Provider.tsx
new file mode 100644
index 00000000..fb8fd7a6
--- /dev/null
+++ b/shared/components/Provider.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { QueryClient, QueryClientProvider } from 'react-query';
+
+const queryClient = new QueryClient();
+
+export const PawProvider: React.FC = React.memo((props) => {
+ return (
+
+ {props.children}
+
+ );
+});
+PawProvider.displayName = 'PawProvider';
diff --git a/shared/hooks/useCache.ts b/shared/hooks/useCache.ts
new file mode 100644
index 00000000..38d23614
--- /dev/null
+++ b/shared/hooks/useCache.ts
@@ -0,0 +1,17 @@
+import { useQuery } from 'react-query';
+import { fetchUserInfo, UserBaseInfo } from '../model/user';
+
+function buildCacheFactory(
+ scope: string,
+ fetcher: (id: string) => Promise
+) {
+ return (id: string): T | Record => {
+ const { data } = useQuery([scope, id], () => fetcher(id));
+ return data ?? {};
+ };
+}
+
+export const useUserInfo = buildCacheFactory(
+ 'user',
+ fetchUserInfo
+);
diff --git a/shared/index.tsx b/shared/index.tsx
index 092d3966..41d761ce 100644
--- a/shared/index.tsx
+++ b/shared/index.tsx
@@ -14,6 +14,7 @@ export type {
export { regField } from './components/FastForm/field';
export { regFormContainer } from './components/FastForm/container';
export type { FastFormContainerComponent } from './components/FastForm/container';
+export { PawProvider } from './components/Provider';
// i18n
export { t, setLanguage, useTranslation } from './i18n';
@@ -22,6 +23,7 @@ export { t, setLanguage, useTranslation } from './i18n';
export { useAsync } from './hooks/useAsync';
export { useAsyncFn } from './hooks/useAsyncFn';
export { useAsyncRequest } from './hooks/useAsyncRequest';
+export { useUserInfo } from './hooks/useCache';
export { useMountedState } from './hooks/useMountedState';
export { useRafState } from './hooks/useRafState';
@@ -54,10 +56,6 @@ export {
// redux
export { useAppSelector, useAppDispatch } from './redux/hooks/useAppSelector';
-export {
- useCachedUserInfo,
- useCachedUserInfoList,
-} from './redux/hooks/useReduxCache';
export { userActions } from './redux/slices';
export { setupRedux } from './redux/setup';
export { createStore } from './redux/store';
diff --git a/shared/package.json b/shared/package.json
index 9e4acd29..723679df 100644
--- a/shared/package.json
+++ b/shared/package.json
@@ -16,6 +16,7 @@
"lodash": "^4.17.21",
"react-i18next": "^11.11.0",
"react-native-storage": "npm:@trpgengine/react-native-storage@^1.0.1",
+ "react-query": "^3.18.1",
"react-redux": "^7.2.4",
"redux": "^4.1.0",
"str2int": "^1.0.0",
diff --git a/shared/redux/hooks/useReduxCache.ts b/shared/redux/hooks/useReduxCache.ts
deleted file mode 100644
index b4705071..00000000
--- a/shared/redux/hooks/useReduxCache.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import _get from 'lodash/get';
-import _set from 'lodash/set';
-import _isNil from 'lodash/isNil';
-import { useEffect, useMemo, useRef } from 'react';
-import { fetchUserInfo, UserBaseInfo } from '../../model/user';
-import { cacheActions } from '../slices';
-import type { CacheKey } from '../slices/cache';
-import { useAppDispatch, useAppSelector } from './useAppSelector';
-
-// 检查是否需要跳过处理
-const isSkipId = (id: string) =>
- _isNil(id) ||
- id === '' ||
- typeof id !== 'string' ||
- id.toString().startsWith('_');
-
-interface CacheHookOptions {
- forceFetch?: boolean;
-}
-
-type GetCacheDataFn = (id: string) => Promise;
-
-function reduxHookCacheFactory(
- cacheScope: CacheKey,
- getCacheData: GetCacheDataFn
-) {
- const isFetchingDataIdQueue: string[] = []; // 正在请求的id列表
-
- return function useReduxCache(
- id: string,
- options?: CacheHookOptions
- ): Partial {
- const data = useAppSelector(
- (state) => _get(state, ['cache', cacheScope, id]) as any
- );
- const dispatch = useAppDispatch();
- const forceFetchRef = useRef(options?.forceFetch ?? false);
-
- useEffect(() => {
- if ((_isNil(data) || forceFetchRef.current === true) && !isSkipId(id)) {
- // 如果没有数据或设置了强制重新获取 且 不是内置的UUID
- // 从服务端获取缓存信息
- if (isFetchingDataIdQueue.indexOf(id) === -1) {
- // 没有正在获取缓存信息
- console.log(`缓存[${cacheScope}: ${id}]不存在, 自动获取`);
-
- getCacheData(id).then((data) => {
- // 从列表中移除
- const index = isFetchingDataIdQueue.indexOf(id);
- if (index !== -1) {
- isFetchingDataIdQueue.splice(index, 1);
- }
- forceFetchRef.current = false; // 不论怎么样都置为false 表示已经获取过了
-
- dispatch(
- cacheActions.setCache({
- scope: cacheScope,
- id,
- data,
- })
- );
- });
-
- isFetchingDataIdQueue.push(id);
- }
- }
- }, [data]);
-
- return data ?? {};
- };
-}
-
-export const useCachedUserInfo = reduxHookCacheFactory(
- 'user',
- (userId) => fetchUserInfo(userId)
-);
-
-/**
- * redux 的批量获取hooks的构造器
- * 用于列表
- * @param cacheScope 缓存的域
- * @param getCacheDispatch 请求缓存的dispatch
- */
-function reduxHookCacheListFactory(
- cacheScope: CacheKey,
- getCacheData: GetCacheDataFn
-) {
- const isFetchingDataIdQueue: string[] = []; // 正在请求的UUID列表
-
- return function hook = Record>(
- idList: string[]
- ): R {
- const cacheList = useAppSelector(
- (state) => _get(state, ['cache', cacheScope]) as any
- );
- const dispatch = useAppDispatch();
-
- const resMap = useMemo(() => {
- const map = {} as R;
- for (const id of idList) {
- if (_isNil(cacheList[id]) && !isSkipId(id)) {
- // 如果没有数据则请求数据
- // 从服务端获取缓存信息
- if (isFetchingDataIdQueue.indexOf(id) === -1) {
- // 没有正在获取缓存信息
- console.log(`缓存[${cacheScope}: ${id}]不存在, 自动获取`);
- getCacheData(id).then((data) => {
- // 从列表中移除
- const index = isFetchingDataIdQueue.indexOf(id);
- if (index !== -1) {
- isFetchingDataIdQueue.splice(index, 1);
- }
-
- dispatch(
- cacheActions.setCache({
- scope: cacheScope,
- id,
- data,
- })
- );
- });
-
- isFetchingDataIdQueue.push(id);
- }
- continue;
- }
-
- // 加入返回的map中
- _set(map, id, cacheList[id]);
- }
-
- return map;
- }, [cacheList, idList.join(',')]);
-
- return resMap;
- };
-}
-export const useCachedUserInfoList = reduxHookCacheListFactory(
- 'user',
- (userId) => fetchUserInfo(userId)
-);
diff --git a/shared/redux/slices/cache.ts b/shared/redux/slices/cache.ts
deleted file mode 100644
index 3dcd8876..00000000
--- a/shared/redux/slices/cache.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-import type { UserBaseInfo } from '../../model/user';
-import _set from 'lodash/set';
-
-interface CacheState {
- user: Record;
-}
-
-export type CacheKey = keyof CacheState;
-
-const initialState: CacheState = { user: {} };
-
-const cacheSlice = createSlice({
- name: 'cache',
- initialState,
- reducers: {
- setCache(
- state,
- action: PayloadAction<{
- scope: CacheKey;
- id: string;
- data: unknown;
- }>
- ) {
- const { scope, id, data } = action.payload;
- _set(state, [scope, id], data);
- },
- },
-});
-
-export const cacheActions = cacheSlice.actions;
-export const cacheReducer = cacheSlice.reducer;
diff --git a/shared/redux/slices/index.ts b/shared/redux/slices/index.ts
index bba90e14..a6bd1dcc 100644
--- a/shared/redux/slices/index.ts
+++ b/shared/redux/slices/index.ts
@@ -1,13 +1,10 @@
import { combineReducers } from '@reduxjs/toolkit';
-import { cacheReducer } from './cache';
import { userReducer } from './user';
export const appReducer = combineReducers({
- cache: cacheReducer,
user: userReducer,
});
export type AppState = ReturnType;
-export { cacheActions } from './cache';
export { userActions } from './user';
diff --git a/web/src/App.tsx b/web/src/App.tsx
index dd873229..036c2cbb 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom';
-import { useStorage } from 'pawchat-shared';
+import { PawProvider, useStorage } from 'pawchat-shared';
import clsx from 'clsx';
import { Loadable } from './components/Loadable';
@@ -13,7 +13,11 @@ const EntryRoute = Loadable(() =>
);
const AppProvider: React.FC = React.memo((props) => {
- return {props.children};
+ return (
+
+ {props.children}
+
+ );
});
AppProvider.displayName = 'AppProvider';
diff --git a/web/src/components/UserListItem.tsx b/web/src/components/UserListItem.tsx
index 678a9802..2b6bf1c8 100644
--- a/web/src/components/UserListItem.tsx
+++ b/web/src/components/UserListItem.tsx
@@ -3,7 +3,7 @@ import { Avatar } from './Avatar';
import _isNil from 'lodash/isNil';
import { Skeleton, Space } from 'antd';
// import { openUserProfile } from './modals/UserProfile';
-import { useCachedUserInfo } from 'pawchat-shared';
+import { useUserInfo } from 'pawchat-shared';
// const UserAvatar = styled(Avatar)`
// cursor: pointer !important;
@@ -21,7 +21,7 @@ interface UserListItemProps {
}
export const UserListItem: React.FC = React.memo((props) => {
const { actions = [] } = props;
- const userInfo = useCachedUserInfo(props.userId);
+ const userInfo = useUserInfo(props.userId);
const userName = userInfo.nickname;
const handleClick = useCallback(() => {
diff --git a/yarn.lock b/yarn.lock
index 6a8ab16c..ad7dc95a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -314,7 +314,7 @@
core-js-pure "^3.15.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.14.6"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
@@ -2097,6 +2097,11 @@ batch@0.6.1:
resolved "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
+big-integer@^1.6.16:
+ version "1.6.48"
+ resolved "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
+ integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==
+
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -2183,6 +2188,20 @@ braces@^3.0.1, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
+broadcast-channel@^3.4.1:
+ version "3.7.0"
+ resolved "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937"
+ integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ detect-node "^2.1.0"
+ js-sha3 "0.8.0"
+ microseconds "0.2.0"
+ nano-time "1.0.0"
+ oblivious-set "1.0.0"
+ rimraf "3.0.2"
+ unload "2.2.0"
+
browser-process-hrtime@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
@@ -3073,7 +3092,7 @@ detect-newline@^3.0.0:
resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
-detect-node@^2.0.4:
+detect-node@^2.0.4, detect-node@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
@@ -5533,6 +5552,11 @@ joycon@^3.0.1:
resolved "https://registry.npmjs.org/joycon/-/joycon-3.0.1.tgz#9074c9b08ccf37a6726ff74a18485f85efcaddaf"
integrity sha512-SJcJNBg32dGgxhPtM0wQqxqV0ax9k/9TaUskGDSJkSFSQOEWWvQ3zzWdGQRIUry2j1zA5+ReH13t0Mf3StuVZA==
+js-sha3@0.8.0:
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+ integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -5973,6 +5997,14 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
+match-sorter@^6.0.2:
+ version "6.3.0"
+ resolved "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.0.tgz#454a1b31ed218cddbce6231a0ecb5fdc549fed01"
+ integrity sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ remove-accents "0.4.2"
+
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -6050,6 +6082,11 @@ micromatch@^4.0.2, micromatch@^4.0.4:
braces "^3.0.1"
picomatch "^2.2.3"
+microseconds@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39"
+ integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==
+
mime-db@1.48.0, "mime-db@>= 1.43.0 < 2":
version "1.48.0"
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
@@ -6208,6 +6245,13 @@ nan@^2.12.1:
resolved "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
+nano-time@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef"
+ integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=
+ dependencies:
+ big-integer "^1.6.16"
+
nanoclone@^0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
@@ -6471,6 +6515,11 @@ object.values@^1.1.4:
define-properties "^1.1.3"
es-abstract "^1.18.2"
+oblivious-set@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566"
+ integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==
+
obuf@^1.0.0, obuf@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
@@ -7533,6 +7582,15 @@ react-is@^17.0.1:
opencollective "^1.0.3"
opencollective-postinstall "^2.0.2"
+react-query@^3.18.1:
+ version "3.18.1"
+ resolved "https://registry.npmjs.org/react-query/-/react-query-3.18.1.tgz#893b5475a7b4add099e007105317446f7a2cd310"
+ integrity sha512-17lv3pQxU9n+cB5acUv0/cxNTjo9q8G+RsedC6Ax4V9D8xEM7Q5xf9xAbCPdEhDrrnzPjTls9fQEABKRSi7OJA==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ broadcast-channel "^3.4.1"
+ match-sorter "^6.0.2"
+
react-redux@^7.2.4:
version "7.2.4"
resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
@@ -7720,6 +7778,11 @@ relateurl@^0.2.7:
resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
+remove-accents@0.4.2:
+ version "0.4.2"
+ resolved "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5"
+ integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=
+
remove-bom-buffer@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53"
@@ -7898,6 +7961,13 @@ reusify@^1.0.4:
resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
@@ -7905,13 +7975,6 @@ rimraf@^2.6.3:
dependencies:
glob "^7.1.3"
-rimraf@^3.0.0, rimraf@^3.0.2:
- version "3.0.2"
- resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
run-async@^2.2.0:
version "2.4.1"
resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@@ -9093,6 +9156,14 @@ universalify@^2.0.0:
resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+unload@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7"
+ integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==
+ dependencies:
+ "@babel/runtime" "^7.6.2"
+ detect-node "^2.0.4"
+
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"