mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
Feature: use websocket api
This commit is contained in:
parent
d66cf8f9fa
commit
da255fa38c
152
package-lock.json
generated
152
package-lock.json
generated
@ -101,6 +101,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -956,6 +962,12 @@
|
|||||||
"lodash": "^4.17.13",
|
"lodash": "^4.17.13",
|
||||||
"to-fast-properties": "^2.0.0"
|
"to-fast-properties": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1250,6 +1262,12 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/semver": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-G1Ggy7/9Nsa1Jt2yiBR2riEuyK2DFNnqow6R7cromXPMNynackRY1vqFTLz/gwnef1LHokbXThcPhqMRjUbkpQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/unist": {
|
"@types/unist": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
|
||||||
@ -2232,6 +2250,15 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -2272,6 +2299,15 @@
|
|||||||
"bin-version": "^3.0.0",
|
"bin-version": "^3.0.0",
|
||||||
"semver": "^5.6.0",
|
"semver": "^5.6.0",
|
||||||
"semver-truncate": "^1.1.2"
|
"semver-truncate": "^1.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bin-wrapper": {
|
"bin-wrapper": {
|
||||||
@ -3927,6 +3963,14 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -5851,6 +5895,15 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -6627,6 +6680,15 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -6695,6 +6757,15 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -7804,6 +7875,14 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"pify": "^4.0.1",
|
"pify": "^4.0.1",
|
||||||
"semver": "^5.6.0"
|
"semver": "^5.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mamacro": {
|
"mamacro": {
|
||||||
@ -8404,6 +8483,14 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"normalize-package-data": {
|
"normalize-package-data": {
|
||||||
@ -8416,6 +8503,14 @@
|
|||||||
"resolve": "^1.10.0",
|
"resolve": "^1.10.0",
|
||||||
"semver": "2 || 3 || 4 || 5",
|
"semver": "2 || 3 || 4 || 5",
|
||||||
"validate-npm-package-license": "^3.0.1"
|
"validate-npm-package-license": "^3.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
@ -8773,6 +8868,14 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -9222,6 +9325,15 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"execa": {
|
"execa": {
|
||||||
@ -10475,10 +10587,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.7.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
|
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"semver-regex": {
|
"semver-regex": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -10495,6 +10606,15 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
@ -12343,6 +12463,14 @@
|
|||||||
"semver": "^5.3.0",
|
"semver": "^5.3.0",
|
||||||
"tslib": "^1.8.0",
|
"tslib": "^1.8.0",
|
||||||
"tsutils": "^2.29.0"
|
"tsutils": "^2.29.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslint-config-standard": {
|
"tslint-config-standard": {
|
||||||
@ -12393,6 +12521,14 @@
|
|||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"rimraf": "^2.4.4",
|
"rimraf": "^2.4.4",
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tsutils": {
|
"tsutils": {
|
||||||
@ -13096,6 +13232,14 @@
|
|||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"shebang-command": "^1.2.0",
|
"shebang-command": "^1.2.0",
|
||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"@types/react-router-dom": "^5.1.0",
|
"@types/react-router-dom": "^5.1.0",
|
||||||
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
||||||
"@types/react-window": "^1.8.1",
|
"@types/react-window": "^1.8.1",
|
||||||
|
"@types/semver": "^6.0.2",
|
||||||
"autoprefixer": "^9.6.1",
|
"autoprefixer": "^9.6.1",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
@ -83,6 +84,7 @@
|
|||||||
"react-router-dom": "^5.1.1",
|
"react-router-dom": "^5.1.1",
|
||||||
"react-virtualized-auto-sizer": "^1.0.2",
|
"react-virtualized-auto-sizer": "^1.0.2",
|
||||||
"react-window": "^1.8.5",
|
"react-window": "^1.8.5",
|
||||||
|
"semver": "^6.3.0",
|
||||||
"unstated-next": "^1.1.0",
|
"unstated-next": "^1.1.0",
|
||||||
"use-immer": "^0.3.4"
|
"use-immer": "^0.3.4"
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ export default function Proxies () {
|
|||||||
|
|
||||||
const [sort, setSort] = useState(sortType.None)
|
const [sort, setSort] = useState(sortType.None)
|
||||||
const proxies = useMemo(() => {
|
const proxies = useMemo(() => {
|
||||||
console.log(1)
|
|
||||||
switch (sort) {
|
switch (sort) {
|
||||||
case sortType.Desc:
|
case sortType.Desc:
|
||||||
return data.proxy.slice().sort((a, b) => compareDesc(a, b))
|
return data.proxy.slice().sort((a, b) => compareDesc(a, b))
|
||||||
|
29
src/lib/asyncSingleton.ts
Normal file
29
src/lib/asyncSingleton.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export function createAsyncSingleton<T> (fn: () => Promise<T>): () => Promise<T> {
|
||||||
|
let promise: Promise<T> | null = null
|
||||||
|
let instance: T | null = null
|
||||||
|
|
||||||
|
async function fetch () {
|
||||||
|
if (promise) {
|
||||||
|
return promise
|
||||||
|
}
|
||||||
|
|
||||||
|
promise = fn()
|
||||||
|
return promise
|
||||||
|
.then(r => {
|
||||||
|
promise = null
|
||||||
|
return r
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
promise = null
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return async function () {
|
||||||
|
if (instance) {
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch()
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
import axios, { AxiosInstance } from 'axios'
|
import axios from 'axios'
|
||||||
import { Partial, getLocalStorageItem } from '@lib/helper'
|
import { Partial, getLocalStorageItem, to } from '@lib/helper'
|
||||||
import { isClashX, jsBridge } from '@lib/jsBridge'
|
import { isClashX, jsBridge } from '@lib/jsBridge'
|
||||||
|
import { createAsyncSingleton } from '@lib/asyncSingleton'
|
||||||
import { Log } from '@models/Log'
|
import { Log } from '@models/Log'
|
||||||
import { StreamReader } from './streamer'
|
import { StreamReader } from './streamer'
|
||||||
|
|
||||||
let instance: AxiosInstance
|
|
||||||
let logsStreamReader: StreamReader<Log> = null
|
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
port: number
|
port: number
|
||||||
'socks-port': number
|
'socks-port': number
|
||||||
@ -51,6 +49,19 @@ export interface Group {
|
|||||||
history: History[]
|
history: History[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getInstance = createAsyncSingleton(async () => {
|
||||||
|
const {
|
||||||
|
hostname,
|
||||||
|
port,
|
||||||
|
secret
|
||||||
|
} = await getExternalControllerConfig()
|
||||||
|
|
||||||
|
return axios.create({
|
||||||
|
baseURL: `//${hostname}:${port}`,
|
||||||
|
headers: secret ? { Authorization: `Bearer ${secret}` } : {}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
export async function getConfig () {
|
export async function getConfig () {
|
||||||
const req = await getInstance()
|
const req = await getInstance()
|
||||||
return req.get<Config>('configs')
|
return req.get<Config>('configs')
|
||||||
@ -81,6 +92,11 @@ export async function getProxy (name: string) {
|
|||||||
return req.get<Proxy>(`proxies/${name}`)
|
return req.get<Proxy>(`proxies/${name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getVersion () {
|
||||||
|
const req = await getInstance()
|
||||||
|
return req.get<{ version: string }>('version')
|
||||||
|
}
|
||||||
|
|
||||||
export async function getProxyDelay (name: string) {
|
export async function getProxyDelay (name: string) {
|
||||||
const req = await getInstance()
|
const req = await getInstance()
|
||||||
return req.get<{ delay: number }>(`proxies/${name}/delay`, {
|
return req.get<{ delay: number }>(`proxies/${name}/delay`, {
|
||||||
@ -96,25 +112,6 @@ export async function changeProxySelected (name: string, select: string) {
|
|||||||
return req.put<void>(`proxies/${name}`, { name: select })
|
return req.put<void>(`proxies/${name}`, { name: select })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInstance () {
|
|
||||||
if (instance) {
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
hostname,
|
|
||||||
port,
|
|
||||||
secret
|
|
||||||
} = await getExternalControllerConfig()
|
|
||||||
|
|
||||||
instance = axios.create({
|
|
||||||
baseURL: `//${hostname}:${port}`,
|
|
||||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {}
|
|
||||||
})
|
|
||||||
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getExternalControllerConfig () {
|
export async function getExternalControllerConfig () {
|
||||||
if (isClashX()) {
|
if (isClashX()) {
|
||||||
const info = await jsBridge.getAPIInfo()
|
const info = await jsBridge.getAPIInfo()
|
||||||
@ -137,14 +134,12 @@ export async function getExternalControllerConfig () {
|
|||||||
return { hostname, port, secret }
|
return { hostname, port, secret }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLogsStreamReader () {
|
export const getLogsStreamReader = createAsyncSingleton(async function getLogsStreamReader () {
|
||||||
if (logsStreamReader) {
|
|
||||||
return logsStreamReader
|
|
||||||
}
|
|
||||||
const externalController = await getExternalControllerConfig()
|
const externalController = await getExternalControllerConfig()
|
||||||
const { data: config } = await getConfig()
|
const { data: config } = await getConfig()
|
||||||
const logUrl = `//${externalController.hostname}:${externalController.port}/logs?level=${config['log-level']}`
|
const [data, err] = await to(getVersion())
|
||||||
const auth = externalController.secret ? { Authorization: `Bearer ${externalController.secret}` } : {}
|
const version = err ? 'unkonwn version' : data.data.version
|
||||||
logsStreamReader = new StreamReader({ url: logUrl, bufferLength: 200, headers: auth })
|
|
||||||
return logsStreamReader
|
const logUrl = `${location.protocol}//${externalController.hostname}:${externalController.port}/logs?level=${config['log-level']}`
|
||||||
}
|
return new StreamReader<Log>({ url: logUrl, bufferLength: 200, token: externalController.secret, version })
|
||||||
|
})
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { to } from '@lib/helper'
|
import { to } from '@lib/helper'
|
||||||
|
import semver from 'semver'
|
||||||
import EventEmitter from 'eventemitter3'
|
import EventEmitter from 'eventemitter3'
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
url: string
|
url: string
|
||||||
headers?: { [key: string]: string }
|
version: string
|
||||||
|
token?: string
|
||||||
bufferLength?: number
|
bufferLength?: number
|
||||||
retryInterval?: number
|
retryInterval?: number
|
||||||
}
|
}
|
||||||
@ -24,15 +26,43 @@ export class StreamReader<T> {
|
|||||||
config
|
config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (semver.valid(config.version) && semver.gt(config.version, 'v0.15.0-52-gc384693')) {
|
||||||
|
this.websocketLoop()
|
||||||
|
return
|
||||||
|
}
|
||||||
this.loop()
|
this.loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected websocketLoop () {
|
||||||
|
const url = new URL(this.config.url)
|
||||||
|
url.protocol = location.protocol === 'http:' ? 'ws:' : 'wss:'
|
||||||
|
url.searchParams.set('token', this.config.token)
|
||||||
|
|
||||||
|
const connection = new WebSocket(url.toJSON())
|
||||||
|
connection.addEventListener('message', msg => {
|
||||||
|
const data = JSON.parse(msg.data)
|
||||||
|
this.EE.emit('data', [data])
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
connection.addEventListener('close', () => setTimeout(this.websocketLoop, this.config.retryInterval))
|
||||||
|
connection.addEventListener('error', err => {
|
||||||
|
this.EE.emit('error', err)
|
||||||
|
setTimeout(this.websocketLoop, this.config.retryInterval)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
protected async loop () {
|
protected async loop () {
|
||||||
const [resp, err] = await to(fetch(
|
const [resp, err] = await to(fetch(
|
||||||
this.config.url,
|
this.config.url,
|
||||||
{
|
{
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
headers: this.config.headers
|
headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -76,6 +76,7 @@ export interface APIInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
|
version?: string
|
||||||
|
|
||||||
general?: {
|
general?: {
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import { useI18n } from '@i18n'
|
|||||||
|
|
||||||
function useData () {
|
function useData () {
|
||||||
const [data, set] = useObject<Models.Data>({
|
const [data, set] = useObject<Models.Data>({
|
||||||
|
version: '',
|
||||||
general: {},
|
general: {},
|
||||||
proxy: [],
|
proxy: [],
|
||||||
proxyGroup: [],
|
proxyGroup: [],
|
||||||
@ -56,6 +57,13 @@ function useData () {
|
|||||||
proxyGroup: general.mode === 'Global' ? [proxyList] : groups as API.Group[],
|
proxyGroup: general.mode === 'Global' ? [proxyList] : groups as API.Group[],
|
||||||
rules: rules.data.rules
|
rules: rules.data.rules
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [version, vErr] = await to(API.getVersion())
|
||||||
|
if (vErr) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set('version', version.data.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDelay (proxy: string, delay: number) {
|
function updateDelay (proxy: string, delay: number) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user