From df0bfb5e10003e6332d9d2c6cb6bea61b7fa2c30 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 1 Jul 2021 23:56:50 +0800 Subject: [PATCH] Chore: add more strictly eslint --- .eslintrc.yml | 14 +++ package.json | 3 + src/components/Alert/index.tsx | 2 +- src/components/ButtonSelect/index.tsx | 2 +- src/components/Input/index.tsx | 2 +- src/components/Message/index.tsx | 14 +-- src/components/Modal/index.tsx | 2 +- src/components/Select/index.tsx | 24 ++--- src/containers/App.tsx | 4 +- src/containers/Connections/Devices/index.tsx | 2 +- src/containers/Connections/index.tsx | 43 +++++---- src/containers/Connections/store.ts | 4 +- .../ExternalControllerDrawer/index.tsx | 2 +- src/containers/Logs/index.tsx | 6 +- src/containers/Overview/index.tsx | 4 +- .../Proxies/components/Group/index.tsx | 4 +- .../Proxies/components/Provider/index.tsx | 4 +- .../Proxies/components/Proxy/index.tsx | 19 ++-- src/containers/Proxies/index.tsx | 22 ++--- src/containers/Rules/Provider/index.tsx | 2 +- src/containers/Settings/index.tsx | 10 +- src/containers/Sidebar/index.tsx | 6 +- src/i18n/en_US.ts | 32 +++---- src/i18n/index.ts | 2 +- src/i18n/zh_CN.ts | 32 +++---- src/lib/asyncSingleton.ts | 6 +- src/lib/hook.ts | 2 +- src/lib/jsBridge.ts | 58 +++++------ src/lib/request.ts | 74 +++++++-------- src/lib/streamer.ts | 14 +-- src/models/Cipher.ts | 26 ++--- src/models/Proxy.ts | 6 +- src/stores/jotai.ts | 26 ++--- src/stores/request.ts | 36 +++---- yarn.lock | 95 ++++++++++++++++++- 35 files changed, 351 insertions(+), 253 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 822bb79..6986db6 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,3 +1,17 @@ extends: + - standard-with-typescript - react-app parser: '@typescript-eslint/parser' +parserOptions: + project: './tsconfig.json' +rules: + comma-dangle: [error, always-multiline] + '@typescript-eslint/indent': [error, 4] + '@typescript-eslint/explicit-function-return-type': off + '@typescript-eslint/restrict-template-expressions': off + '@typescript-eslint/strict-boolean-expressions': off + '@typescript-eslint/no-non-null-assertion': off + '@typescript-eslint/consistent-type-assertions': off + '@typescript-eslint/promise-function-async': off + '@typescript-eslint/no-floating-promises': off + '@typescript-eslint/no-invalid-void-type': off diff --git a/package.json b/package.json index 819cdd2..af29156 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,12 @@ "babel-eslint": "^10.1.0", "eslint": "^7.29.0", "eslint-config-react-app": "^6.0.0", + "eslint-config-standard-with-typescript": "^20.0.0", "eslint-plugin-flowtype": "^5.7.2", "eslint-plugin-import": "^2.23.4", "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^5.1.0", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", "sass": "^1.35.1", diff --git a/src/components/Alert/index.tsx b/src/components/Alert/index.tsx index 1a3a687..ea5c979 100644 --- a/src/components/Alert/index.tsx +++ b/src/components/Alert/index.tsx @@ -14,7 +14,7 @@ const iconMap = { success: 'check', info: 'info', warning: 'info', - error: 'close' + error: 'close', } export function Alert (props: AlertProps) { diff --git a/src/components/ButtonSelect/index.tsx b/src/components/ButtonSelect/index.tsx index f4bf46f..d798597 100644 --- a/src/components/ButtonSelect/index.tsx +++ b/src/components/ButtonSelect/index.tsx @@ -10,7 +10,7 @@ export interface ButtonSelectOptions { export interface ButtonSelectProps extends BaseComponentProps { // options - options: ButtonSelectOptions[] + options: Array> // active value value: T diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index a1e546f..d554c33 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -26,7 +26,7 @@ export function Input (props: InputProps) { type = 'text', disabled = false, onChange = noop, - onBlur = noop + onBlur = noop, } = props const classname = classnames('input', `text-${align}`, { 'focus:shadow-none': inside }, className) diff --git a/src/components/Message/index.tsx b/src/components/Message/index.tsx index 7880ca1..c6430aa 100644 --- a/src/components/Message/index.tsx +++ b/src/components/Message/index.tsx @@ -10,7 +10,7 @@ const TYPE_ICON_MAP = { info: 'info', success: 'check', warning: 'info-o', - error: 'close' + error: 'close', } type NoticeType = 'success' | 'info' | 'warning' | 'error' @@ -38,7 +38,7 @@ export function Message (props: MessageProps) { icon = , content = '', type = 'info', - duration = 1500 + duration = 1500, } = props const { visible, show, hide } = useVisible() @@ -85,7 +85,7 @@ export function showMessage (args: ArgsProps) { content, removeComponent, duration, - onClose + onClose, } render(, container) @@ -94,23 +94,23 @@ export function showMessage (args: ArgsProps) { export const info = ( content: string, duration?: number, - onClose?: typeof noop + onClose?: typeof noop, ) => showMessage({ type: 'info', content, duration, onClose }) export const success = ( content: string, duration?: number, - onClose?: typeof noop + onClose?: typeof noop, ) => showMessage({ type: 'success', content, duration, onClose }) export const warning = ( content: string, duration?: number, - onClose?: typeof noop + onClose?: typeof noop, ) => showMessage({ type: 'warning', content, duration, onClose }) export const error = ( content: string, duration?: number, - onClose?: typeof noop + onClose?: typeof noop, ) => showMessage({ type: 'error', content, duration, onClose }) diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 30d9f39..754c97d 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -45,7 +45,7 @@ export function Modal (props: ModalProps) { bodyStyle, className, style, - children + children, } = props const { translation } = useI18n() diff --git a/src/components/Select/index.tsx b/src/components/Select/index.tsx index 77e73a3..ebaa60e 100644 --- a/src/components/Select/index.tsx +++ b/src/components/Select/index.tsx @@ -23,18 +23,18 @@ interface SelectProps extends BaseComponentProps { export function Select (props: SelectProps) { const { value, onSelect, children, className: cn, style } = props - const portalRef = useRef() + const portalRef = useRef(document.createElement('div')) const attachmentRef = useRef(null) const targetRef = useRef(null) const [showDropDownList, setShowDropDownList] = useState(false) const [hasCreateDropList, setHasCreateDropList] = useState(false) const dropdownListStyles = useMemo(() => { - if (targetRef.current) { + if (targetRef.current != null) { const targetRectInfo = targetRef.current.getBoundingClientRect() return { top: Math.floor(targetRectInfo.top) - 10, - left: Math.floor(targetRectInfo.left) - 10 + left: Math.floor(targetRectInfo.left) - 10, } } return {} @@ -49,23 +49,17 @@ export function Select (props: SelectProps) { } useLayoutEffect(() => { + const current = portalRef.current + document.body.appendChild(current) document.addEventListener('click', handleGlobalClick, true) return () => { document.addEventListener('click', handleGlobalClick, true) - if (portalRef.current) { - document.body.removeChild(portalRef.current) - } + document.body.removeChild(current) } }, []) function handleShowDropList () { if (!hasCreateDropList) { - if (!portalRef.current) { - // create container element - const container = document.createElement('div') - document.body.appendChild(container) - portalRef.current = container - } setHasCreateDropList(true) } setShowDropDownList(true) @@ -100,9 +94,9 @@ export function Select (props: SelectProps) { onClick: (e: React.MouseEvent) => { onSelect?.(child.props.value, e) setShowDropDownList(false) - rawOnClickEvent && rawOnClickEvent(e) + rawOnClickEvent?.(e) }, - className + className, })) }) }, [children, value, onSelect]) @@ -131,7 +125,7 @@ export function Select (props: SelectProps) { { - hasCreateDropList && createPortal(dropDownList, portalRef?.current!) + hasCreateDropList && createPortal(dropDownList, portalRef.current) } ) diff --git a/src/containers/App.tsx b/src/containers/App.tsx index 22d8b2b..ec69f65 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -25,7 +25,7 @@ export default function App () { { path: '/logs', name: 'Logs', component: Logs }, { path: '/rules', name: 'Rules', component: Rules, noMobile: true }, { path: '/connections', name: 'Connections', component: Connections, noMobile: true }, - { path: '/settings', name: 'Settings', component: Settings } + { path: '/settings', name: 'Settings', component: Settings }, ] return ( @@ -36,7 +36,7 @@ export default function App () { } /> { routes.map( - route => + route => , ) } diff --git a/src/containers/Connections/Devices/index.tsx b/src/containers/Connections/Devices/index.tsx index e7eabc2..e4eacdd 100644 --- a/src/containers/Connections/Devices/index.tsx +++ b/src/containers/Connections/Devices/index.tsx @@ -34,7 +34,7 @@ export function Devices (props: DevicesProps) { onClick={() => handleSelected(device.label)}> { device.label } ({ device.number }) - ) + ), ) } diff --git a/src/containers/Connections/index.tsx b/src/containers/Connections/index.tsx index 6eb3a82..a93adf1 100644 --- a/src/containers/Connections/index.tsx +++ b/src/containers/Connections/index.tsx @@ -47,7 +47,7 @@ interface ITableInstance extends TableInstance, UseFiltersInstanceProps {} -function formatTraffic(num: number) { +function formatTraffic (num: number) { const s = ['B', 'KB', 'MB', 'GB', 'TB'] let idx = 0 while (~~(num / 1024) && idx < s.length) { @@ -58,7 +58,7 @@ function formatTraffic(num: number) { return `${idx === 0 ? num : num.toFixed(2)} ${s[idx]}` } -function formatSpeed(upload: number, download: number) { +function formatSpeed (upload: number, download: number) { switch (true) { case upload === 0 && download === 0: return '-' @@ -89,7 +89,7 @@ interface formatConnection { completed: boolean } -export default function Connections() { +export default function Connections () { const { translation, lang } = useI18n() const t = useMemo(() => translation('Connections').t, [translation]) const connStreamReader = useConnectionStreamReader() @@ -98,12 +98,12 @@ export default function Connections() { // total const [traffic, setTraffic] = useObject({ uploadTotal: 0, - downloadTotal: 0 + downloadTotal: 0, }) // close all connections const { visible, show, hide } = useVisible() - function handleCloseConnections() { + function handleCloseConnections () { client.closeAllConnections().finally(() => hide()) } @@ -122,8 +122,8 @@ export default function Connections() { type: c.metadata.type, network: c.metadata.network.toUpperCase(), speed: { upload: c.uploadSpeed, download: c.downloadSpeed }, - completed: !!c.completed - }) + completed: !!c.completed, + }), ), [connections]) const devices = useMemo(() => { const gb = groupBy(connections, 'metadata.sourceIP') @@ -133,7 +133,7 @@ export default function Connections() { // table const tableRef = useRef(null) const { x: scrollX } = useScroll(tableRef) - const columns: TableColumnOption[] = useMemo(() => [ + const columns: Array> = useMemo(() => [ { Header: t(`columns.${Columns.Host}`), accessor: Columns.Host, minWidth: 260, width: 260 }, { Header: t(`columns.${Columns.Network}`), accessor: Columns.Network, minWidth: 80, width: 80 }, { Header: t(`columns.${Columns.Type}`), accessor: Columns.Type, minWidth: 120, width: 120 }, @@ -142,31 +142,32 @@ export default function Connections() { { id: Columns.Speed, Header: t(`columns.${Columns.Speed}`), - accessor(originalRow: formatConnection) { + accessor (originalRow: formatConnection) { return [originalRow.speed.upload, originalRow.speed.download] }, - sortType(rowA, rowB) { + sortType (rowA, rowB) { const speedA = rowA.original.speed const speedB = rowB.original.speed return speedA.download === speedB.download ? speedA.upload - speedB.upload : speedA.download - speedB.download }, - minWidth: 200, width: 200, - sortDescFirst: true + minWidth: 200, + width: 200, + sortDescFirst: true, }, { Header: t(`columns.${Columns.Upload}`), accessor: Columns.Upload, minWidth: 100, width: 100, sortDescFirst: true }, { Header: t(`columns.${Columns.Download}`), accessor: Columns.Download, minWidth: 100, width: 100, sortDescFirst: true }, { Header: t(`columns.${Columns.SourceIP}`), accessor: Columns.SourceIP, minWidth: 140, width: 140 }, - { Header: t(`columns.${Columns.Time}`), accessor: Columns.Time, minWidth: 120, width: 120, sortType(rowA, rowB) { return rowB.original.time - rowA.original.time } }, - ] as TableColumnOption[], [t]) + { Header: t(`columns.${Columns.Time}`), accessor: Columns.Time, minWidth: 120, width: 120, sortType (rowA, rowB) { return rowB.original.time - rowA.original.time } }, + ] as Array>, [t]) useLayoutEffect(() => { - function handleConnection(snapshots: API.Snapshot[]) { + function handleConnection (snapshots: API.Snapshot[]) { for (const snapshot of snapshots) { setTraffic({ uploadTotal: snapshot.uploadTotal, - downloadTotal: snapshot.downloadTotal + downloadTotal: snapshot.downloadTotal, }) feed(snapshot.connections) @@ -186,19 +187,19 @@ export default function Connections() { headerGroups, rows, prepareRow, - setFilter + setFilter, } = useTable( { columns, data, autoResetSortBy: false, autoResetFilters: false, - initialState: { sortBy: [{ id: Columns.Time, desc: false }] } + initialState: { sortBy: [{ id: Columns.Time, desc: false }] }, } as ITableOptions, useResizeColumns, useBlockLayout, useFilters, - useSortBy + useSortBy, ) as ITableInstance const headerGroup = useMemo(() => headerGroups[0], [headerGroups]) const renderCell = useCallback(function (cell: Cell) { @@ -244,7 +245,7 @@ export default function Connections() { {...realColumn.getHeaderProps()} className={classnames('connections-th', { resizing: realColumn.isResizing, - fixed: scrollX > 0 && realColumn.id === Columns.Host + fixed: scrollX > 0 && realColumn.id === Columns.Host, })} key={id}>
@@ -275,7 +276,7 @@ export default function Connections() { const classname = classnames( 'connections-block', { 'text-center': shouldCenter.has(cell.column.id), completed: row.original.completed }, - { fixed: scrollX > 0 && cell.column.id === Columns.Host } + { fixed: scrollX > 0 && cell.column.id === Columns.Host }, ) return (
diff --git a/src/containers/Connections/store.ts b/src/containers/Connections/store.ts index 919daaf..85a27d7 100644 --- a/src/containers/Connections/store.ts +++ b/src/containers/Connections/store.ts @@ -9,7 +9,7 @@ class Store { appendToSet (connections: API.Connections[]) { const mapping = connections.reduce( - (map, c) => map.set(c.id, c), new Map() + (map, c) => map.set(c.id, c), new Map(), ) for (const id of this.connections.keys()) { @@ -18,7 +18,7 @@ class Store { this.connections.delete(id) } else { const connection = this.connections.get(id) - if (connection) { + if (connection != null) { connection.completed = true connection.uploadSpeed = 0 connection.downloadSpeed = 0 diff --git a/src/containers/ExternalControllerDrawer/index.tsx b/src/containers/ExternalControllerDrawer/index.tsx index c98bba5..4e38356 100644 --- a/src/containers/ExternalControllerDrawer/index.tsx +++ b/src/containers/ExternalControllerDrawer/index.tsx @@ -15,7 +15,7 @@ export default function ExternalController () { const [value, set] = useObject({ hostname: '', port: '', - secret: '' + secret: '', }) useEffect(() => { diff --git a/src/containers/Logs/index.tsx b/src/containers/Logs/index.tsx index 0f30960..f9acbed 100644 --- a/src/containers/Logs/index.tsx +++ b/src/containers/Logs/index.tsx @@ -15,7 +15,7 @@ export default function Logs () { useLayoutEffect(() => { const ul = listRef.current - if (ul) { + if (ul != null) { ul.scrollTop = ul.scrollHeight } }) @@ -26,7 +26,7 @@ export default function Logs () { setLogs(logsRef.current) } - if (logsStreamReader) { + if (logsStreamReader != null) { logsStreamReader.subscribe('data', handleLog) logsRef.current = logsStreamReader.buffer() setLogs(logsRef.current) @@ -47,7 +47,7 @@ export default function Logs () { { dayjs(log.time).format('YYYY-MM-DD HH:mm:ss') } [{ log.type }] { log.payload } - ) + ), ) } diff --git a/src/containers/Overview/index.tsx b/src/containers/Overview/index.tsx index 3aaab7f..aaca3ab 100644 --- a/src/containers/Overview/index.tsx +++ b/src/containers/Overview/index.tsx @@ -9,10 +9,10 @@ export default function Overview () { alignItems: 'center', justifyContent: 'center', flexDirection: 'column', - opacity: 0.3 + opacity: 0.3, }}> Logo

Coming Soon...

diff --git a/src/containers/Proxies/components/Group/index.tsx b/src/containers/Proxies/components/Group/index.tsx index 555b966..6387a97 100644 --- a/src/containers/Proxies/components/Group/index.tsx +++ b/src/containers/Proxies/components/Group/index.tsx @@ -28,9 +28,7 @@ export function Group (props: GroupProps) { } } - for (const id of list) { - client.closeConnection(id) - } + await Promise.all(list.map(id => client.closeConnection(id))) } } diff --git a/src/containers/Proxies/components/Provider/index.tsx b/src/containers/Proxies/components/Provider/index.tsx index 08c22a4..00db23e 100644 --- a/src/containers/Proxies/components/Provider/index.tsx +++ b/src/containers/Proxies/components/Provider/index.tsx @@ -24,12 +24,12 @@ export function Provider (props: ProvidersProps) { function handleHealthChech () { show() - client.healthCheckProvider(provider.name).then(() => update()).finally(() => hide()) + client.healthCheckProvider(provider.name).then(async () => await update()).finally(() => hide()) } function handleUpdate () { show() - client.updateProvider(provider.name).then(() => update()).finally(() => hide()) + client.updateProvider(provider.name).then(async () => await update()).finally(() => hide()) } const proxies = useMemo(() => { diff --git a/src/containers/Proxies/components/Proxy/index.tsx b/src/containers/Proxies/components/Proxy/index.tsx index 028adc5..0314d89 100644 --- a/src/containers/Proxies/components/Proxy/index.tsx +++ b/src/containers/Proxies/components/Proxy/index.tsx @@ -18,7 +18,7 @@ const TagColors = { '#909399': 0, '#00c520': 260, '#ff9a28': 600, - '#ff3e5e': Infinity + '#ff3e5e': Infinity, } export function Proxy (props: ProxyProps) { @@ -42,7 +42,7 @@ export function Proxy (props: ProxyProps) { const validDelay = result.isErr() ? 0 : result.value set(draft => { const proxy = draft.proxies.find(p => p.name === config.name) - if (proxy) { + if (proxy != null) { proxy.history.push({ time: Date.now().toString(), delay: validDelay }) } }) @@ -50,20 +50,21 @@ export function Proxy (props: ProxyProps) { const delay = useMemo( () => config.history?.length ? config.history.slice(-1)[0].delay : 0, - [config] + [config], ) useLayoutEffect(() => { - EE.subscribe(Action.SPEED_NOTIFY, speedTest) - return () => EE.unsubscribe(Action.SPEED_NOTIFY, speedTest) + const handler = () => { speedTest() } + EE.subscribe(Action.SPEED_NOTIFY, handler) + return () => EE.unsubscribe(Action.SPEED_NOTIFY, handler) }, [speedTest]) const hasError = useMemo(() => delay === 0, [delay]) - const color = useMemo(() => - Object.keys(TagColors).find( - threshold => delay <= TagColors[threshold as keyof typeof TagColors] + const color = useMemo( + () => Object.keys(TagColors).find( + threshold => delay <= TagColors[threshold as keyof typeof TagColors], ), - [delay] + [delay], ) const backgroundColor = hasError ? undefined : color diff --git a/src/containers/Proxies/index.tsx b/src/containers/Proxies/index.tsx index 2fbf8a6..a29300a 100644 --- a/src/containers/Proxies/index.tsx +++ b/src/containers/Proxies/index.tsx @@ -17,12 +17,12 @@ enum sortType { const sortMap = { [sortType.None]: 'sort', [sortType.Asc]: 'sort-ascending', - [sortType.Desc]: 'sort-descending' + [sortType.Desc]: 'sort-descending', } export function compareDesc (a: API.Proxy, b: API.Proxy) { - const lastDelayA = a.history.length ? a.history.slice(-1)[0].delay : 0 - const lastDelayB = b.history.length ? b.history.slice(-1)[0].delay : 0 + const lastDelayA = (a.history.length > 0) ? a.history.slice(-1)[0].delay : 0 + const lastDelayB = (b.history.length > 0) ? b.history.slice(-1)[0].delay : 0 return (lastDelayB || Number.MAX_SAFE_INTEGER) - (lastDelayA || Number.MAX_SAFE_INTEGER) } @@ -35,7 +35,7 @@ function ProxyGroups () { const list = useMemo( () => general.mode === 'global' ? [global] : groups, - [general, groups, global] + [general, groups, global], ) return <> @@ -100,16 +100,16 @@ function Proxies () { } const { current: sort, next } = useRound( - [sortType.Asc, sortType.Desc, sortType.None] + [sortType.Asc, sortType.Desc, sortType.None], ) const sortedProxies = useMemo(() => { switch (sort) { - case sortType.Desc: - return proxies.slice().sort((a, b) => compareDesc(a, b)) - case sortType.Asc: - return proxies.slice().sort((a, b) => -1 * compareDesc(a, b)) - default: - return proxies.slice() + case sortType.Desc: + return proxies.slice().sort((a, b) => compareDesc(a, b)) + case sortType.Asc: + return proxies.slice().sort((a, b) => -1 * compareDesc(a, b)) + default: + return proxies.slice() } }, [sort, proxies]) const handleSort = next diff --git a/src/containers/Rules/Provider/index.tsx b/src/containers/Rules/Provider/index.tsx index 46d261f..ec964ec 100644 --- a/src/containers/Rules/Provider/index.tsx +++ b/src/containers/Rules/Provider/index.tsx @@ -23,7 +23,7 @@ export function Provider (props: ProvidersProps) { function handleUpdate () { show() - client.updateRuleProvider(provider.name).then(() => update()).finally(() => hide()) + client.updateRuleProvider(provider.name).then(async () => await update()).finally(() => hide()) } const updateClassnames = classnames('rule-provider-icon', { 'rule-provider-loading': visible }) diff --git a/src/containers/Settings/index.tsx b/src/containers/Settings/index.tsx index c1a423c..955bb49 100644 --- a/src/containers/Settings/index.tsx +++ b/src/containers/Settings/index.tsx @@ -23,7 +23,7 @@ export default function Settings () { const [info, set] = useObject({ socks5ProxyPort: 7891, httpProxyPort: 7890, - mixedProxyPort: 0 + mixedProxyPort: 0, }) useEffect(() => { @@ -39,12 +39,12 @@ export default function Settings () { async function handleStartAtLoginChange (state: boolean) { await jsBridge?.setStartAtLogin(state) - fetchClashXData() + await fetchClashXData() } async function handleSetSystemProxy (state: boolean) { await jsBridge?.setSystemProxy(state) - fetchClashXData() + await fetchClashXData() } function changeLanguage (language: Lang) { @@ -73,7 +73,7 @@ export default function Settings () { const { hostname: externalControllerHost, - port: externalControllerPort + port: externalControllerPort, } = apiInfo const { allowLan, mode } = general @@ -86,7 +86,7 @@ export default function Settings () { const options = [ { label: t('values.global'), value: 'Global' }, { label: t('values.rules'), value: 'Rule' }, - { label: t('values.direct'), value: 'Direct' } + { label: t('values.direct'), value: 'Direct' }, ] if (premium) { options.push({ label: t('values.script'), value: 'Script' }) diff --git a/src/containers/Sidebar/index.tsx b/src/containers/Sidebar/index.tsx index 19d46ed..672bdfa 100644 --- a/src/containers/Sidebar/index.tsx +++ b/src/containers/Sidebar/index.tsx @@ -7,12 +7,12 @@ import logo from '@assets/logo.png' import './style.scss' interface SidebarProps { - routes: { + routes: Array<{ path: string name: string noMobile?: boolean exact?: boolean - }[] + }> } export default function Sidebar (props: SidebarProps) { @@ -27,7 +27,7 @@ export default function Sidebar (props: SidebarProps) {
  • { t(name) }
  • - ) + ), ) return ( diff --git a/src/i18n/en_US.ts b/src/i18n/en_US.ts index 1179c22..fdcc375 100644 --- a/src/i18n/en_US.ts +++ b/src/i18n/en_US.ts @@ -6,7 +6,7 @@ const EN = { Rules: 'Rules', Settings: 'Setting', Connections: 'Connections', - Version: 'Version' + Version: 'Version', }, Settings: { title: 'Settings', @@ -19,7 +19,7 @@ const EN = { socks5ProxyPort: 'Socks5 proxy port', httpProxyPort: 'HTTP proxy port', mixedProxyPort: 'Mixed proxy port', - externalController: 'External controller' + externalController: 'External controller', }, values: { cn: '中文', @@ -27,7 +27,7 @@ const EN = { global: 'Global', rules: 'Rules', direct: 'Direct', - script: 'Script' + script: 'Script', }, versionString: 'Current ClashX is the latest version:{{version}}', checkUpdate: 'Check Update', @@ -36,17 +36,17 @@ const EN = { note: 'Please note that modifying this configuration will only configure Dashboard. Will not modify your Clash configuration file. Please make sure that the external controller address matches the address in the Clash configuration file, otherwise, Dashboard will not be able to connect to Clash.', host: 'Host', port: 'Port', - secret: 'Secret' - } + secret: 'Secret', + }, }, Logs: { - title: 'Logs' + title: 'Logs', }, Rules: { title: 'Rules', providerTitle: 'Providers', providerUpdateTime: 'Last updated at', - ruleCount: 'Rule count' + ruleCount: 'Rule count', }, Connections: { title: 'Connections', @@ -54,14 +54,14 @@ const EN = { total: { text: 'total', upload: 'upload', - download: 'download' + download: 'download', }, closeAll: { title: 'Warning', - content: 'This would close all connections' + content: 'This would close all connections', }, filter: { - all: 'All' + all: 'All', }, columns: { host: 'Host', @@ -73,8 +73,8 @@ const EN = { speed: 'Speed', upload: 'Upload', download: 'Download', - sourceIP: 'Source IP' - } + sourceIP: 'Source IP', + }, }, Proxies: { title: 'Proxies', @@ -91,7 +91,7 @@ const EN = { 'obfs-host': 'Obfs-host', uuid: 'UUID', alterId: 'AlterId', - tls: 'TLS' + tls: 'TLS', }, groupTitle: 'Policy Group', providerTitle: 'Providers', @@ -99,12 +99,12 @@ const EN = { expandText: 'Expand', collapseText: 'Collapse', speedTestText: 'Speed Test', - breakConnectionsText: 'Close connections which include the group' + breakConnectionsText: 'Close connections which include the group', }, Modal: { ok: 'Ok', - cancel: 'Cancel' - } + cancel: 'Cancel', + }, } export default EN diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 651fbd6..dd10430 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -3,7 +3,7 @@ import zh_CN from './zh_CN' export const Language = { en_US, - zh_CN + zh_CN, } export type Lang = keyof typeof Language diff --git a/src/i18n/zh_CN.ts b/src/i18n/zh_CN.ts index 0b2832d..0d0b0d6 100644 --- a/src/i18n/zh_CN.ts +++ b/src/i18n/zh_CN.ts @@ -6,7 +6,7 @@ const CN = { Rules: '规则', Settings: '设置', Connections: '连接', - Version: '版本' + Version: '版本', }, Settings: { title: '设置', @@ -19,7 +19,7 @@ const CN = { socks5ProxyPort: 'Socks5 代理端口', httpProxyPort: 'HTTP 代理端口', mixedProxyPort: '混合代理端口', - externalController: '外部控制设置' + externalController: '外部控制设置', }, values: { cn: '中文', @@ -27,7 +27,7 @@ const CN = { global: '全局', rules: '规则', direct: '直连', - script: '脚本' + script: '脚本', }, versionString: '当前 ClashX 已是最新版本:{{version}}', checkUpdate: '检查更新', @@ -36,17 +36,17 @@ const CN = { note: '请注意,修改该配置项并不会修改你的 Clash 配置文件,请确认修改后的外部控制地址和 Clash 配置文件内的地址一致,否则会导致 Dashboard 无法连接。', host: 'Host', port: '端口', - secret: '密钥' - } + secret: '密钥', + }, }, Logs: { - title: '日志' + title: '日志', }, Rules: { title: '规则', providerTitle: '规则集', providerUpdateTime: '最后更新于', - ruleCount: '规则条数' + ruleCount: '规则条数', }, Connections: { title: '连接', @@ -54,14 +54,14 @@ const CN = { total: { text: '总量', upload: '上传', - download: '下载' + download: '下载', }, closeAll: { title: '警告', - content: '将会关闭所有连接' + content: '将会关闭所有连接', }, filter: { - all: '全部' + all: '全部', }, columns: { host: '域名', @@ -73,8 +73,8 @@ const CN = { speed: '速率', upload: '上传', download: '下载', - sourceIP: '来源 IP' - } + sourceIP: '来源 IP', + }, }, Proxies: { title: '代理', @@ -91,7 +91,7 @@ const CN = { 'obfs-host': 'Obfs-host', uuid: 'UUID', alterId: 'AlterId', - tls: 'TLS' + tls: 'TLS', }, groupTitle: '策略组', providerTitle: '代理集', @@ -99,12 +99,12 @@ const CN = { expandText: '展开', collapseText: '收起', speedTestText: '测速', - breakConnectionsText: '切换时打断包含策略组的连接' + breakConnectionsText: '切换时打断包含策略组的连接', }, Modal: { ok: '确 定', - cancel: '取 消' - } + cancel: '取 消', + }, } export default CN diff --git a/src/lib/asyncSingleton.ts b/src/lib/asyncSingleton.ts index 86bb8e4..7f13046 100644 --- a/src/lib/asyncSingleton.ts +++ b/src/lib/asyncSingleton.ts @@ -2,11 +2,11 @@ export function createAsyncSingleton (fn: () => Promise): () => Promise let promise: Promise | null = null return async function () { - if (promise) { - return promise + if (promise != null) { + return await promise } promise = fn() - return promise + return await promise .catch(e => { promise = null throw e diff --git a/src/lib/hook.ts b/src/lib/hook.ts index ae7f640..d90161a 100644 --- a/src/lib/hook.ts +++ b/src/lib/hook.ts @@ -53,7 +53,7 @@ export function useInterval (callback: () => void, delay: number) { return () => clearInterval(id) } }, - [delay] + [delay], ) } diff --git a/src/lib/jsBridge.ts b/src/lib/jsBridge.ts index 4a6bc02..8ecc9cd 100644 --- a/src/lib/jsBridge.ts +++ b/src/lib/jsBridge.ts @@ -73,7 +73,7 @@ export class JsBridge { instance: JsBridgeAPI | null = null constructor (callback: () => void) { - if (window.WebViewJavascriptBridge) { + if (window.WebViewJavascriptBridge != null) { this.instance = window.WebViewJavascriptBridge } @@ -97,12 +97,12 @@ export class JsBridge { return callback?.(null) } - if (window.WebViewJavascriptBridge) { + if (window.WebViewJavascriptBridge != null) { return callback(window.WebViewJavascriptBridge) } // setup callback - if (window.WVJBCallbacks) { + if (window.WVJBCallbacks != null) { return window.WVJBCallbacks.push(callback) } @@ -115,63 +115,63 @@ export class JsBridge { setTimeout(() => document.documentElement.removeChild(WVJBIframe), 0) } - public callHandler (handleName: string, data?: any) { - return new Promise((resolve) => { + public async callHandler (handleName: string, data?: any) { + return await new Promise((resolve) => { this.instance?.callHandler( handleName, data, - resolve + resolve, ) }) } - public ping () { - return this.callHandler('ping') + public async ping () { + return await this.callHandler('ping') } - public readConfigString () { - return this.callHandler('readConfigString') + public async readConfigString () { + return await this.callHandler('readConfigString') } - public getPasteboard () { - return this.callHandler('getPasteboard') + public async getPasteboard () { + return await this.callHandler('getPasteboard') } - public getAPIInfo () { - return this.callHandler<{ host: string, port: string, secret: string }>('apiInfo') + public async getAPIInfo () { + return await this.callHandler<{ host: string, port: string, secret: string }>('apiInfo') } - public setPasteboard (data: string) { - return this.callHandler('setPasteboard', data) + public async setPasteboard (data: string) { + return await this.callHandler('setPasteboard', data) } - public writeConfigWithString (data: string) { - return this.callHandler('writeConfigWithString', data) + public async writeConfigWithString (data: string) { + return await this.callHandler('writeConfigWithString', data) } - public setSystemProxy (data: boolean) { - return this.callHandler('setSystemProxy', data) + public async setSystemProxy (data: boolean) { + return await this.callHandler('setSystemProxy', data) } - public getStartAtLogin () { - return this.callHandler('getStartAtLogin') + public async getStartAtLogin () { + return await this.callHandler('getStartAtLogin') } - public getProxyDelay (name: string) { - return this.callHandler('speedTest', name) + public async getProxyDelay (name: string) { + return await this.callHandler('speedTest', name) } - public setStartAtLogin (data: boolean) { - return this.callHandler('setStartAtLogin', data) + public async setStartAtLogin (data: boolean) { + return await this.callHandler('setStartAtLogin', data) } - public isSystemProxySet () { - return this.callHandler('isSystemProxySet') + public async isSystemProxySet () { + return await this.callHandler('isSystemProxySet') } } export function setupJsBridge (callback: () => void) { - if (jsBridge) { + if (jsBridge != null) { callback() return } diff --git a/src/lib/request.ts b/src/lib/request.ts index 0c69e44..c8289f5 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -94,32 +94,32 @@ export interface Connections { } export class Client { - private axiosClient: AxiosInstance - constructor(url: string, secret?: string) { + private readonly axiosClient: AxiosInstance + constructor (url: string, secret?: string) { this.axiosClient = axios.create({ baseURL: url, - headers: secret ? { Authorization: `Bearer ${secret}` } : {} + headers: secret ? { Authorization: `Bearer ${secret}` } : {}, }) } - getConfig() { - return this.axiosClient.get('configs') + async getConfig () { + return await this.axiosClient.get('configs') } - updateConfig(config: Partial) { - return this.axiosClient.patch('configs', config) + async updateConfig (config: Partial) { + return await this.axiosClient.patch('configs', config) } - getRules() { - return this.axiosClient.get('rules') + async getRules () { + return await this.axiosClient.get('rules') } async getProxyProviders () { const resp = await this.axiosClient.get('providers/proxies', { - validateStatus(status) { + validateStatus (status) { // compatible old version return (status >= 200 && status < 300) || status === 404 - } + }, }) if (resp.status === 404) { resp.data = { providers: {} } @@ -127,56 +127,56 @@ export class Client { return resp } - getRuleProviders () { - return this.axiosClient.get('providers/rules') + async getRuleProviders () { + return await this.axiosClient.get('providers/rules') } - updateProvider (name: string) { - return this.axiosClient.put(`providers/proxies/${encodeURIComponent(name)}`) + async updateProvider (name: string) { + return await this.axiosClient.put(`providers/proxies/${encodeURIComponent(name)}`) } - updateRuleProvider (name: string) { - return this.axiosClient.put(`providers/rules/${encodeURIComponent(name)}`) + async updateRuleProvider (name: string) { + return await this.axiosClient.put(`providers/rules/${encodeURIComponent(name)}`) } - healthCheckProvider (name: string) { - return this.axiosClient.get(`providers/proxies/${encodeURIComponent(name)}/healthcheck`) + async healthCheckProvider (name: string) { + return await this.axiosClient.get(`providers/proxies/${encodeURIComponent(name)}/healthcheck`) } - getProxies () { - return this.axiosClient.get('proxies') + async getProxies () { + return await this.axiosClient.get('proxies') } - getProxy (name: string) { - return this.axiosClient.get(`proxies/${encodeURIComponent(name)}`) + async getProxy (name: string) { + return await this.axiosClient.get(`proxies/${encodeURIComponent(name)}`) } - getVersion () { - return this.axiosClient.get<{ version: string, premium?: boolean }>('version') + async getVersion () { + return await this.axiosClient.get<{ version: string, premium?: boolean }>('version') } - getProxyDelay (name: string) { - return this.axiosClient.get<{ delay: number }>(`proxies/${encodeURIComponent(name)}/delay`, { + async getProxyDelay (name: string) { + return await this.axiosClient.get<{ delay: number }>(`proxies/${encodeURIComponent(name)}/delay`, { params: { timeout: 5000, - url: 'http://www.gstatic.com/generate_204' - } + url: 'http://www.gstatic.com/generate_204', + }, }) } - closeAllConnections () { - return this.axiosClient.delete('connections') + async closeAllConnections () { + return await this.axiosClient.delete('connections') } - closeConnection (id: string) { - return this.axiosClient.delete(`connections/${id}`) + async closeConnection (id: string) { + return await this.axiosClient.delete(`connections/${id}`) } - getConnections () { - return this.axiosClient.get('connections') + async getConnections () { + return await this.axiosClient.get('connections') } - changeProxySelected (name: string, select: string) { - return this.axiosClient.put(`proxies/${encodeURIComponent(name)}`, { name: select }) + async changeProxySelected (name: string, select: string) { + return await this.axiosClient.put(`proxies/${encodeURIComponent(name)}`, { name: select }) } } diff --git a/src/lib/streamer.ts b/src/lib/streamer.ts index 6d88047..f11404d 100644 --- a/src/lib/streamer.ts +++ b/src/lib/streamer.ts @@ -21,9 +21,9 @@ export class StreamReader { { bufferLength: 0, retryInterval: 5000, - headers: {} + headers: {}, }, - config + config, ) this.config.useWebsocket @@ -60,13 +60,13 @@ export class StreamReader { this.config.url, { mode: 'cors', - headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {} - } + headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}, + }, ), e => e as Error) if (result.isErr()) { this.retry(result.error) return - } else if (!result.value.body) { + } else if (result.value.body == null) { this.retry(new Error('fetch body error')) return } @@ -87,7 +87,7 @@ export class StreamReader { const lines = decoder.decode(result.value.value).trim().split('\n') const data = lines.map(l => JSON.parse(l)) this.EE.emit('data', data) - if (this.config.bufferLength! > 0) { + if (this.config.bufferLength > 0) { this.innerBuffer.push(...data) if (this.innerBuffer.length > this.config.bufferLength) { this.innerBuffer.splice(0, this.innerBuffer.length - this.config.bufferLength) @@ -99,7 +99,7 @@ export class StreamReader { protected retry (err: Error) { if (!this.isClose) { this.EE.emit('error', err) - window.setTimeout(this.loop, this.config.retryInterval) + window.setTimeout(() => { this.loop() }, this.config.retryInterval) } } diff --git a/src/models/Cipher.ts b/src/models/Cipher.ts index 048b901..25afe8d 100644 --- a/src/models/Cipher.ts +++ b/src/models/Cipher.ts @@ -20,7 +20,7 @@ export const SsCipher = [ 'AES-256-CFB', 'CHACHA20', 'CHACHA20-IETF', - 'XCHACHA20' + 'XCHACHA20', ] /** @@ -31,7 +31,7 @@ export const VmessCipher = [ 'auto', 'none', 'aes-128-gcm', - 'chacha20-poly1305' + 'chacha20-poly1305', ] /** @@ -41,17 +41,17 @@ export function pickCipherWithAlias (c: string) { const cipher = c.toUpperCase() switch (cipher) { - case 'CHACHA20-IETF-POLY1305': - return 'AEAD_CHACHA20_POLY1305' - case 'XCHACHA20-IETF-POLY1305': - return 'AEAD_XCHACHA20_POLY1305' - case 'AES-128-GCM': - return 'AEAD_AES_128_GCM' - case 'AES-196-GCM': - return 'AEAD_AES_196_GCM' - case 'AES-256-GCM': - return 'AEAD_AES_256_GCM' + case 'CHACHA20-IETF-POLY1305': + return 'AEAD_CHACHA20_POLY1305' + case 'XCHACHA20-IETF-POLY1305': + return 'AEAD_XCHACHA20_POLY1305' + case 'AES-128-GCM': + return 'AEAD_AES_128_GCM' + case 'AES-196-GCM': + return 'AEAD_AES_196_GCM' + case 'AES-256-GCM': + return 'AEAD_AES_256_GCM' } - return SsCipher.find(c => c === cipher) || '' + return SsCipher.find(c => c === cipher) ?? '' } diff --git a/src/models/Proxy.ts b/src/models/Proxy.ts index ad0e44c..f823222 100644 --- a/src/models/Proxy.ts +++ b/src/models/Proxy.ts @@ -5,13 +5,13 @@ export const ProxyType = { Shadowsocks: 'ss', Vmess: 'vmess', - Socks5: 'socks5' + Socks5: 'socks5', } export type Proxy = ShadowsocksProxy & VmessProxy & Socks5Proxy export const SsProxyConfigList = [ - 'name', 'type', 'server', 'port', 'cipher', 'password', 'obfs', 'obfs-host' + 'name', 'type', 'server', 'port', 'cipher', 'password', 'obfs', 'obfs-host', ] export interface ShadowsocksProxy { name?: string @@ -32,7 +32,7 @@ export interface ShadowsocksProxy { } export const VmessProxyConfigList = [ - 'name', 'type', 'server', 'port', 'uuid', 'alterid', 'cipher', 'tls' + 'name', 'type', 'server', 'port', 'uuid', 'alterid', 'cipher', 'tls', ] export interface VmessProxy { name?: string diff --git a/src/stores/jotai.ts b/src/stores/jotai.ts index a2525c1..eece51e 100644 --- a/src/stores/jotai.ts +++ b/src/stores/jotai.ts @@ -34,7 +34,7 @@ export function useI18n () { } return { t } }, - [lang] + [lang], ) return { lang, locales, setLang, translation } @@ -42,7 +42,7 @@ export function useI18n () { export const version = atom({ version: '', - premium: false + premium: false, }) export function useVersion () { @@ -57,7 +57,7 @@ export function useVersion () { set( result.isErr() ? { version: '', premium: false } - : { version: result.value.data.version, premium: !!result.value.data.premium } + : { version: result.value.data.version, premium: !!result.value.data.premium }, ) }) @@ -83,7 +83,7 @@ export function useRuleProviders () { } export const configAtom = atomWithStorage('profile', { - breakConnections: false + breakConnections: false, }) export function useConfig () { @@ -128,7 +128,7 @@ export function useGeneral () { redirPort: data['redir-port'], mode: data.mode.toLowerCase() as Models.Data['general']['mode'], logLevel: data['log-level'], - allowLan: data['allow-lan'] + allowLan: data['allow-lan'], } as Models.Data['general'] }) @@ -143,8 +143,8 @@ export const proxies = atomWithImmer({ type: 'Selector', now: '', history: [], - all: [] - } as API.Group + all: [], + } as API.Group, }) export function useProxy () { @@ -187,7 +187,7 @@ export function useProxy () { global: allProxy.global, update: mutate, markProxySelected, - set + set, } } @@ -196,7 +196,7 @@ export const proxyMapping = atom((get) => { const providers = get(proxyProvider) const proxyMap = new Map() for (const p of ps.proxies) { - proxyMap.set(p.name, p as API.Proxy) + proxyMap.set(p.name, p) } for (const provider of providers) { @@ -214,7 +214,7 @@ export function useClashXData () { return { isClashX: false, startAtLogin: false, - systemProxy: false + systemProxy: false, } } @@ -244,7 +244,7 @@ export function useRule () { const logsAtom = atom({ key: '', - instance: null as StreamReader | null + instance: null as StreamReader | null, }) export function useLogsStreamReader () { @@ -269,7 +269,7 @@ export function useLogsStreamReader () { const instance = new StreamReader({ url: logUrl, bufferLength: 200, token: apiInfo.secret, useWebsocket }) setItem({ key, instance }) - if (oldInstance) { + if (oldInstance != null) { oldInstance.destory() } @@ -285,6 +285,6 @@ export function useConnectionStreamReader () { const url = `${apiInfo.protocol}//${apiInfo.hostname}:${apiInfo.port}/connections` return useMemo( () => version.version ? new StreamReader({ url, bufferLength: 200, token: apiInfo.secret, useWebsocket }) : null, - [apiInfo.secret, url, useWebsocket, version.version] + [apiInfo.secret, url, useWebsocket, version.version], ) } diff --git a/src/stores/request.ts b/src/stores/request.ts index ff56654..7ef9de6 100644 --- a/src/stores/request.ts +++ b/src/stores/request.ts @@ -1,8 +1,8 @@ -import { atom, useAtom } from "jotai"; -import { isClashX, jsBridge } from "@lib/jsBridge"; -import { atomWithStorage, useAtomValue } from "jotai/utils"; -import { useLocation } from "react-use"; -import { Client } from "@lib/request"; +import { atom, useAtom } from 'jotai' +import { isClashX, jsBridge } from '@lib/jsBridge' +import { atomWithStorage, useAtomValue } from 'jotai/utils' +import { useLocation } from 'react-use' +import { Client } from '@lib/request' const clashxConfigAtom = atom(async () => { if (!isClashX()) { @@ -14,29 +14,29 @@ const clashxConfigAtom = atom(async () => { hostname: info.host, port: info.port, secret: info.secret, - protocol: 'http:' + protocol: 'http:', } }) -export const localStorageAtom = atomWithStorage<{ - hostname: string; - port: string; - secret: string; -}[]>('externalControllers', []) +export const localStorageAtom = atomWithStorage>('externalControllers', []) -export function useAPIInfo() { +export function useAPIInfo () { const clashx = useAtomValue(clashxConfigAtom) const location = useLocation() const localStorage = useAtomValue(localStorageAtom) - if (clashx) { + if (clashx != null) { return clashx } - let url: URL | undefined; + let url: URL | undefined { const meta = document.querySelector('meta[name="external-controller"]') - if (meta?.content?.match(/^https?:/)) { + if ((meta?.content?.match(/^https?:/)) != null) { // [protocol]://[secret]@[hostname]:[port] url = new URL(meta.content) } @@ -54,15 +54,15 @@ export function useAPIInfo() { const clientAtom = atom({ key: '', - instance: null as Client | null + instance: null as Client | null, }) -export function useClient() { +export function useClient () { const { hostname, port, secret, - protocol + protocol, } = useAPIInfo() const [item, setItem] = useAtom(clientAtom) diff --git a/yarn.lock b/yarn.lock index 5fd32d7..bb4b66b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -422,6 +422,16 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/parser@^4.0.0": + version "4.28.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.1.tgz#5181b81658414f47291452c15bf6cd44a32f85bd" + integrity sha512-UjrMsgnhQIIK82hXGaD+MCN8IfORS1CbMdu7VlZbYa8LCZtbZjJA26De4IPQB7XYZbL8gJ99KWNj0l6WD0guJg== + dependencies: + "@typescript-eslint/scope-manager" "4.28.1" + "@typescript-eslint/types" "4.28.1" + "@typescript-eslint/typescript-estree" "4.28.1" + debug "^4.3.1" + "@typescript-eslint/parser@^4.28.0": version "4.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.0.tgz#2404c16751a28616ef3abab77c8e51d680a12caa" @@ -440,11 +450,24 @@ "@typescript-eslint/types" "4.28.0" "@typescript-eslint/visitor-keys" "4.28.0" +"@typescript-eslint/scope-manager@4.28.1": + version "4.28.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.1.tgz#fd3c20627cdc12933f6d98b386940d8d0ce8a991" + integrity sha512-o95bvGKfss6705x7jFGDyS7trAORTy57lwJ+VsYwil/lOUxKQ9tA7Suuq+ciMhJc/1qPwB3XE2DKh9wubW8YYA== + dependencies: + "@typescript-eslint/types" "4.28.1" + "@typescript-eslint/visitor-keys" "4.28.1" + "@typescript-eslint/types@4.28.0": version "4.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.0.tgz#a33504e1ce7ac51fc39035f5fe6f15079d4dafb0" integrity sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA== +"@typescript-eslint/types@4.28.1": + version "4.28.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.1.tgz#d0f2ecbef3684634db357b9bbfc97b94b828f83f" + integrity sha512-4z+knEihcyX7blAGi7O3Fm3O6YRCP+r56NJFMNGsmtdw+NCdpG5SgNz427LS9nQkRVTswZLhz484hakQwB8RRg== + "@typescript-eslint/typescript-estree@4.28.0": version "4.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz#e66d4e5aa2ede66fec8af434898fe61af10c71cf" @@ -458,6 +481,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@4.28.1": + version "4.28.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.1.tgz#af882ae41740d1f268e38b4d0fad21e7e8d86a81" + integrity sha512-GhKxmC4sHXxHGJv8e8egAZeTZ6HI4mLU6S7FUzvFOtsk7ZIDN1ksA9r9DyOgNqowA9yAtZXV0Uiap61bIO81FQ== + dependencies: + "@typescript-eslint/types" "4.28.1" + "@typescript-eslint/visitor-keys" "4.28.1" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/visitor-keys@4.28.0": version "4.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz#255c67c966ec294104169a6939d96f91c8a89434" @@ -466,6 +502,14 @@ "@typescript-eslint/types" "4.28.0" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@4.28.1": + version "4.28.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.1.tgz#162a515ee255f18a6068edc26df793cdc1ec9157" + integrity sha512-K4HMrdFqr9PFquPu178SaSb92CaWe2yErXyPumc8cYWxFmhgJsNY9eSePmO05j0JhBvf2Cdhptd6E6Yv9HVHcg== + dependencies: + "@typescript-eslint/types" "4.28.1" + eslint-visitor-keys "^2.0.0" + "@vitejs/plugin-react-refresh@^1.3.3": version "1.3.3" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-refresh/-/plugin-react-refresh-1.3.3.tgz#d5afb3e0463f368a8afadfdd7305fe5c5fe78a6a" @@ -1016,6 +1060,19 @@ eslint-config-react-app@^6.0.0: dependencies: confusing-browser-globals "^1.0.10" +eslint-config-standard-with-typescript@^20.0.0: + version "20.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-20.0.0.tgz#0c550eca0a216cbf8da9013eb6e311acd3102d87" + integrity sha512-IoySf3r0a2+P3Z6GMjv8p1HuOQ6GWQbMpdt9G8uEbkGpnNWAGBXpgaiutbZHbaQAvG5pkVtYepCfHUxYbVDLCA== + dependencies: + "@typescript-eslint/parser" "^4.0.0" + eslint-config-standard "^16.0.0" + +eslint-config-standard@^16.0.0: + version "16.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516" + integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg== + eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" @@ -1032,6 +1089,14 @@ eslint-module-utils@^2.6.1: debug "^3.2.7" pkg-dir "^2.0.0" +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-flowtype@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.7.2.tgz#482a42fe5d15ee614652ed256d37543d584d7bc0" @@ -1078,6 +1143,23 @@ eslint-plugin-jsx-a11y@^6.4.1: jsx-ast-utils "^3.1.0" language-tags "^1.0.5" +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-promise@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz#fb2188fb734e4557993733b41aa1a688f46c6f24" + integrity sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng== + eslint-plugin-react-hooks@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" @@ -1109,7 +1191,7 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^2.1.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== @@ -1469,7 +1551,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: +ignore@^5.1.1, ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -2258,6 +2340,11 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" +regexpp@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" @@ -2283,7 +2370,7 @@ resolve-pathname@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.20.0: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -2362,7 +2449,7 @@ screenfull@^5.1.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.3.0: +semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==