From 32bed273c83f0593187110d2b08a0f9ec5a7efd7 Mon Sep 17 00:00:00 2001 From: Haishan Date: Wed, 1 Jul 2020 22:06:26 +0800 Subject: [PATCH] feat: support rule provider --- package.json | 17 +- src/api/rule-provider.ts | 74 +++++++ src/api/rules.js | 8 - src/api/rules.ts | 41 ++++ src/components/Button.module.css | 4 + src/components/Button.tsx | 9 +- src/components/RuleSearch.js | 6 - src/components/Rules.js | 115 ++++++++--- src/components/Rules.module.css | 22 ++- src/components/StateProvider.js | 5 + src/components/proxies/TextFilter.tsx | 21 +- .../rules/RuleProviderItem.module.css | 43 ++++ src/components/rules/RuleProviderItem.tsx | 71 +++++++ src/components/rules/TextFilter.tsx | 18 ++ src/hooks/useTextInput.ts | 23 +++ src/store/index.js | 2 - src/store/logs.js | 16 +- src/store/rules.js | 62 +----- src/types.ts | 5 + tsconfig.json | 5 +- yarn.lock | 185 ++++++++++-------- 21 files changed, 539 insertions(+), 213 deletions(-) create mode 100644 src/api/rule-provider.ts delete mode 100644 src/api/rules.js create mode 100644 src/api/rules.ts delete mode 100644 src/components/RuleSearch.js create mode 100644 src/components/rules/RuleProviderItem.module.css create mode 100644 src/components/rules/RuleProviderItem.tsx create mode 100644 src/components/rules/TextFilter.tsx create mode 100644 src/hooks/useTextInput.ts diff --git a/package.json b/package.json index bbe70e6..22126b1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "dependencies": { "@babel/runtime": "^7.10.3", "@hsjs/react-cache": "0.0.0-alpha.aa94237", - "@sentry/browser": "^5.18.1", + "@sentry/browser": "^5.19.0", "chart.js": "^2.9.2", "clsx": "^1.1.0", "core-js": "^3.6.2", @@ -52,10 +52,11 @@ "react-feather": "^2.0.3", "react-icons": "^3.10.0", "react-modal": "^3.11.1", + "react-query": "^2.4.13", "react-router": "^6.0.0-alpha.1", "react-router-dom": "^6.0.0-alpha.1", "react-switch": "^5.0.1", - "react-table": "^7.2.1", + "react-table": "^7.2.2", "react-tabs": "^3.1.0", "react-tiny-fab": "^3.5.0", "react-window": "^1.8.5", @@ -77,7 +78,9 @@ "@babel/preset-typescript": "^7.10.1", "@hsjs/react-refresh-webpack-plugin": "^0.1.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.2.0", + "@types/invariant": "^2.2.33", "@types/jest": "^26.0.3", + "@types/lodash-es": "^4.17.3", "@types/react": "^16.9.41", "@types/react-dom": "^16.9.8", "@typescript-eslint/eslint-plugin": "^3.4.0", @@ -86,10 +89,10 @@ "babel-eslint": "10.x", "babel-loader": "^8.0.5", "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.2", + "copy-webpack-plugin": "^6.0.3", "css-loader": "^3.4.2", "cssnano": "^4.1.7", - "eslint": "^7.3.1", + "eslint": "^7.4.0", "eslint-config-airbnb-base": "^14.1.0", "eslint-config-prettier": "^6.11.0", "eslint-config-react-app": "^5.2.1", @@ -98,12 +101,12 @@ "eslint-plugin-import": "^2.22.0", "eslint-plugin-jest": "^23.17.1", "eslint-plugin-jsx-a11y": "^6.3.1", - "eslint-plugin-react": "7.x", + "eslint-plugin-react": "^7.20.3", "eslint-plugin-react-hooks": "^4.0.0", "eslint-plugin-simple-import-sort": "^5.0.3", "file-loader": "^6.0.0", "fork-ts-checker-notifier-webpack-plugin": "^3.0.0", - "fork-ts-checker-webpack-plugin": "^5.0.5", + "fork-ts-checker-webpack-plugin": "^5.0.6", "html-webpack-plugin": "^4.3.0", "husky": "^4.0.0", "lint-staged": "^10.2.11", @@ -120,7 +123,7 @@ "style-loader": "^1.2.1", "terser-webpack-plugin": "^3.0.6", "ts-loader": "^7.0.5", - "typescript": "^3.9.5", + "typescript": "^3.9.6", "webpack": "^4.41.6", "webpack-bundle-analyzer": "^3.6.0", "webpack-cli": "^3.3.12", diff --git a/src/api/rule-provider.ts b/src/api/rule-provider.ts new file mode 100644 index 0000000..5d39527 --- /dev/null +++ b/src/api/rule-provider.ts @@ -0,0 +1,74 @@ +import { getURLAndInit } from 'src/misc/request-helper'; +import { ClashAPIConfig } from 'src/types'; + +export type RuleProvider = RuleProviderAPIItem & { idx: number }; + +export type RuleProviderAPIItem = { + behavior: string; + name: string; + ruleCount: number; + type: 'Rule'; + // example value "2020-06-30T16:23:01.44143802+08:00" + updatedAt: string; + vehicleType: 'HTTP' | 'File'; +}; + +type RuleProviderAPIData = { + providers: Record; +}; + +function normalizeAPIResponse(data: RuleProviderAPIData) { + const providers = data.providers; + const names = Object.keys(providers); + const byName: Record = {}; + + // attach an idx to each item + for (let i = 0; i < names.length; i++) { + const name = names[i]; + byName[name] = { ...providers[name], idx: i }; + } + + return { byName, names }; +} + +export async function fetchRuleProviders( + endpoint: string, + apiConfig: ClashAPIConfig +) { + const { url, init } = getURLAndInit(apiConfig); + + let data = { providers: {} }; + try { + const res = await fetch(url + endpoint, init); + if (res.ok) { + data = await res.json(); + } + } catch (err) { + // log and ignore + // eslint-disable-next-line no-console + console.log('failed to GET /providers/rules', err); + } + return normalizeAPIResponse(data); +} + +export async function refreshRuleProviderByName({ + name, + apiConfig, +}: { + name: string; + apiConfig: ClashAPIConfig; +}) { + const { url, init } = getURLAndInit(apiConfig); + try { + const res = await fetch(url + `/providers/rules/${name}`, { + method: 'PUT', + ...init, + }); + return res.ok; + } catch (err) { + // log and ignore + // eslint-disable-next-line no-console + console.log('failed to PUT /providers/rules/:name', err); + return false; + } +} diff --git a/src/api/rules.js b/src/api/rules.js deleted file mode 100644 index 574de96..0000000 --- a/src/api/rules.js +++ /dev/null @@ -1,8 +0,0 @@ -import { getURLAndInit } from '../misc/request-helper'; - -const endpoint = '/rules'; - -export async function fetchRules(apiConfig) { - const { url, init } = getURLAndInit(apiConfig); - return await fetch(url + endpoint, init); -} diff --git a/src/api/rules.ts b/src/api/rules.ts new file mode 100644 index 0000000..b57b0e3 --- /dev/null +++ b/src/api/rules.ts @@ -0,0 +1,41 @@ +import invariant from 'invariant'; +import { getURLAndInit } from 'src/misc/request-helper'; +import { ClashAPIConfig } from 'src/types'; + +// const endpoint = '/rules'; + +type RuleItem = RuleAPIItem & { id: number }; + +type RuleAPIItem = { + type: string; + payload: string; + proxy: string; +}; + +function normalizeAPIResponse(json: { + rules: Array; +}): Array { + invariant( + json.rules && json.rules.length >= 0, + 'there is no valid rules list in the rules API response' + ); + + // attach an id + return json.rules.map((r: RuleAPIItem, i: number) => ({ ...r, id: i })); +} + +export async function fetchRules(endpoint: string, apiConfig: ClashAPIConfig) { + let json = { rules: [] }; + try { + const { url, init } = getURLAndInit(apiConfig); + const res = await fetch(url + endpoint, init); + if (res.ok) { + json = await res.json(); + } + } catch (err) { + // log and ignore + // eslint-disable-next-line no-console + console.log('failed to fetch rules', err); + } + return normalizeAPIResponse(json); +} diff --git a/src/components/Button.module.css b/src/components/Button.module.css index 719a9aa..83da6af 100644 --- a/src/components/Button.module.css +++ b/src/components/Button.module.css @@ -43,6 +43,10 @@ } } +.btn:disabled { + opacity: 0.5; +} + .btnStart { margin-right: 5px; display: inline-flex; diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 7409c58..9450969 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -16,6 +16,7 @@ type ButtonInternalProps = { type ButtonProps = { isLoading?: boolean; onClick?: (e: React.MouseEvent) => unknown; + disabled?: boolean; kind?: 'primary' | 'minimal'; className?: string; } & ButtonInternalProps; @@ -23,6 +24,7 @@ type ButtonProps = { function Button(props: ButtonProps, ref: React.Ref) { const { onClick, + disabled = false, isLoading, kind = 'primary', className, @@ -43,7 +45,12 @@ function Button(props: ButtonProps, ref: React.Ref) { className ); return ( - + + + ); +} + diff --git a/src/components/rules/TextFilter.tsx b/src/components/rules/TextFilter.tsx new file mode 100644 index 0000000..a3cc29e --- /dev/null +++ b/src/components/rules/TextFilter.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { useTextInut } from 'src/hooks/useTextInput'; +import { ruleFilterText } from 'src/store/rules'; + +import shared from '../shared.module.css'; + +export function TextFilter() { + const [onChange, text] = useTextInut(ruleFilterText); + return ( + + ); +} diff --git a/src/hooks/useTextInput.ts b/src/hooks/useTextInput.ts new file mode 100644 index 0000000..1fa19f7 --- /dev/null +++ b/src/hooks/useTextInput.ts @@ -0,0 +1,23 @@ +import debounce from 'lodash-es/debounce'; +import * as React from 'react'; +import { RecoilState, useRecoilState } from 'recoil'; + +const { useCallback, useState, useMemo } = React; + +export function useTextInut( + x: RecoilState +): [(e: React.ChangeEvent) => void, string] { + const [, setTextGlobal] = useRecoilState(x); + const [text, setText] = useState(''); + const setTextDebounced = useMemo(() => debounce(setTextGlobal, 300), [ + setTextGlobal, + ]); + const onChange = useCallback( + (e: React.ChangeEvent) => { + setText(e.target.value); + setTextDebounced(e.target.value); + }, + [setTextDebounced] + ); + return [onChange, text]; +} diff --git a/src/store/index.js b/src/store/index.js index 0e559ad..bd4e7a9 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -8,14 +8,12 @@ import { initialState as configs } from './configs'; import { initialState as logs } from './logs'; import { initialState as modals } from './modals'; import { actions as proxiesActions, initialState as proxies } from './proxies'; -import { initialState as rules } from './rules'; export const initialState = { app: app(), modals, configs, proxies, - rules, logs, }; diff --git a/src/store/logs.js b/src/store/logs.js index c3b3b9a..6da2b33 100644 --- a/src/store/logs.js +++ b/src/store/logs.js @@ -2,9 +2,9 @@ import { createSelector } from 'reselect'; const LogSize = 300; -const getLogs = s => s.logs.logs; -const getTail = s => s.logs.tail; -export const getSearchText = s => s.logs.searchText; +const getLogs = (s) => s.logs.logs; +const getTail = (s) => s.logs.tail; +export const getSearchText = (s) => s.logs.searchText; export const getLogsForDisplay = createSelector( getLogs, getTail, @@ -21,13 +21,13 @@ export const getLogsForDisplay = createSelector( } if (searchText === '') return x; - return x.filter(r => r.payload.toLowerCase().indexOf(searchText) >= 0); + return x.filter((r) => r.payload.toLowerCase().indexOf(searchText) >= 0); } ); export function updateSearchText(text) { - return dispatch => { - dispatch('logsUpdateSearchText', s => { + return (dispatch) => { + dispatch('logsUpdateSearchText', (s) => { s.logs.searchText = text.toLowerCase(); }); }; @@ -42,7 +42,7 @@ export function appendLog(log) { // mutate intentionally for performance logs[tail] = log; - dispatch('logsAppendLog', s => { + dispatch('logsAppendLog', (s) => { s.logs.tail = tail; }); }; @@ -52,5 +52,5 @@ export const initialState = { searchText: '', logs: [], // tail's initial value must be -1 - tail: -1 + tail: -1, }; diff --git a/src/store/rules.js b/src/store/rules.js index 61e3328..bdd835d 100644 --- a/src/store/rules.js +++ b/src/store/rules.js @@ -1,58 +1,6 @@ -import invariant from 'invariant'; -import { createSelector } from 'reselect'; +import { atom } from 'recoil'; -import * as rulesAPI from '../api/rules'; - -export const getAllRules = (s) => s.rules.allRules; -export const getSearchText = (s) => s.rules.searchText; -export const getRules = createSelector( - getSearchText, - getAllRules, - (searchText, allRules) => { - if (searchText === '') return allRules; - return allRules.filter((r) => r.payload.indexOf(searchText) >= 0); - } -); -export function updateSearchText(text) { - return (dispatch) => { - dispatch('rulesUpdateSearchText', (s) => { - s.rules.searchText = text.toLowerCase(); - }); - }; -} - -export function fetchRules(apiConfig) { - return async (dispatch) => { - const res = await rulesAPI.fetchRules(apiConfig); - const json = await res.json(); - invariant( - json.rules && json.rules.length >= 0, - 'there is no valid rules list in the rules API response' - ); - - // attach an id - const allRules = json.rules.map((r, i) => { - r.id = i; - return r; - }); - - dispatch('rulesFetchRules', (s) => { - s.rules.allRules = allRules; - }); - }; -} - -export function fetchRulesOnce(apiConfig) { - return async (dispatch, getState) => { - const allRules = getAllRules(getState()); - if (allRules.length === 0) return await dispatch(fetchRules(apiConfig)); - }; -} - -// {"type":"FINAL","payload":"","proxy":"Proxy"} -// {"type":"IPCIDR","payload":"172.16.0.0/12","proxy":"DIRECT"} -export const initialState = { - // filteredRules: [], - allRules: [], - searchText: '', -}; +export const ruleFilterText = atom({ + key: 'ruleFilterText', + default: '', +}); diff --git a/src/types.ts b/src/types.ts index e69de29..047f3fb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -0,0 +1,5 @@ +export type ClashAPIConfig = { + hostname: string; + port: number; + secret?: string; +}; diff --git a/tsconfig.json b/tsconfig.json index 1a1b9ab..b7f0ee5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,8 @@ { "compilerOptions": { "baseUrl": ".", - "allowSyntheticDefaultImports": false, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "target": "es5", "downlevelIteration": true, "importHelpers": true, @@ -15,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "experimentalDecorators": true, "noImplicitAny": false, - "noUnusedParameters": true, + "noUnusedParameters": false, "noImplicitReturns": true, "noImplicitThis": true, "noUnusedLocals": true, diff --git a/yarn.lock b/yarn.lock index 90b9a52..013b0fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1176,61 +1176,56 @@ style-value-types "^3.1.7" tslib "^1.10.0" -"@scarf/scarf@^1.0.4": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.0.6.tgz#52011dfb19187b53b75b7b6eac20da0810ddd88f" - integrity sha512-y4+DuXrAd1W5UIY3zTcsosi/1GyYT8k5jGnZ/wG7UUHVrU+MHlH4Mp87KK2/lvMW4+H7HVcdB+aJhqywgXksjA== - -"@sentry/browser@^5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.18.1.tgz#6a2ebe8f4ba88b2e98ccc91442e1dcb37b2df988" - integrity sha512-U1w0d5kRMsfzMYwWn4+awDKfBEI5lxhHa0bMChSpj5z/dWiz/e0mikZ9gCoF+ZNqkXJ92l/3r9gRz+SIsn5ZoA== +"@sentry/browser@^5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.19.0.tgz#9189b6633fe45e54325e40b39345d9eabd171e4a" + integrity sha512-Cz8PnzC5NGfpHIGCmHLgA6iDEBVELwo4Il/iFweXjs4+VL4biw62lI32Q4iLCCpmX0t5UvrWBOnju2v8zuFIjA== dependencies: - "@sentry/core" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/core" "5.19.0" + "@sentry/types" "5.19.0" + "@sentry/utils" "5.19.0" tslib "^1.9.3" -"@sentry/core@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.18.1.tgz#c2aa7ef9054e372d006d32234969711234d2bb02" - integrity sha512-nC2aK6gwVIBVysmtdFHxYJyuChIHtkv7TnvmwgA5788L/HWo7E3R+Rd8Tf2npvp/aP+kmNITNbc5CIIqwGPaqQ== +"@sentry/core@5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.19.0.tgz#31b08a0b46ae1ee6863447225b401ac2a777774c" + integrity sha512-ry1Zms6jrVQPEwmfywItyUhOgabPrykd8stR1x/u2t1YiISWlR813fE5nzdwgW5mxEitXz/ikTwvrfK3egsDWQ== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/minimal" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/hub" "5.19.0" + "@sentry/minimal" "5.19.0" + "@sentry/types" "5.19.0" + "@sentry/utils" "5.19.0" tslib "^1.9.3" -"@sentry/hub@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.18.1.tgz#4c2f642e29a320885692b902fba89e57a9906e64" - integrity sha512-dFnaj1fQRT74EhoF8MXJ23K3svt11zEF6CS3cdMrkSzfRbAHjyza7KT2AJHUeF6gtH2BZzqsSw+FnfAke0HGIg== +"@sentry/hub@5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.19.0.tgz#f38e7745a4980d9fa6c5baeca5605e7e6fecd5ac" + integrity sha512-UFaQLa1XAa02ZcxUmN9GdDpGs3vHK1LpOyYooimX8ttWa4KAkMuP+O5uXH1TJabry6o/cRwYisg2k6PBSy8gxw== dependencies: - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/types" "5.19.0" + "@sentry/utils" "5.19.0" tslib "^1.9.3" -"@sentry/minimal@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.18.1.tgz#8de01e87c5f5c6e74b707849202150cd4b316ee0" - integrity sha512-St2bjcZ5FFiH+bYkWoEPlEb0w38YSvftnjJTvZyk05SCdsF7HkGfoBeFmztwBf1VLQPYt3ojny14L6KDAvOTpw== +"@sentry/minimal@5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.19.0.tgz#aa5a700618608ea79d270280fe77f04bbb44ed5a" + integrity sha512-3FHgirwOuOMF4VlwHboYObPT9c0S9b9y5FW0DGgNt8sJPezS00VaJti/38ZwOHQJ4fJ6ubt/Y3Kz0eBTVxMCCQ== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/types" "5.18.1" + "@sentry/hub" "5.19.0" + "@sentry/types" "5.19.0" tslib "^1.9.3" -"@sentry/types@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.18.1.tgz#9d72254262f28e966b06371c5b3833de8f0253b8" - integrity sha512-y5YTkRFC4Y7r4GHrvin6aZLBpQIGdMZRq78f/s7IIEZrmWYbVKsK4dyJht6pOsUdEaxeYpsu3okIA0bqmthSJA== +"@sentry/types@5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.19.0.tgz#30c6a05040b644d90337ef8b50d9d59c0872744d" + integrity sha512-NlHLS9mwCEimKUA5vClAwVhXFLsqSF3VJEXU+K61fF6NZx8zfJi/HTrIBtoM4iNSAt9o4XLQatC1liIpBC06tg== -"@sentry/utils@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.18.1.tgz#c9880056793ae77d651db0dae76a08a8a0b31eac" - integrity sha512-P4lt6NauCBWASaP6R5kfOmc24imbD32G5FeWqK7vHftIphOJ0X7OZfh93DJPs3e5RIvW3YCywUsa7MpTH5/ClA== +"@sentry/utils@5.19.0": + version "5.19.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.19.0.tgz#0e01f84aa67a1cf2ec71faab670230918ea7e9aa" + integrity sha512-EU/T9aJrI8isexRnyDx5InNw/HjSQ0nKI7YWdiwfFrJusqQ/uisnCGK7vw6gGHDgiAHMXW3TJ38NHpNBin6y7Q== dependencies: - "@sentry/types" "5.18.1" + "@sentry/types" "5.19.0" tslib "^1.9.3" "@types/anymatch@*": @@ -1267,6 +1262,11 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.0.0.tgz#7532440c138605ced1b555935c3115ddd20e8bef" integrity sha512-q95SP4FdkmF0CwO0F2q0H6ZgudsApaY/yCtAQNRn1gduef5fGpyEphzy0YCq/N0UFvDSnLg5V8jFK/YGXlDiCw== +"@types/invariant@^2.2.33": + version "2.2.33" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.33.tgz#ec5eec29c63bf5e4ca164e9feb3ef7337cdcbadb" + integrity sha512-/jUNmS8d4bCKdqslfxW6dg/9Gksfzxz67IYfqApHn+HvHlMVXwYv2zpTDnS/yaK9BB0i0GlBTaYci0EFE62Hmw== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5" @@ -1305,6 +1305,18 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/lodash-es@^4.17.3": + version "4.17.3" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.3.tgz#87eb0b3673b076b8ee655f1890260a136af09a2d" + integrity sha512-iHI0i7ZAL1qepz1Y7f3EKg/zUMDwDfTzitx+AlHhJJvXwenP682ZyGbgPSc5Ej3eEAKVbNWKFuwOadCj5vBbYQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": + version "4.14.157" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.157.tgz#fdac1c52448861dfde1a2e1515dbc46e54926dc8" + integrity sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -2737,21 +2749,21 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-webpack-plugin@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.2.tgz#10efc6ad219a61acbf2f5fb50af83da38431bc34" - integrity sha512-9Gm8X0c6eXlKnmltMPFCBeGOKjtcRIyTt4VaO3k1TkNgVTe5Ov2lYsYVuyLp0kp8DItO3apewflM+1GYgh6V2Q== +copy-webpack-plugin@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz#2b3d2bfc6861b96432a65f0149720adbd902040b" + integrity sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA== dependencies: cacache "^15.0.4" - fast-glob "^3.2.2" + fast-glob "^3.2.4" find-cache-dir "^3.3.1" glob-parent "^5.1.1" globby "^11.0.1" loader-utils "^2.0.0" normalize-path "^3.0.0" - p-limit "^2.3.0" + p-limit "^3.0.1" schema-utils "^2.7.0" - serialize-javascript "^3.1.0" + serialize-javascript "^4.0.0" webpack-sources "^1.4.3" core-js-compat@^3.6.2: @@ -3616,10 +3628,10 @@ eslint-plugin-react-hooks@^4.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.5.tgz#4879003aa38e5d05d0312175beb6e4a1f617bfcf" integrity sha512-3YLSjoArsE2rUwL8li4Yxx1SUg3DQWp+78N3bcJQGWVZckcp+yeQGsap/MSq05+thJk57o+Ww4PtZukXGL02TQ== -eslint-plugin-react@7.x: - version "7.20.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.2.tgz#b0d72abcd94c59c842338aa09c800808219ea77d" - integrity sha512-J3BdtsPNbcF/CG9HdyLx7jEtC7tuODODGldkS9P1zU2WMoHPdcsN2enUopgIaec5f9eYhSFI5zQAaWA/dgv2zw== +eslint-plugin-react@^7.20.3: + version "7.20.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" + integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" @@ -3676,10 +3688,10 @@ eslint-visitor-keys@^1.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== -eslint@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== +eslint@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -3917,7 +3929,7 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.1.1, fast-glob@^3.2.2: +fast-glob@^3.1.1: version "3.2.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== @@ -3929,6 +3941,18 @@ fast-glob@^3.1.1, fast-glob@^3.2.2: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -4137,10 +4161,10 @@ fork-ts-checker-webpack-plugin@1.5.0: tapable "^1.0.0" worker-rpc "^0.1.0" -fork-ts-checker-webpack-plugin@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.0.5.tgz#4cf77f925008464db4670750a6e9266a4d25a988" - integrity sha512-2vpP+irspLOpZ1pcH3K3yR76MWXVSOYKTGwhwFQGnWjOs5MxzPN+dyDh1tNoaD5DUFP5kr4lGQURE9Qk+DpiUQ== +fork-ts-checker-webpack-plugin@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.0.6.tgz#02af713af02e47b338a3992279209bc65d34c773" + integrity sha512-8h4S7WANr69Resw+tMd5U23xdbVPsT+VOeMKQhUaKhkGeMm0fNf7ObJPP81WG+tsmy4LK4ayIf0JXBY+hy6vMw== dependencies: "@babel/code-frame" "^7.8.3" chalk "^2.4.1" @@ -6144,7 +6168,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -7136,6 +7160,13 @@ react-modal@^3.11.1: react-lifecycles-compat "^3.0.0" warning "^4.0.3" +react-query@^2.4.13: + version "2.4.13" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-2.4.13.tgz#478f4f32a8c6b56de0e7bb6eb3cd2baa812e1ebb" + integrity sha512-PFUmChSy3kph+r0c+oz7HgBiKi98bb1D8FeeBZ1qiuuGXUJYhWCvOST+lOgwtLiBbT1wdoNjObFC35jpHbSvUQ== + dependencies: + ts-toolbelt "^6.9.4" + react-refresh@^0.8.2: version "0.8.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" @@ -7164,12 +7195,10 @@ react-switch@^5.0.1: dependencies: prop-types "^15.6.2" -react-table@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.2.1.tgz#d85f5a59b6441ccd9e0acddc93c288c54a7de7ee" - integrity sha512-cICU3w5yFWTDluz9yFePziEQXGt3PK5R1Va3InP7qMGnZOKm8kv0GiDMli+VOqE1uM1dBYPb9BEad15up1ac6g== - dependencies: - "@scarf/scarf" "^1.0.4" +react-table@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.2.2.tgz#2978a903f0e367e1ceab25d60a6a40ae23498f77" + integrity sha512-JBE3QUyRQJkHRU72NKo7HRGtSGcrzIcVLDbsoZI+KhWkFEZ2t9UfpqeHBdbc3R5RRJZ6qC7+NzZZxJPSYWKPBQ== react-tabs@^3.1.0: version "3.1.1" @@ -7654,13 +7683,6 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== -serialize-javascript@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" - integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== - dependencies: - randombytes "^2.1.0" - serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" @@ -8418,6 +8440,11 @@ ts-loader@^7.0.5: micromatch "^4.0.0" semver "^6.0.0" +ts-toolbelt@^6.9.4: + version "6.9.9" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.9.9.tgz#e6cfd8ec7d425d2a06bda3b4fe9577ceaf2abda8" + integrity sha512-5a8k6qfbrL54N4Dw+i7M6kldrbjgDWb5Vit8DnT+gwThhvqMg8KtxLE5Vmnft+geIgaSOfNJyAcnmmlflS+Vdg== + tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -8485,10 +8512,10 @@ typeface-roboto-mono@^0.0.75: resolved "https://registry.yarnpkg.com/typeface-roboto-mono/-/typeface-roboto-mono-0.0.75.tgz#00c4543662066a837c014c251ee5140fb66a5ad8" integrity sha512-dYfyXd6HrKyMC/PuBAAtay0tZKsBrzxIW/fBY325vLxFfi/IDKSuyTkWxkU4lyZV6KPHetFnJ661PNXzz2FS/w== -typescript@^3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@^3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4"