feat: add tauri-plugin-mihomo

This commit is contained in:
oomeow
2025-10-01 09:28:40 +08:00
parent 1b4691d0ac
commit f905969ed8
150 changed files with 8411 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
MIHOMO_SOCKET=1
+14
View File
@@ -0,0 +1,14 @@
# Generated by Cargo
# will have compiled files and executables
/target/
WixTools
frontend
Cargo.lock
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas
permissions/*
!permissions/default.toml
@@ -0,0 +1,48 @@
fail_fast: true
repos:
# prek has build-in pre-commit hooks
# - repo: "https://github.com/pre-commit/pre-commit-hooks"
# rev: v5.0.0
# hooks:
# - id: trailing-whitespace
# - id: end-of-file-fixer
# - id: check-yaml
# - id: check-toml
# - id: check-added-large-files
# this will check typos and fix file automatically, but need to re-add file by using git
- repo: https://github.com/crate-ci/typos
rev: v1.36.2
hooks:
- id: typos
- repo: local
hooks:
# wait for `running multiple commands` feature to complete (https://github.com/j178/prek/issues/431)
# cargo fmt
- id: cargo-fmt
name: cargo fmt
description: Format files with rustfmt.
entry: cargo +nightly fmt -- --check
language: system
types:
- rust
# cargo check
- id: cargo-check
name: cargo check
description: Check the package for errors.
entry: cargo check --all
language: system
types:
- rust
pass_filenames: false
# cargo clippy
- id: cargo-clippy
name: cargo clippy
description: Lint rust sources
entry: cargo clippy --all-targets --all-features --tests --benches -- -D warnings
language: system
types:
- rust
pass_filenames: false
+35
View File
@@ -0,0 +1,35 @@
[package]
name = "tauri-plugin-mihomo"
version = "0.1.0"
authors = ["oomeow"]
description = "http or ipc api for mihomo"
edition = "2024"
exclude = ["/examples", "/dist-js", "/guest-js", "/node_modules"]
links = "tauri-plugin-mihomo"
[dependencies]
tauri = { version = "2" }
thiserror = "2"
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
futures-util = "0.3"
tokio = { version = "1", features = ["net", "sync", "macros"] }
tokio-tungstenite = { version = "0.27" }
rand = "0.9"
http = "1.3"
base64 = "0.22"
httparse = "1.10"
log = "0.4"
urlencoding = "2.1"
ts-rs = "11.0"
pin-project = "1.1.10"
[target.'cfg(windows)'.dependencies]
windows-sys = "0.59"
[build-dependencies]
tauri-plugin = { version = "2", features = ["build"] }
[dev-dependencies]
dotenvy = "=0.15.7"
+23
View File
@@ -0,0 +1,23 @@
# Tauri Plugin mihomo
一个基于 Tauri 框架的调用 Mihomo API 插件,支持 Mihomo 的 HTTP 和 Socket 通信
### 测试 Mimoho 所有 API 的接口状态
推荐使用 [nextest](https://github.com/nextest-rs/nextest) (一款更干净美观、速度更快的跨平台测试运行器)进行单元测试
默认使用 socket 连接 Mihomo 测试,可通过设置 `MIHOMO_SOCKET` 环境变量来使用 http 连接 Mihomo 测试
> 修改 `.env` 配置文件,将 `MIHOMO_SOCKET` 设置为 `0`, 再执行单元测试
```shell
# 此命令会排除 restart/reload_config 方法, 因为这两个接口都会让内核重新加载配置文件,会导致其他测试用例错误
cargo nextest run mihomo_
# --------------------------
# 测试 reload_config 方法
cargo nextest run reload
# 测试 restart 方法
cargo nextest run restart
```
+47
View File
@@ -0,0 +1,47 @@
const COMMANDS: &[&str] = &[
"update_controller",
"update_secret",
"get_version",
"flush_fakeip",
"flush_dns",
"get_connections",
"close_all_connections",
"close_connections",
"get_groups",
"get_group_by_name",
"delay_group",
"get_proxy_providers",
"get_proxy_provider_by_name",
"update_proxy_provider",
"healthcheck_proxy_provider",
"healthcheck_node_in_provider",
"get_proxies",
"get_proxy_by_name",
"select_node_for_group",
"unfixed_proxy",
"delay_proxy_by_name",
"get_rules",
"get_rule_providers",
"update_rule_provider",
"get_base_config",
"reload_config",
"patch_base_config",
"update_geo",
"restart",
"upgrade_core",
"upgrade_ui",
"upgrade_geo",
"ws_traffic",
"ws_memory",
"ws_connections",
"ws_logs",
"ws_disconnect",
"clear_all_ws_connections",
];
fn main() {
tauri_plugin::Builder::new(COMMANDS)
.android_path("android")
.ios_path("ios")
.build();
}
@@ -0,0 +1,46 @@
import type { ClashMode } from "./ClashMode";
import type { FindProcessMode } from "./FindProcessMode";
import type { GeoXUrl } from "./GeoXUrl";
import type { LogLevel } from "./LogLevel";
import type { TuicServer } from "./TuicServer";
import type { TunConfig } from "./TunConfig";
export type BaseConfig = {
port: number;
socksPort: number;
redirPort: number;
tproxyPort: number;
mixedPort: number;
tun: TunConfig;
tuicServer: TuicServer;
ssConfig: string;
vmessConfig: string;
authentication: Array<string> | null;
skipAuthPrefixes: Array<string> | null;
lanAllowedIps: Array<string> | null;
lanDisallowedIps: Array<string> | null;
allowLan: boolean;
bindAddress: string;
inboundTfo: boolean;
inboundMptcp: boolean;
mode: ClashMode;
unifiedDelay: boolean;
logLevel: LogLevel;
ipv6: boolean;
interfaceName: string;
routingMark: number;
geoxUrl: GeoXUrl;
geoAutoUpdate: boolean;
geoUpdateInterval: number;
geodataMode: boolean;
geodataLoader: string;
geositeMatcher: string;
tcpConcurrent: boolean;
findProcessMode: FindProcessMode;
sniffing: boolean;
globalClientFingerprint: string;
globalUa: string;
etagSupport: boolean;
keepAliveInterval: number;
keepAliveIdle: number;
disableKeepAlive: boolean;
};
@@ -0,0 +1,5 @@
export type BrutalOption = {
enabled: boolean;
up?: string;
down?: string;
};
@@ -0,0 +1,4 @@
/**
* clash mode enum
*/
export type ClashMode = "rule" | "global" | "direct";
@@ -0,0 +1,11 @@
import type { ConnectionMetaData } from "./ConnectionMetaData";
export type Connection = {
id: string;
metadata: ConnectionMetaData;
upload: bigint;
download: bigint;
start: string;
chains: Array<string>;
rule: string;
rulePayload: string;
};
@@ -0,0 +1,29 @@
import type { ConnectionType } from "./ConnectionType";
import type { DNSMode } from "./DNSMode";
import type { Network } from "./Network";
export type ConnectionMetaData = {
network: Network;
type: ConnectionType;
sourceIP: string;
destinationIP: string;
sourceGeoIP: Array<string> | null;
destinationGeoIP: Array<string> | null;
sourceIPASN: string;
destinationIPASN: string;
sourcePort: string;
destinationPort: string;
inboundIP: string;
inboundPort: string;
inboundName: string;
inboundUser: string;
host: string;
dnsMode: DNSMode;
uid: number;
process: string;
processPath: string;
specialProxy: string;
specialRules: string;
remoteDestination: string;
dscp: number;
sniffHost: string;
};
@@ -0,0 +1 @@
export type ConnectionType = "HTTP" | "HTTPS" | "Socks4" | "Socks5" | "ShadowSocks" | "Vmess" | "Vless" | "Redir" | "TProxy" | "Trojan" | "Tunnel" | "Tun" | "Tuic" | "Hysteria2" | "AnyTLS" | "Inner";
@@ -0,0 +1,10 @@
import type { Connection } from "./Connection";
/**
* connections
*/
export type Connections = {
downloadTotal: bigint;
uploadTotal: bigint;
connections: Array<Connection> | null;
memory: number;
};
@@ -0,0 +1 @@
export type CoreUpdaterChannel = "release" | "alpha" | "auto";
@@ -0,0 +1 @@
export type DNSMode = "normal" | "fake-ip" | "redir-host" | "hosts";
@@ -0,0 +1,4 @@
export type DelayHistory = {
time: string;
delay: number;
};
@@ -0,0 +1,5 @@
import type { DelayHistory } from "./DelayHistory";
export type Extra = {
alive: boolean;
history: Array<DelayHistory>;
};
@@ -0,0 +1 @@
export type FindProcessMode = "strict" | "always" | "off";
@@ -0,0 +1,6 @@
export type GeoXUrl = {
geoIp: string;
mmdb: string;
asn: string;
geoSite: string;
};
@@ -0,0 +1,7 @@
import type { Proxy } from "./Proxy";
/**
* group proxies
*/
export type Groups = {
proxies: Array<Proxy>;
};
+4
View File
@@ -0,0 +1,4 @@
export type Log = {
type: string;
payload: string;
};
@@ -0,0 +1 @@
export type LogLevel = "debug" | "info" | "warning" | "error" | "silent";
@@ -0,0 +1,4 @@
export type Memory = {
inuse: number;
oslimit: number;
};
@@ -0,0 +1,7 @@
/**
* mihomo version
*/
export type MihomoVersion = {
meta: boolean;
version: string;
};
@@ -0,0 +1,5 @@
import type { BrutalOption } from "./BrutalOption";
export type MuxOption = {
padding?: boolean;
brutal?: BrutalOption;
};
@@ -0,0 +1 @@
export type Network = "tcp" | "udp" | "all";
@@ -0,0 +1 @@
export type ProviderType = "Proxy" | "Rule";
@@ -0,0 +1,9 @@
import type { Proxy } from "./Proxy";
/**
* proxies
*/
export type Proxies = {
proxies: {
[key in string]?: Proxy;
};
};
+29
View File
@@ -0,0 +1,29 @@
import type { DelayHistory } from "./DelayHistory";
import type { Extra } from "./Extra";
import type { ProxyType } from "./ProxyType";
export type Proxy = {
all?: Array<string>;
expectedStatus?: string;
fixed?: string;
hidden?: boolean;
icon?: string;
now?: string;
testUrl?: string;
id?: string;
alive: boolean;
history: Array<DelayHistory>;
extra: {
[key in string]?: Extra;
};
name: string;
udp: boolean;
uot: boolean;
type: ProxyType;
xudp: boolean;
tfo: boolean;
mptcp: boolean;
smux: boolean;
interface: string;
dialerProxy: string;
routingMark: number;
};
@@ -0,0 +1,8 @@
/**
* proxy delay result
*
* displays a message if it times out, otherwise it only displays the delay
*/
export type ProxyDelay = {
delay: number;
};
@@ -0,0 +1,14 @@
import type { ProviderType } from "./ProviderType";
import type { Proxy } from "./Proxy";
import type { SubScriptionInfo } from "./SubScriptionInfo";
import type { VehicleType } from "./VehicleType";
export type ProxyProvider = {
name: string;
type: ProviderType;
vehicleType: VehicleType;
proxies: Array<Proxy>;
testUrl: string;
expectedStatus: string;
updatedAt: string | null;
subscriptionInfo: SubScriptionInfo | null;
};
@@ -0,0 +1,6 @@
import type { ProxyProvider } from "./ProxyProvider";
export type ProxyProviders = {
providers: {
[key in string]?: ProxyProvider;
};
};
@@ -0,0 +1 @@
export type ProxyType = "Direct" | "Reject" | "RejectDrop" | "Compatible" | "Pass" | "Dns" | "Shadowsocks" | "ShadowsocksR" | "Snell" | "Socks5" | "Http" | "Vmess" | "Vless" | "Trojan" | "Hysteria" | "Hysteria2" | "WireGuard" | "Tuic" | "Ssh" | "Mieru" | "AnyTLS" | "Relay" | "Selector" | "Fallback" | "URLTest" | "LoadBalance";
+7
View File
@@ -0,0 +1,7 @@
import type { RuleType } from "./RuleType";
export type Rule = {
type: RuleType;
payload: string;
proxy: string;
size: number;
};
@@ -0,0 +1 @@
export type RuleBehavior = "Domain" | "IPCIDR" | "Classical";
@@ -0,0 +1 @@
export type RuleFormat = "YamlRule" | "TextRule" | "MrsRule";
@@ -0,0 +1,13 @@
import type { ProviderType } from "./ProviderType";
import type { RuleBehavior } from "./RuleBehavior";
import type { RuleFormat } from "./RuleFormat";
import type { VehicleType } from "./VehicleType";
export type RuleProvider = {
behavior: RuleBehavior;
format: RuleFormat;
name: string;
ruleCount: number;
type: ProviderType;
updatedAt: string;
vehicleType: VehicleType;
};
@@ -0,0 +1,6 @@
import type { RuleProvider } from "./RuleProvider";
export type RuleProviders = {
providers: {
[key in string]?: RuleProvider;
};
};
@@ -0,0 +1 @@
export type RuleType = "Domain" | "DomainSuffix" | "DomainKeyword" | "DomainRegex" | "GeoSite" | "GeoIP" | "SrcGeoIP" | "IPASN" | "SrcIPASN" | "IPCIDR" | "SrcIPCIDR" | "IPSuffix" | "SrcIPSuffix" | "SrcPort" | "DstPort" | "InPort" | "InUser" | "InName" | "InType" | "ProcessName" | "ProcessPath" | "ProcessNameRegex" | "ProcessPathRegex" | "Match" | "RuleSet" | "Network" | "DSCP" | "Uid" | "SubRules" | "AND" | "OR" | "NOT";
@@ -0,0 +1,7 @@
import type { Rule } from "./Rule";
/**
* rules
*/
export type Rules = {
rules: Array<Rule>;
};
@@ -0,0 +1,6 @@
export type SubScriptionInfo = {
Upload: bigint;
Download: bigint;
Total: bigint;
Expire: bigint;
};
@@ -0,0 +1,4 @@
export type Traffic = {
up: bigint;
down: bigint;
};
@@ -0,0 +1,20 @@
import type { MuxOption } from "./MuxOption";
export type TuicServer = {
enable: boolean;
listen: string;
token?: Array<string>;
users?: {
[key in string]?: string;
};
certificate: string;
privateKey: string;
echKey: string;
congestionController?: string;
maxIdleTime?: number;
authenticationTimeout?: number;
alpn?: Array<string>;
maxUdpRelayPacketSize?: number;
maxDatagramFrameSize?: number;
cwnd?: number;
muxOption?: MuxOption;
};
@@ -0,0 +1,47 @@
import type { TunStack } from "./TunStack";
export type TunConfig = {
enable: boolean;
device: string;
stack: TunStack;
dnsHijack: Array<string>;
autoRoute: boolean;
autoDetectInterface: boolean;
mtu?: number;
gso?: boolean;
gsoMaxSize?: number;
inet4Address?: Array<string>;
inet6Address?: Array<string>;
iproute2TableIndex?: number;
iproute2RuleIndex?: number;
autoRedirect?: boolean;
autoRedirectInputMark?: number;
autoRedirectOutputMark?: number;
loopbackAddress?: string;
strictRoute?: boolean;
routeAddress?: Array<string>;
routeAddressSet?: Array<string>;
routeExcludeAddress?: Array<string>;
routeExcludeAddressSet?: Array<string>;
includeInterface?: Array<string>;
excludeInterface?: Array<string>;
includeUid?: Array<number>;
includeUidRange?: Array<string>;
excludeUid?: Array<number>;
excludeUidRange?: Array<string>;
excludeSrcPort?: Array<number>;
excludeSrcPortRange?: Array<string>;
excludeDstPort?: Array<number>;
excludeDstPortRange?: Array<string>;
includeAndroidUser?: Array<number>;
includePackage?: Array<string>;
excludePackage?: Array<string>;
endpointIndependentNat?: boolean;
udpTimeout?: bigint;
fileDescriptor: number;
inet4RouteAddress?: Array<string>;
inet6RouteAddress?: Array<string>;
inet4RouteExcludeAddress?: Array<string>;
inet6RouteExcludeAddress?: Array<string>;
recvmsgx?: boolean;
sendmsgx?: boolean;
};
@@ -0,0 +1,4 @@
/**
* tun stack enum
*/
export type TunStack = "Mixed" | "gVisor" | "System";
@@ -0,0 +1 @@
export type VehicleType = "File" | "HTTP" | "Compatible" | "Inline";
+40
View File
@@ -0,0 +1,40 @@
export * from "./BaseConfig";
export * from "./BrutalOption";
export * from "./ClashMode";
export * from "./Connection";
export * from "./ConnectionMetaData";
export * from "./Connections";
export * from "./ConnectionType";
export * from "./CoreUpdaterChannel";
export * from "./DelayHistory";
export * from "./DNSMode";
export * from "./Extra";
export * from "./FindProcessMode";
export * from "./GeoXUrl";
export * from "./Groups";
export * from "./Log";
export * from "./LogLevel";
export * from "./Memory";
export * from "./MihomoVersion";
export * from "./MuxOption";
export * from "./Network";
export * from "./ProviderType";
export * from "./Proxies";
export * from "./Proxy";
export * from "./ProxyDelay";
export * from "./ProxyProvider";
export * from "./ProxyProviders";
export * from "./ProxyType";
export * from "./Rule";
export * from "./RuleBehavior";
export * from "./RuleFormat";
export * from "./RuleProvider";
export * from "./RuleProviders";
export * from "./Rules";
export * from "./RuleType";
export * from "./SubScriptionInfo";
export * from "./Traffic";
export * from "./TuicServer";
export * from "./TunConfig";
export * from "./TunStack";
export * from "./VehicleType";
@@ -0,0 +1,474 @@
'use strict';
var core = require('@tauri-apps/api/core');
// ======================= functions =======================
/**
* 更新控制器地址
* @param controller 控制器地址, 例如:127.0.0.1:9090
*/
async function updateController(controller) {
const [host, portStr] = controller.trim().split(":");
const port = parseInt(portStr);
await core.invoke("plugin:mihomo|update_controller", { host, port });
}
/**
* 更新控制器的密钥
* @param secret 控制器的密钥
*/
async function updateSecret(secret) {
await core.invoke("plugin:mihomo|update_secret", { secret });
}
/**
* 获取Mihomo版本信息
*/
async function getVersion() {
return await core.invoke("plugin:mihomo|get_version");
}
/**
* 清除 FakeIP 缓存
*/
async function flushFakeIp() {
await core.invoke("plugin:mihomo|flush_fakeip");
}
/**
* 清除 DNS 缓存
*/
async function flushDNS() {
await core.invoke("plugin:mihomo|flush_dns");
}
// connections
/**
* 获取所有连接信息
* @returns 所有连接信息
*/
async function getConnections() {
return await core.invoke("plugin:mihomo|get_connections");
}
/**
* 关闭所有连接
*/
async function closeAllConnections() {
await core.invoke("plugin:mihomo|close_all_connections");
}
/**
* 关闭指定连接
* @param connectionId 连接 ID
*/
async function closeConnections(connectionId) {
await core.invoke("plugin:mihomo|close_connections", { connectionId });
}
// groups
/**
* 获取所有代理组信息
* @returns 所有代理组信息
*/
async function getGroups() {
return await core.invoke("plugin:mihomo|get_groups");
}
/**
* 获取指定代理组信息
* @param groupName 代理组名称
* @returns 指定代理组信息
*/
async function getGroupByName(groupName) {
return await core.invoke("plugin:mihomo|get_group_by_name", {
groupName,
});
}
/**
* 对指定代理组进行延迟测试
*
* 注:返回值中不包含超时的节点
* @param groupName 代理组名称
* @param testUrl 测试 url
* @param timeout 超时时间(毫秒)
* @param keepFixed 是否保留已固定的节点, 默认 false
* @returns 代理组里代理节点的延迟
*/
async function delayGroup(groupName, testUrl, timeout, keepFixed = false) {
return await core.invoke("plugin:mihomo|delay_group", {
groupName,
testUrl,
timeout,
keepFixed,
});
}
// providers
/**
* 获取所有代理提供者信息
* @returns 所有代理提供者信息
*/
async function getProxyProviders() {
return await core.invoke("plugin:mihomo|get_proxy_providers");
}
/**
* 获取指定的代理提供者信息
* @param providerName 代理提供者名称
* @returns 代理提供者信息
*/
async function getProxyProviderByName(providerName) {
return await core.invoke("plugin:mihomo|get_proxy_provider_by_name", { providerName });
}
/**
* 更新代理提供者信息
* @param providerName 代理提供者名称
*/
async function updateProxyProvider(providerName) {
await core.invoke("plugin:mihomo|update_proxy_provider", {
providerName,
});
}
/**
* 对指定的代理提供者进行健康检查
* @param providerName 代理提供者名称
*/
async function healthcheckProxyProvider(providerName) {
await core.invoke("plugin:mihomo|healthcheck_proxy_provider", {
providerName,
});
}
/**
* 对指定代理提供者下的指定节点(非代理组)进行健康检查, 并返回新的延迟信息
* @param providerName 代理提供者名称
* @param proxyName 代理节点名称 (非代理组)
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟
*/
async function healthcheckNodeInProvider(providerName, proxyName, testUrl, timeout) {
return await core.invoke("plugin:mihomo|healthcheck_node_in_provider", {
providerName,
proxyName,
testUrl,
timeout,
});
}
// proxies
/**
* 获取所有代理信息
* @returns 所有代理信息
*/
async function getProxies() {
return await core.invoke("plugin:mihomo|get_proxies");
}
/**
* 获取指定代理信息
* @param proxyName 代理名称
* @returns 代理信息
*/
async function getProxyByName(proxyName) {
return await core.invoke("plugin:mihomo|get_proxy_by_name", {
proxiesName: proxyName,
});
}
/**
* 为指定代理选择节点
*
* 一般为指定代理组下使用指定的代理节点 【代理组/节点】
* @param groupName 代理组名称
* @param node 代理节点
*/
async function selectNodeForGroup(groupName, node) {
await core.invoke("plugin:mihomo|select_node_for_group", {
groupName,
node,
});
}
/**
* 指定代理组下不再使用固定的代理节点
*
* 一般用于自动选择的代理组(例如:URLTest 类型的代理组)下的节点
* @param groupName 代理组名称
*/
async function unfixedProxy(groupName) {
await core.invoke("plugin:mihomo|unfixed_proxy", {
groupName,
});
}
/**
* 对指定代理进行延迟测试
*
* 一般用于代理节点的延迟测试,也可传代理组名称(只会测试代理组下选中的代理节点)
* @param proxyName 代理节点名称
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟信息
*/
async function delayProxyByName(proxyName, testUrl, timeout) {
return await core.invoke("plugin:mihomo|delay_proxy_by_name", {
proxyName,
testUrl,
timeout,
});
}
// rules
/**
* 获取所有规则信息
* @returns 所有规则信息
*/
async function getRules() {
return await core.invoke("plugin:mihomo|get_rules");
}
/**
* 获取所有规则提供者信息
* @returns 所有规则提供者信息
*/
async function getRuleProviders() {
return await core.invoke("plugin:mihomo|get_rule_providers");
}
/**
* 更新规则提供者信息
* @param providerName 规则提供者名称
*/
async function updateRuleProvider(providerName) {
await core.invoke("plugin:mihomo|update_rule_provider", {
providerName,
});
}
// runtime config
/**
* 获取基础配置
* @returns 基础配置
*/
async function getBaseConfig() {
return await core.invoke("plugin:mihomo|get_base_config");
}
/**
* 重新加载配置
* @param force 强制更新
* @param configPath 配置文件路径
*/
async function reloadConfig(force, configPath) {
await core.invoke("plugin:mihomo|reload_config", {
force,
configPath,
});
}
/**
* 更改基础配置
* @param data 基础配置更改后的内容, 例如:{"tun": {"enabled": true}}
*/
async function patchBaseConfig(data) {
await core.invoke("plugin:mihomo|patch_base_config", {
data,
});
}
/**
* 更新 Geo
*/
async function updateGeo() {
await core.invoke("plugin:mihomo|update_geo");
}
/**
* 重启核心
*/
async function restart() {
await core.invoke("plugin:mihomo|restart");
}
// upgrade
/**
* 升级核心,将当前运行中的核心升级到选择的通道的最新版
* @param channel 升级通道, 默认 auto
* - release: 稳定版
* - alpha: 测试版
* - auto: 根据当前运行的核心版本自动选择升级通道
* @param force 是否强制升级,默认 false
* - false: 若当前版本为最新版,返回当前为最新版的错误,不再执行升级操作, 否则下载最新版,覆盖升级
* - true: 直接下载最新版,强制覆盖升级
*/
async function upgradeCore(channel = "auto", force = false) {
await core.invoke("plugin:mihomo|upgrade_core", { channel, force });
}
/**
* 更新 UI
*/
async function upgradeUi() {
await core.invoke("plugin:mihomo|upgrade_ui");
}
/**
* 更新 Geo
*/
async function upgradeGeo() {
await core.invoke("plugin:mihomo|upgrade_geo");
}
/**
* 清除 Rust 侧中所有的 WebSocket 连接
*/
async function clearAllWsConnections() {
await core.invoke("plugin:mihomo|clear_all_ws_connections");
}
class MihomoWebSocket {
constructor(id, listeners) {
this.id = id;
this.listeners = listeners;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的流量监控
* @returns WebSocket 实例
*/
static async connect_traffic() {
const listeners = new Set();
const onMessage = new core.Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await core.invoke("plugin:mihomo|ws_traffic", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的内存监控
* @returns WebSocket 实例
*/
static async connect_memory() {
const listeners = new Set();
const onMessage = new core.Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await core.invoke("plugin:mihomo|ws_memory", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的连接监控
* @returns WebSocket 实例
*/
static async connect_connections() {
const listeners = new Set();
const onMessage = new core.Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await core.invoke("plugin:mihomo|ws_connections", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的日志监控
* @returns WebSocket 实例
*/
static async connect_logs(level) {
const listeners = new Set();
const onMessage = new core.Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await core.invoke("plugin:mihomo|ws_logs", {
level,
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 添加处理 WebSocket 连接后接受的数据的回调函数
* @param cb 回调函数
*/
addListener(cb) {
this.listeners.add(cb);
return () => {
this.listeners.delete(cb);
};
}
// /**
// * 发送消息到 WebSocket 连接
// * @param message 发送的消息
// */
// async send(message: Message | string | number[]): Promise<void> {
// let m: Message;
// if (typeof message === "string") {
// m = { type: "Text", data: message };
// } else if (typeof message === "object" && "type" in message) {
// m = message;
// } else if (Array.isArray(message)) {
// m = { type: "Binary", data: message };
// } else {
// throw new Error(
// "invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array",
// );
// }
// await invoke("plugin:mihomo|ws_send", { id: this.id, message: m });
// }
/**
* 关闭 WebSocket 连接
* @param forceTimeout 强制关闭 WebSocket 连接等待的时间,单位: 毫秒, 默认为 0
*/
async close() {
try {
await core.invoke("plugin:mihomo|ws_disconnect", {
id: this.id,
forceTimeout: 0,
});
}
catch (ignore) {
// ignore
}
finally {
MihomoWebSocket.instances.delete(this);
}
}
/**
* 清理全部的 websocket 连接资源
*/
static async cleanupAll() {
await Promise.all(Array.from(MihomoWebSocket.instances).map((instance) => instance.close()));
this.instances.clear();
await clearAllWsConnections();
}
}
MihomoWebSocket.instances = new Set();
exports.MihomoWebSocket = MihomoWebSocket;
exports.clearAllWsConnections = clearAllWsConnections;
exports.closeAllConnections = closeAllConnections;
exports.closeConnections = closeConnections;
exports.delayGroup = delayGroup;
exports.delayProxyByName = delayProxyByName;
exports.flushDNS = flushDNS;
exports.flushFakeIp = flushFakeIp;
exports.getBaseConfig = getBaseConfig;
exports.getConnections = getConnections;
exports.getGroupByName = getGroupByName;
exports.getGroups = getGroups;
exports.getProxies = getProxies;
exports.getProxyByName = getProxyByName;
exports.getProxyProviderByName = getProxyProviderByName;
exports.getProxyProviders = getProxyProviders;
exports.getRuleProviders = getRuleProviders;
exports.getRules = getRules;
exports.getVersion = getVersion;
exports.healthcheckNodeInProvider = healthcheckNodeInProvider;
exports.healthcheckProxyProvider = healthcheckProxyProvider;
exports.patchBaseConfig = patchBaseConfig;
exports.reloadConfig = reloadConfig;
exports.restart = restart;
exports.selectNodeForGroup = selectNodeForGroup;
exports.unfixedProxy = unfixedProxy;
exports.updateController = updateController;
exports.updateGeo = updateGeo;
exports.updateProxyProvider = updateProxyProvider;
exports.updateRuleProvider = updateRuleProvider;
exports.updateSecret = updateSecret;
exports.upgradeCore = upgradeCore;
exports.upgradeGeo = upgradeGeo;
exports.upgradeUi = upgradeUi;
+238
View File
@@ -0,0 +1,238 @@
import { BaseConfig, Connections, CoreUpdaterChannel, Groups, LogLevel, MihomoVersion, Proxies, Proxy, ProxyDelay, ProxyProvider, ProxyProviders, RuleProviders, Rules } from "./bindings";
export * from "./bindings";
export type MihomoGroupDelay = Record<string, number>;
/**
* 更新控制器地址
* @param controller 控制器地址, 例如:127.0.0.1:9090
*/
export declare function updateController(controller: string): Promise<void>;
/**
* 更新控制器的密钥
* @param secret 控制器的密钥
*/
export declare function updateSecret(secret: string): Promise<void>;
/**
* 获取Mihomo版本信息
*/
export declare function getVersion(): Promise<MihomoVersion>;
/**
* 清除 FakeIP 缓存
*/
export declare function flushFakeIp(): Promise<void>;
/**
* 清除 DNS 缓存
*/
export declare function flushDNS(): Promise<void>;
/**
* 获取所有连接信息
* @returns 所有连接信息
*/
export declare function getConnections(): Promise<Connections>;
/**
* 关闭所有连接
*/
export declare function closeAllConnections(): Promise<void>;
/**
* 关闭指定连接
* @param connectionId 连接 ID
*/
export declare function closeConnections(connectionId: string): Promise<void>;
/**
* 获取所有代理组信息
* @returns 所有代理组信息
*/
export declare function getGroups(): Promise<Groups>;
/**
* 获取指定代理组信息
* @param groupName 代理组名称
* @returns 指定代理组信息
*/
export declare function getGroupByName(groupName: string): Promise<Proxy>;
/**
* 对指定代理组进行延迟测试
*
* 注:返回值中不包含超时的节点
* @param groupName 代理组名称
* @param testUrl 测试 url
* @param timeout 超时时间(毫秒)
* @param keepFixed 是否保留已固定的节点, 默认 false
* @returns 代理组里代理节点的延迟
*/
export declare function delayGroup(groupName: string, testUrl: string, timeout: number, keepFixed?: boolean): Promise<MihomoGroupDelay>;
/**
* 获取所有代理提供者信息
* @returns 所有代理提供者信息
*/
export declare function getProxyProviders(): Promise<ProxyProviders>;
/**
* 获取指定的代理提供者信息
* @param providerName 代理提供者名称
* @returns 代理提供者信息
*/
export declare function getProxyProviderByName(providerName: string): Promise<ProxyProvider>;
/**
* 更新代理提供者信息
* @param providerName 代理提供者名称
*/
export declare function updateProxyProvider(providerName: string): Promise<void>;
/**
* 对指定的代理提供者进行健康检查
* @param providerName 代理提供者名称
*/
export declare function healthcheckProxyProvider(providerName: string): Promise<void>;
/**
* 对指定代理提供者下的指定节点(非代理组)进行健康检查, 并返回新的延迟信息
* @param providerName 代理提供者名称
* @param proxyName 代理节点名称 (非代理组)
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟
*/
export declare function healthcheckNodeInProvider(providerName: string, proxyName: string, testUrl: string, timeout: number): Promise<ProxyDelay>;
/**
* 获取所有代理信息
* @returns 所有代理信息
*/
export declare function getProxies(): Promise<Proxies>;
/**
* 获取指定代理信息
* @param proxyName 代理名称
* @returns 代理信息
*/
export declare function getProxyByName(proxyName: string): Promise<Proxy | null>;
/**
* 为指定代理选择节点
*
* 一般为指定代理组下使用指定的代理节点 【代理组/节点】
* @param groupName 代理组名称
* @param node 代理节点
*/
export declare function selectNodeForGroup(groupName: string, node: string): Promise<void>;
/**
* 指定代理组下不再使用固定的代理节点
*
* 一般用于自动选择的代理组(例如:URLTest 类型的代理组)下的节点
* @param groupName 代理组名称
*/
export declare function unfixedProxy(groupName: string): Promise<void>;
/**
* 对指定代理进行延迟测试
*
* 一般用于代理节点的延迟测试,也可传代理组名称(只会测试代理组下选中的代理节点)
* @param proxyName 代理节点名称
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟信息
*/
export declare function delayProxyByName(proxyName: string, testUrl: string, timeout: number): Promise<ProxyDelay>;
/**
* 获取所有规则信息
* @returns 所有规则信息
*/
export declare function getRules(): Promise<Rules>;
/**
* 获取所有规则提供者信息
* @returns 所有规则提供者信息
*/
export declare function getRuleProviders(): Promise<RuleProviders>;
/**
* 更新规则提供者信息
* @param providerName 规则提供者名称
*/
export declare function updateRuleProvider(providerName: string): Promise<void>;
/**
* 获取基础配置
* @returns 基础配置
*/
export declare function getBaseConfig(): Promise<BaseConfig>;
/**
* 重新加载配置
* @param force 强制更新
* @param configPath 配置文件路径
*/
export declare function reloadConfig(force: boolean, configPath: string): Promise<void>;
/**
* 更改基础配置
* @param data 基础配置更改后的内容, 例如:{"tun": {"enabled": true}}
*/
export declare function patchBaseConfig(data: Record<string, any>): Promise<void>;
/**
* 更新 Geo
*/
export declare function updateGeo(): Promise<void>;
/**
* 重启核心
*/
export declare function restart(): Promise<void>;
/**
* 升级核心,将当前运行中的核心升级到选择的通道的最新版
* @param channel 升级通道, 默认 auto
* - release: 稳定版
* - alpha: 测试版
* - auto: 根据当前运行的核心版本自动选择升级通道
* @param force 是否强制升级,默认 false
* - false: 若当前版本为最新版,返回当前为最新版的错误,不再执行升级操作, 否则下载最新版,覆盖升级
* - true: 直接下载最新版,强制覆盖升级
*/
export declare function upgradeCore(channel?: CoreUpdaterChannel, force?: boolean): Promise<void>;
/**
* 更新 UI
*/
export declare function upgradeUi(): Promise<void>;
/**
* 更新 Geo
*/
export declare function upgradeGeo(): Promise<void>;
/**
* 清除 Rust 侧中所有的 WebSocket 连接
*/
export declare function clearAllWsConnections(): Promise<void>;
export interface MessageKind<T, D> {
type: T;
data: D;
}
export interface CloseFrame {
code: number;
reason: string;
}
export type Message = MessageKind<"Text", string> | MessageKind<"Binary", number[]> | MessageKind<"Ping", number[]> | MessageKind<"Pong", number[]> | MessageKind<"Close", CloseFrame | null>;
export declare class MihomoWebSocket {
id: number;
private readonly listeners;
private static instances;
constructor(id: number, listeners: Set<(arg: Message) => void>);
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的流量监控
* @returns WebSocket 实例
*/
static connect_traffic(): Promise<MihomoWebSocket>;
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的内存监控
* @returns WebSocket 实例
*/
static connect_memory(): Promise<MihomoWebSocket>;
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的连接监控
* @returns WebSocket 实例
*/
static connect_connections(): Promise<MihomoWebSocket>;
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的日志监控
* @returns WebSocket 实例
*/
static connect_logs(level: LogLevel): Promise<MihomoWebSocket>;
/**
* 添加处理 WebSocket 连接后接受的数据的回调函数
* @param cb 回调函数
*/
addListener(cb: (arg: Message) => void): () => void;
/**
* 关闭 WebSocket 连接
* @param forceTimeout 强制关闭 WebSocket 连接等待的时间,单位: 毫秒, 默认为 0
*/
close(): Promise<void>;
/**
* 清理全部的 websocket 连接资源
*/
static cleanupAll(): Promise<void>;
}
+439
View File
@@ -0,0 +1,439 @@
import { invoke, Channel } from '@tauri-apps/api/core';
// ======================= functions =======================
/**
* 更新控制器地址
* @param controller 控制器地址, 例如:127.0.0.1:9090
*/
async function updateController(controller) {
const [host, portStr] = controller.trim().split(":");
const port = parseInt(portStr);
await invoke("plugin:mihomo|update_controller", { host, port });
}
/**
* 更新控制器的密钥
* @param secret 控制器的密钥
*/
async function updateSecret(secret) {
await invoke("plugin:mihomo|update_secret", { secret });
}
/**
* 获取Mihomo版本信息
*/
async function getVersion() {
return await invoke("plugin:mihomo|get_version");
}
/**
* 清除 FakeIP 缓存
*/
async function flushFakeIp() {
await invoke("plugin:mihomo|flush_fakeip");
}
/**
* 清除 DNS 缓存
*/
async function flushDNS() {
await invoke("plugin:mihomo|flush_dns");
}
// connections
/**
* 获取所有连接信息
* @returns 所有连接信息
*/
async function getConnections() {
return await invoke("plugin:mihomo|get_connections");
}
/**
* 关闭所有连接
*/
async function closeAllConnections() {
await invoke("plugin:mihomo|close_all_connections");
}
/**
* 关闭指定连接
* @param connectionId 连接 ID
*/
async function closeConnections(connectionId) {
await invoke("plugin:mihomo|close_connections", { connectionId });
}
// groups
/**
* 获取所有代理组信息
* @returns 所有代理组信息
*/
async function getGroups() {
return await invoke("plugin:mihomo|get_groups");
}
/**
* 获取指定代理组信息
* @param groupName 代理组名称
* @returns 指定代理组信息
*/
async function getGroupByName(groupName) {
return await invoke("plugin:mihomo|get_group_by_name", {
groupName,
});
}
/**
* 对指定代理组进行延迟测试
*
* 注:返回值中不包含超时的节点
* @param groupName 代理组名称
* @param testUrl 测试 url
* @param timeout 超时时间(毫秒)
* @param keepFixed 是否保留已固定的节点, 默认 false
* @returns 代理组里代理节点的延迟
*/
async function delayGroup(groupName, testUrl, timeout, keepFixed = false) {
return await invoke("plugin:mihomo|delay_group", {
groupName,
testUrl,
timeout,
keepFixed,
});
}
// providers
/**
* 获取所有代理提供者信息
* @returns 所有代理提供者信息
*/
async function getProxyProviders() {
return await invoke("plugin:mihomo|get_proxy_providers");
}
/**
* 获取指定的代理提供者信息
* @param providerName 代理提供者名称
* @returns 代理提供者信息
*/
async function getProxyProviderByName(providerName) {
return await invoke("plugin:mihomo|get_proxy_provider_by_name", { providerName });
}
/**
* 更新代理提供者信息
* @param providerName 代理提供者名称
*/
async function updateProxyProvider(providerName) {
await invoke("plugin:mihomo|update_proxy_provider", {
providerName,
});
}
/**
* 对指定的代理提供者进行健康检查
* @param providerName 代理提供者名称
*/
async function healthcheckProxyProvider(providerName) {
await invoke("plugin:mihomo|healthcheck_proxy_provider", {
providerName,
});
}
/**
* 对指定代理提供者下的指定节点(非代理组)进行健康检查, 并返回新的延迟信息
* @param providerName 代理提供者名称
* @param proxyName 代理节点名称 (非代理组)
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟
*/
async function healthcheckNodeInProvider(providerName, proxyName, testUrl, timeout) {
return await invoke("plugin:mihomo|healthcheck_node_in_provider", {
providerName,
proxyName,
testUrl,
timeout,
});
}
// proxies
/**
* 获取所有代理信息
* @returns 所有代理信息
*/
async function getProxies() {
return await invoke("plugin:mihomo|get_proxies");
}
/**
* 获取指定代理信息
* @param proxyName 代理名称
* @returns 代理信息
*/
async function getProxyByName(proxyName) {
return await invoke("plugin:mihomo|get_proxy_by_name", {
proxiesName: proxyName,
});
}
/**
* 为指定代理选择节点
*
* 一般为指定代理组下使用指定的代理节点 【代理组/节点】
* @param groupName 代理组名称
* @param node 代理节点
*/
async function selectNodeForGroup(groupName, node) {
await invoke("plugin:mihomo|select_node_for_group", {
groupName,
node,
});
}
/**
* 指定代理组下不再使用固定的代理节点
*
* 一般用于自动选择的代理组(例如:URLTest 类型的代理组)下的节点
* @param groupName 代理组名称
*/
async function unfixedProxy(groupName) {
await invoke("plugin:mihomo|unfixed_proxy", {
groupName,
});
}
/**
* 对指定代理进行延迟测试
*
* 一般用于代理节点的延迟测试,也可传代理组名称(只会测试代理组下选中的代理节点)
* @param proxyName 代理节点名称
* @param testUrl 测试 url
* @param timeout 超时时间
* @returns 该代理节点的延迟信息
*/
async function delayProxyByName(proxyName, testUrl, timeout) {
return await invoke("plugin:mihomo|delay_proxy_by_name", {
proxyName,
testUrl,
timeout,
});
}
// rules
/**
* 获取所有规则信息
* @returns 所有规则信息
*/
async function getRules() {
return await invoke("plugin:mihomo|get_rules");
}
/**
* 获取所有规则提供者信息
* @returns 所有规则提供者信息
*/
async function getRuleProviders() {
return await invoke("plugin:mihomo|get_rule_providers");
}
/**
* 更新规则提供者信息
* @param providerName 规则提供者名称
*/
async function updateRuleProvider(providerName) {
await invoke("plugin:mihomo|update_rule_provider", {
providerName,
});
}
// runtime config
/**
* 获取基础配置
* @returns 基础配置
*/
async function getBaseConfig() {
return await invoke("plugin:mihomo|get_base_config");
}
/**
* 重新加载配置
* @param force 强制更新
* @param configPath 配置文件路径
*/
async function reloadConfig(force, configPath) {
await invoke("plugin:mihomo|reload_config", {
force,
configPath,
});
}
/**
* 更改基础配置
* @param data 基础配置更改后的内容, 例如:{"tun": {"enabled": true}}
*/
async function patchBaseConfig(data) {
await invoke("plugin:mihomo|patch_base_config", {
data,
});
}
/**
* 更新 Geo
*/
async function updateGeo() {
await invoke("plugin:mihomo|update_geo");
}
/**
* 重启核心
*/
async function restart() {
await invoke("plugin:mihomo|restart");
}
// upgrade
/**
* 升级核心,将当前运行中的核心升级到选择的通道的最新版
* @param channel 升级通道, 默认 auto
* - release: 稳定版
* - alpha: 测试版
* - auto: 根据当前运行的核心版本自动选择升级通道
* @param force 是否强制升级,默认 false
* - false: 若当前版本为最新版,返回当前为最新版的错误,不再执行升级操作, 否则下载最新版,覆盖升级
* - true: 直接下载最新版,强制覆盖升级
*/
async function upgradeCore(channel = "auto", force = false) {
await invoke("plugin:mihomo|upgrade_core", { channel, force });
}
/**
* 更新 UI
*/
async function upgradeUi() {
await invoke("plugin:mihomo|upgrade_ui");
}
/**
* 更新 Geo
*/
async function upgradeGeo() {
await invoke("plugin:mihomo|upgrade_geo");
}
/**
* 清除 Rust 侧中所有的 WebSocket 连接
*/
async function clearAllWsConnections() {
await invoke("plugin:mihomo|clear_all_ws_connections");
}
class MihomoWebSocket {
constructor(id, listeners) {
this.id = id;
this.listeners = listeners;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的流量监控
* @returns WebSocket 实例
*/
static async connect_traffic() {
const listeners = new Set();
const onMessage = new Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await invoke("plugin:mihomo|ws_traffic", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的内存监控
* @returns WebSocket 实例
*/
static async connect_memory() {
const listeners = new Set();
const onMessage = new Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await invoke("plugin:mihomo|ws_memory", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的连接监控
* @returns WebSocket 实例
*/
static async connect_connections() {
const listeners = new Set();
const onMessage = new Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await invoke("plugin:mihomo|ws_connections", {
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 创建一个新的 WebSocket 连接,用于 Mihomo 的日志监控
* @returns WebSocket 实例
*/
static async connect_logs(level) {
const listeners = new Set();
const onMessage = new Channel();
onMessage.onmessage = (message) => {
listeners.forEach((l) => {
l(message);
});
};
const id = await invoke("plugin:mihomo|ws_logs", {
level,
onMessage,
});
const instance = new MihomoWebSocket(id, listeners);
MihomoWebSocket.instances.add(instance);
return instance;
}
/**
* 添加处理 WebSocket 连接后接受的数据的回调函数
* @param cb 回调函数
*/
addListener(cb) {
this.listeners.add(cb);
return () => {
this.listeners.delete(cb);
};
}
// /**
// * 发送消息到 WebSocket 连接
// * @param message 发送的消息
// */
// async send(message: Message | string | number[]): Promise<void> {
// let m: Message;
// if (typeof message === "string") {
// m = { type: "Text", data: message };
// } else if (typeof message === "object" && "type" in message) {
// m = message;
// } else if (Array.isArray(message)) {
// m = { type: "Binary", data: message };
// } else {
// throw new Error(
// "invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array",
// );
// }
// await invoke("plugin:mihomo|ws_send", { id: this.id, message: m });
// }
/**
* 关闭 WebSocket 连接
* @param forceTimeout 强制关闭 WebSocket 连接等待的时间,单位: 毫秒, 默认为 0
*/
async close() {
try {
await invoke("plugin:mihomo|ws_disconnect", {
id: this.id,
forceTimeout: 0,
});
}
catch (ignore) {
// ignore
}
finally {
MihomoWebSocket.instances.delete(this);
}
}
/**
* 清理全部的 websocket 连接资源
*/
static async cleanupAll() {
await Promise.all(Array.from(MihomoWebSocket.instances).map((instance) => instance.close()));
this.instances.clear();
await clearAllWsConnections();
}
}
MihomoWebSocket.instances = new Set();
export { MihomoWebSocket, clearAllWsConnections, closeAllConnections, closeConnections, delayGroup, delayProxyByName, flushDNS, flushFakeIp, getBaseConfig, getConnections, getGroupByName, getGroups, getProxies, getProxyByName, getProxyProviderByName, getProxyProviders, getRuleProviders, getRules, getVersion, healthcheckNodeInProvider, healthcheckProxyProvider, patchBaseConfig, reloadConfig, restart, selectNodeForGroup, unfixedProxy, updateController, updateGeo, updateProxyProvider, updateRuleProvider, updateSecret, upgradeCore, upgradeGeo, upgradeUi };
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
@@ -0,0 +1,7 @@
# Tauri + React + Typescript
This template should help get you started developing with Tauri, React and Typescript in Vite.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri + React + Typescript</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
@@ -0,0 +1,28 @@
{
"name": "check-mihomo-api",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"tauri": "tauri"
},
"dependencies": {
"@codemirror/lang-json": "^6.0.2",
"@tauri-apps/api": "^2",
"@uiw/react-codemirror": "^4.25.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tauri-plugin-mihomo-api": "file:../.."
},
"devDependencies": {
"@tauri-apps/cli": "^2",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.6.0",
"typescript": "~5.8.3",
"vite": "^7.0.4"
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
<svg width="206" height="231" viewBox="0 0 206 231" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M143.143 84C143.143 96.1503 133.293 106 121.143 106C108.992 106 99.1426 96.1503 99.1426 84C99.1426 71.8497 108.992 62 121.143 62C133.293 62 143.143 71.8497 143.143 84Z" fill="#FFC131"/>
<ellipse cx="84.1426" cy="147" rx="22" ry="22" transform="rotate(180 84.1426 147)" fill="#24C8DB"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M166.738 154.548C157.86 160.286 148.023 164.269 137.757 166.341C139.858 160.282 141 153.774 141 147C141 144.543 140.85 142.121 140.558 139.743C144.975 138.204 149.215 136.139 153.183 133.575C162.73 127.404 170.292 118.608 174.961 108.244C179.63 97.8797 181.207 86.3876 179.502 75.1487C177.798 63.9098 172.884 53.4021 165.352 44.8883C157.82 36.3744 147.99 30.2165 137.042 27.1546C126.095 24.0926 114.496 24.2568 103.64 27.6274C92.7839 30.998 83.1319 37.4317 75.8437 46.1553C74.9102 47.2727 74.0206 48.4216 73.176 49.5993C61.9292 50.8488 51.0363 54.0318 40.9629 58.9556C44.2417 48.4586 49.5653 38.6591 56.679 30.1442C67.0505 17.7298 80.7861 8.57426 96.2354 3.77762C111.685 -1.01901 128.19 -1.25267 143.769 3.10474C159.348 7.46215 173.337 16.2252 184.056 28.3411C194.775 40.457 201.767 55.4101 204.193 71.404C206.619 87.3978 204.374 103.752 197.73 118.501C191.086 133.25 180.324 145.767 166.738 154.548ZM41.9631 74.275L62.5557 76.8042C63.0459 72.813 63.9401 68.9018 65.2138 65.1274C57.0465 67.0016 49.2088 70.087 41.9631 74.275Z" fill="#FFC131"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.4045 76.4519C47.3493 70.6709 57.2677 66.6712 67.6171 64.6132C65.2774 70.9669 64 77.8343 64 85.0001C64 87.1434 64.1143 89.26 64.3371 91.3442C60.0093 92.8732 55.8533 94.9092 51.9599 97.4256C42.4128 103.596 34.8505 112.392 30.1816 122.756C25.5126 133.12 23.9357 144.612 25.6403 155.851C27.3449 167.09 32.2584 177.598 39.7906 186.112C47.3227 194.626 57.153 200.784 68.1003 203.846C79.0476 206.907 90.6462 206.743 101.502 203.373C112.359 200.002 122.011 193.568 129.299 184.845C130.237 183.722 131.131 182.567 131.979 181.383C143.235 180.114 154.132 176.91 164.205 171.962C160.929 182.49 155.596 192.319 148.464 200.856C138.092 213.27 124.357 222.426 108.907 227.222C93.458 232.019 76.9524 232.253 61.3736 227.895C45.7948 223.538 31.8055 214.775 21.0867 202.659C10.3679 190.543 3.37557 175.59 0.949823 159.596C-1.47592 143.602 0.768139 127.248 7.41237 112.499C14.0566 97.7497 24.8183 85.2327 38.4045 76.4519ZM163.062 156.711L163.062 156.711C162.954 156.773 162.846 156.835 162.738 156.897C162.846 156.835 162.954 156.773 163.062 156.711Z" fill="#24C8DB"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas
@@ -0,0 +1,23 @@
[package]
name = "check-mihomo-api"
version = "0.1.0"
description = "A Tauri App to test Mihomo api"
authors = ["oomeow"]
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
# The `_lib` suffix may seem redundant but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "mihomo_api_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
formatjson = "0.3.1"
tauri = { version = "2", features = [] }
tauri-plugin-mihomo = { path = "../../../" }
@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}
@@ -0,0 +1,7 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": ["core:default", "mihomo:default"]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,27 @@
use tauri_plugin_mihomo::Protocol;
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[tauri::command]
async fn cmd_format_json(text: &str) -> Result<String, String> {
Ok(formatjson::format_json(text).map_err(|_| "failed to format json".to_string())?)
// Ok(format_json(text, " "))
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(
tauri_plugin_mihomo::Builder::new()
.protocol(Protocol::LocalSocket)
.socket_path("/tmp/verge-mihomo.sock")
.build(),
)
.invoke_handler(tauri::generate_handler![greet, cmd_format_json])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
@@ -0,0 +1,6 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
mihomo_api_lib::run()
}
@@ -0,0 +1,35 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "check-mihomo-api",
"version": "0.1.0",
"identifier": "com.oomeow.check-mihomo-api",
"build": {
"beforeDevCommand": "pnpm dev",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "pnpm build",
"frontendDist": "../dist"
},
"app": {
"windows": [
{
"title": "check-mihomo-api",
"width": 800,
"height": 600
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}
@@ -0,0 +1,116 @@
.logo.vite:hover {
filter: drop-shadow(0 0 2em #747bff);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafb);
}
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}
.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}
.row {
display: flex;
justify-content: center;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}
input,
button {
outline: none;
}
#greet-input {
margin-right: 5px;
}
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}
a:hover {
color: #24c8db;
}
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}
@@ -0,0 +1,49 @@
import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import "./App.css";
import { getGroups } from "tauri-plugin-mihomo-api";
import CodeMirror from "@uiw/react-codemirror";
import { json } from "@codemirror/lang-json";
function App() {
const [response, setResponse] = useState("");
async function format_json(text: string) {
return await invoke<string>("cmd_format_json", { text });
}
async function check() {
try {
// await upgradeCore();
let data = await getGroups();
const formattedJson = await format_json(JSON.stringify(data));
setResponse(formattedJson);
} catch (err: any) {
setResponse(err.toString());
}
}
return (
<main style={{ backgroundColor: "white" }}>
<div className="row">
<button
onClick={() => {
check();
}}>
Check
</button>
</div>
<CodeMirror
style={{ marginTop: "10px", textAlign: "left" }}
width="100%"
height="85dvh"
minHeight="480px"
value={response}
theme={"dark"}
extensions={[json()]}
/>
</main>
);
}
export default App;
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,9 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
@@ -0,0 +1 @@
/// <reference types="vite/client" />
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
@@ -0,0 +1,32 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST;
// https://vite.dev/config/
export default defineConfig(async () => ({
plugins: [react()],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
//
// 1. prevent Vite from obscuring rust errors
clearScreen: false,
// 2. tauri expects a fixed port, fail if that port is not available
server: {
port: 1420,
strictPort: true,
host: host || false,
hmr: host
? {
protocol: "ws",
host,
port: 1421,
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
},
},
}));
@@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ClashMode } from "./ClashMode";
import type { FindProcessMode } from "./FindProcessMode";
import type { GeoXUrl } from "./GeoXUrl";
import type { LogLevel } from "./LogLevel";
import type { TuicServer } from "./TuicServer";
import type { TunConfig } from "./TunConfig";
export type BaseConfig = { port: number, socksPort: number, redirPort: number, tproxyPort: number, mixedPort: number, tun: TunConfig, tuicServer: TuicServer, ssConfig: string, vmessConfig: string, authentication: Array<string> | null, skipAuthPrefixes: Array<string> | null, lanAllowedIps: Array<string> | null, lanDisallowedIps: Array<string> | null, allowLan: boolean, bindAddress: string, inboundTfo: boolean, inboundMptcp: boolean, mode: ClashMode, unifiedDelay: boolean, logLevel: LogLevel, ipv6: boolean, interfaceName: string, routingMark: number, geoxUrl: GeoXUrl, geoAutoUpdate: boolean, geoUpdateInterval: number, geodataMode: boolean, geodataLoader: string, geositeMatcher: string, tcpConcurrent: boolean, findProcessMode: FindProcessMode, sniffing: boolean, globalClientFingerprint: string, globalUa: string, etagSupport: boolean, keepAliveInterval: number, keepAliveIdle: number, disableKeepAlive: boolean, };
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type BrutalOption = { enabled: boolean, up?: string, down?: string, };
@@ -0,0 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* clash mode enum
*/
export type ClashMode = "rule" | "global" | "direct";
@@ -0,0 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ConnectionMetaData } from "./ConnectionMetaData";
export type Connection = { id: string, metadata: ConnectionMetaData, upload: bigint, download: bigint, start: string, chains: Array<string>, rule: string, rulePayload: string, };
@@ -0,0 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ConnectionType } from "./ConnectionType";
import type { DNSMode } from "./DNSMode";
import type { Network } from "./Network";
export type ConnectionMetaData = { network: Network, type: ConnectionType, sourceIP: string, destinationIP: string, sourceGeoIP: Array<string> | null, destinationGeoIP: Array<string> | null, sourceIPASN: string, destinationIPASN: string, sourcePort: string, destinationPort: string, inboundIP: string, inboundPort: string, inboundName: string, inboundUser: string, host: string, dnsMode: DNSMode, uid: number, process: string, processPath: string, specialProxy: string, specialRules: string, remoteDestination: string, dscp: number, sniffHost: string, };
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ConnectionType = "HTTP" | "HTTPS" | "Socks4" | "Socks5" | "ShadowSocks" | "Vmess" | "Vless" | "Redir" | "TProxy" | "Trojan" | "Tunnel" | "Tun" | "Tuic" | "Hysteria2" | "AnyTLS" | "Inner";
@@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Connection } from "./Connection";
/**
* connections
*/
export type Connections = { downloadTotal: bigint, uploadTotal: bigint, connections: Array<Connection> | null, memory: number, };
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type CoreUpdaterChannel = "release" | "alpha" | "auto";
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DNSMode = "normal" | "fake-ip" | "redir-host" | "hosts";
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DelayHistory = { time: string, delay: number, };
@@ -0,0 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DelayHistory } from "./DelayHistory";
export type Extra = { alive: boolean, history: Array<DelayHistory>, };
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type FindProcessMode = "strict" | "always" | "off";

Some files were not shown because too many files have changed in this diff Show More