allow open rpc port in gui normal mode (#1795)
Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier Core / build_web (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-loongarch64, ubuntu-24.04, loongarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-riscv64, ubuntu-22.04, riscv64gc-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier Core / magisk_build (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier OHOS / cargo_fmt_check (push) Has been cancelled
EasyTier OHOS / pre_job (push) Has been cancelled
EasyTier OHOS / build-ohos (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled

* allow open rpc port for gui normal mode
* downgrade dev tool console
This commit is contained in:
KKRainbow
2026-01-16 11:12:32 +08:00
committed by GitHub
parent 53264f67bf
commit 005b321f62
11 changed files with 295 additions and 117 deletions

1
Cargo.lock generated
View File

@@ -2326,6 +2326,7 @@ dependencies = [
"tauri-plugin-vpnservice",
"thunk-rs",
"tokio",
"url",
"uuid",
"winapi",
"windows 0.52.0",

View File

@@ -54,7 +54,7 @@
"unplugin-vue-router": "^0.10.8",
"uuid": "^10.0.0",
"vite": "^5.4.8",
"vite-plugin-vue-devtools": "^8.0.5",
"vite-plugin-vue-devtools": "^7.4.6",
"vite-plugin-vue-layouts": "^0.11.0",
"vue-i18n": "^10.0.0",
"vue-tsc": "^2.1.10"

View File

@@ -57,6 +57,8 @@ tauri-plugin-os = "2.3.0"
uuid = "1.17.0"
async-trait = "0.1.89"
url = { version = "2.5", features = ["serde"] }
[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
winapi = { version = "0.3.9", features = ["securitybaseapi", "processthreadsapi"] }

View File

@@ -19,11 +19,13 @@ use easytier::{
launcher::NetworkConfig,
rpc_service::ApiRpcServer,
tunnel::ring::RingTunnelListener,
tunnel::tcp::TcpTunnelListener,
tunnel::TunnelListener,
utils::{self},
};
use std::ops::Deref;
use std::sync::Arc;
use tokio::sync::{RwLock, RwLockReadGuard};
use tokio::sync::{Mutex, RwLock, RwLockReadGuard};
use uuid::Uuid;
use tauri::{AppHandle, Emitter, Manager as _};
@@ -40,8 +42,21 @@ static RPC_RING_UUID: once_cell::sync::Lazy<uuid::Uuid> =
static CLIENT_MANAGER: once_cell::sync::Lazy<RwLock<Option<manager::GUIClientManager>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
static RING_RPC_SERVER: once_cell::sync::Lazy<RwLock<Option<ApiRpcServer<RingTunnelListener>>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
type BoxedTunnelListener = Box<dyn TunnelListener>;
#[derive(Clone, Copy, PartialEq, Eq)]
enum RpcServerKind {
Ring,
Tcp,
}
struct RpcServer {
kind: RpcServerKind,
_server: ApiRpcServer<BoxedTunnelListener>,
bind_url: Option<url::Url>,
}
static RPC_SERVER: once_cell::sync::Lazy<Mutex<Option<RpcServer>>> =
once_cell::sync::Lazy::new(|| Mutex::new(None));
static WEB_CLIENT: once_cell::sync::Lazy<RwLock<Option<WebClient>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
@@ -322,8 +337,25 @@ fn get_service_status() -> Result<&'static str, String> {
}
}
fn normalize_normal_mode_rpc_portal(portal: &str) -> Result<(url::Url, url::Url), String> {
let portal_url: url::Url = portal
.parse()
.map_err(|e| format!("invalid rpc portal: {:#}", e))?;
let bind_url = portal_url.clone();
let mut connect_url = portal_url.clone();
// if bind addr is 0.0.0.0, should convert to 127.0.0.1
if connect_url.host_str() == Some("0.0.0.0") {
connect_url.set_host(Some("127.0.0.1")).unwrap();
}
Ok((bind_url, connect_url))
}
#[tauri::command]
async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(), String> {
async fn init_rpc_connection(
_app: AppHandle,
is_normal_mode: bool,
url: Option<String>,
) -> Result<(), String> {
let mut client_manager_guard =
tokio::time::timeout(std::time::Duration::from_secs(5), CLIENT_MANAGER.write())
.await
@@ -331,41 +363,72 @@ async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(),
let mut instance_manager_guard = INSTANCE_MANAGER
.try_write()
.map_err(|_| "Failed to acquire write lock for instance manager")?;
let mut ring_rpc_server_guard = RING_RPC_SERVER
.try_write()
.map_err(|_| "Failed to acquire write lock for ring rpc server")?;
let mut rpc_server_guard = RPC_SERVER
.try_lock()
.map_err(|_| "Failed to acquire lock for rpc server")?;
let normal_mode = url.is_none();
if normal_mode {
let mut client_url = url.clone();
if is_normal_mode {
let instance_manager = if let Some(im) = instance_manager_guard.take() {
im
} else {
Arc::new(NetworkInstanceManager::new())
};
let rpc_server = if let Some(rpc_server) = ring_rpc_server_guard.take() {
rpc_server
let portal = url.and_then(|s| {
let trimmed = s.trim().to_string();
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
});
let (desired_kind, bind_url, connect_url) = if let Some(portal) = portal {
let (bind_url, connect_url) = normalize_normal_mode_rpc_portal(&portal)?;
(RpcServerKind::Tcp, Some(bind_url), Some(connect_url))
} else {
ApiRpcServer::from_tunnel(
RingTunnelListener::new(
format!("ring://{}", RPC_RING_UUID.deref()).parse().unwrap(),
),
instance_manager.clone(),
)
.with_rx_timeout(None)
.serve()
.await
.map_err(|e| e.to_string())?
(RpcServerKind::Ring, None, None)
};
let need_restart = rpc_server_guard
.as_ref()
.map(|x| x.kind != desired_kind || x.bind_url != bind_url)
.unwrap_or(true);
if need_restart {
*rpc_server_guard = None;
let tunnel: BoxedTunnelListener = match desired_kind {
RpcServerKind::Ring => Box::new(RingTunnelListener::new(
format!("ring://{}", RPC_RING_UUID.deref()).parse().unwrap(),
)),
RpcServerKind::Tcp => Box::new(TcpTunnelListener::new(
bind_url.clone().expect("tcp rpc must have bind url"),
)),
};
let rpc_server = ApiRpcServer::from_tunnel(tunnel, instance_manager.clone())
.with_rx_timeout(None)
.serve()
.await
.map_err(|e| e.to_string())?;
*rpc_server_guard = Some(RpcServer {
kind: desired_kind,
_server: rpc_server,
bind_url,
});
}
*instance_manager_guard = Some(instance_manager);
*ring_rpc_server_guard = Some(rpc_server);
client_url = connect_url.map(|u| u.to_string());
} else {
*ring_rpc_server_guard = None;
*rpc_server_guard = None;
}
let client_manager = tokio::time::timeout(
std::time::Duration::from_millis(1000),
manager::GUIClientManager::new(url),
manager::GUIClientManager::new(client_url),
)
.await
.map_err(|_| "connect remote rpc timed out".to_string())?
@@ -373,7 +436,7 @@ async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(),
.map_err(|e| format!("{:#}", e))?;
*client_manager_guard = Some(client_manager);
if !normal_mode {
if !is_normal_mode {
drop(WEB_CLIENT.write().await.take());
if let Some(instance_manager) = instance_manager_guard.take() {
instance_manager

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, watch, onMounted, ref } from 'vue';
import type { Mode, ServiceMode, RemoteMode } from '~/composables/mode';
import type { Mode, ServiceMode, RemoteMode, NormalMode } from '~/composables/mode';
import { appConfigDir, appLogDir } from '@tauri-apps/api/path';
import { join } from '@tauri-apps/api/path';
import { getServiceStatus, type ServiceStatus } from '~/composables/backend';
@@ -15,6 +15,14 @@ const defaultLogDir = ref('')
const serviceStatus = ref<ServiceStatus>('NotInstalled')
const isServiceStatusLoaded = ref(false)
function normalizeRpcListenPort(port: unknown): number {
const defaultPort = 15999
const numericPort = typeof port === 'number' ? port : Number.parseInt(String(port ?? ''), 10)
if (Number.isNaN(numericPort))
return defaultPort
return Math.min(65535, Math.max(1, Math.floor(numericPort)))
}
onMounted(async () => {
defaultConfigDir.value = await join(await appConfigDir(), 'config.d')
defaultLogDir.value = await appLogDir()
@@ -26,6 +34,43 @@ const modeOptions = computed(() => [
{ label: t('mode.remote'), value: 'remote' },
]);
const normalMode = computed({
get: () => model.value.mode === 'normal' ? model.value as NormalMode : undefined,
set: (value) => {
if (value) {
model.value = value
}
}
})
const rpcListenOptions = computed(() => [
{ label: t('web.common.disable'), value: false },
{ label: t('web.common.enable'), value: true },
])
const rpcListenEnabled = computed<boolean>({
get: () => !!normalMode.value?.enable_rpc_port_listen,
set: (value) => {
if (!normalMode.value)
return
normalMode.value.enable_rpc_port_listen = value
},
})
const rpcListenPort = computed<string>({
get: () => String(normalMode.value?.rpc_listen_port ?? 15999),
set: (value) => {
if (!normalMode.value)
return
const trimmed = value.trim()
if (trimmed === '')
return
if (!/^\d+$/.test(trimmed))
return
normalMode.value.rpc_listen_port = Number.parseInt(trimmed, 10)
},
})
const serviceMode = computed({
get: () => model.value.mode === 'service' ? model.value as ServiceMode : undefined,
set: (value) => {
@@ -57,6 +102,24 @@ const statusColorClass = computed(() => {
}
})
watch(() => [normalMode.value?.enable_rpc_port_listen, normalMode.value?.rpc_listen_port], ([enabled, port]) => {
if (!normalMode.value)
return
if (!enabled) {
normalMode.value.rpc_portal = undefined
return
}
const normalizedPort = normalizeRpcListenPort(port)
if (normalMode.value.rpc_listen_port !== normalizedPort)
normalMode.value.rpc_listen_port = normalizedPort
const desiredPortal = `tcp://0.0.0.0:${normalizedPort}`
if (normalMode.value.rpc_portal !== desiredPortal)
normalMode.value.rpc_portal = desiredPortal
}, { immediate: true })
watch(() => model.value.mode, async (newMode, oldMode) => {
if (newMode === oldMode)
return
@@ -69,8 +132,12 @@ watch(() => model.value.mode, async (newMode, oldMode) => {
const oldModelValue = { ...model.value }
if (newMode === 'normal') {
const portal = normalMode.value?.rpc_portal?.trim()
model.value = {
...oldModelValue,
rpc_portal: portal || undefined,
enable_rpc_port_listen: normalMode.value?.enable_rpc_port_listen,
rpc_listen_port: normalMode.value?.rpc_listen_port,
mode: 'normal',
}
}
@@ -113,6 +180,20 @@ watch(() => model.value.mode, async (newMode, oldMode) => {
{{ t('mode.remote_description') }}
</div>
<div v-if="normalMode" class="flex flex-col gap-2">
<div class="flex items-center gap-2">
<label for="rpc-listen-toggle">{{ t('mode.enable_rpc_tcp_listen') }}</label>
<SelectButton id="rpc-listen-toggle" v-model="rpcListenEnabled" :options="rpcListenOptions" option-label="label"
option-value="value" />
</div>
<div v-if="rpcListenEnabled" class="flex flex-col gap-2">
<div class="flex items-center gap-2">
<label for="rpc-listen-port">{{ t('mode.rpc_listen_port') }}</label>
<InputText id="rpc-listen-port" v-model="rpcListenPort" class="flex-1" inputmode="numeric" />
</div>
</div>
</div>
<div v-if="serviceMode" class="flex flex-col gap-2">
<div class="flex items-center gap-2">
<label for="config-dir">{{ t('mode.config_dir') }}</label>

View File

@@ -89,8 +89,8 @@ export async function getServiceStatus() {
return await invoke<ServiceStatus>('get_service_status')
}
export async function initRpcConnection(url?: string) {
return await invoke('init_rpc_connection', { url })
export async function initRpcConnection(isNormalMode: boolean, url?: string) {
return await invoke('init_rpc_connection', { isNormalMode, url })
}
export async function isClientRunning() {

View File

@@ -4,8 +4,12 @@ export interface WebClientConfig {
config_server_url?: string
}
interface NormalMode extends WebClientConfig {
export interface NormalMode extends WebClientConfig {
mode: 'normal'
// if not provided will use ring tunnel rpc server
rpc_portal?: string
enable_rpc_port_listen?: boolean
rpc_listen_port?: number
}
export interface ServiceMode extends WebClientConfig {

View File

@@ -156,13 +156,23 @@ async function initWithMode(mode: Mode) {
url = "tcp://" + mode.rpc_portal.replace("0.0.0.0", "127.0.0.1")
retrys = 5
break;
case 'normal':
url = mode.rpc_portal;
break;
}
for (let i = 0; i < retrys; i++) {
try {
await connectRpcClient(url)
await connectRpcClient(mode.mode === 'normal', url)
break;
} catch (e) {
if (i === retrys - 1) {
const errMsg = e instanceof Error ? e.message : String(e)
toast.add({
severity: 'error',
summary: t('error'),
detail: t('mode.rpc_connection_failed', { error: errMsg }),
life: 1000,
})
throw e;
}
console.error("Error connecting rpc client, retrying...", e)
@@ -332,9 +342,9 @@ const setting_menu_items: Ref<MenuItem[]> = ref([
},
])
async function connectRpcClient(url?: string) {
await initRpcConnection(url)
console.log("easytier rpc connection established")
async function connectRpcClient(isNormalMode: boolean, url?: string) {
await initRpcConnection(isNormalMode, url)
console.log("easytier rpc connection established, isNormalMode: ", isNormalMode)
}
onMounted(async () => {

View File

@@ -334,6 +334,8 @@ web:
success: 成功
warning: 警告
info: 提示
enable: 开启
disable: 关闭
settings:
title: 设置
@@ -350,6 +352,8 @@ mode:
switch_mode: 切换模式
config_dir: 配置目录
rpc_portal: RPC端口
enable_rpc_tcp_listen: 开启 RPC 端口监听TCP
rpc_listen_port: RPC 监听端口
log_level: 日志级别
log_dir: 日志目录
remote_rpc_address: 远程RPC地址
@@ -370,6 +374,7 @@ mode:
stop_service_success: 服务停止成功
remote_rpc_address_empty: 远程RPC地址不能为空
service_config_empty: 服务配置不能为空
rpc_connection_failed: "RPC 连接失败:{error}"
config-server:
title: 配置服务器

View File

@@ -334,6 +334,8 @@ web:
success: Success
warning: Warning
info: Info
enable: Enable
disable: Disable
settings:
title: Settings
@@ -350,6 +352,8 @@ mode:
switch_mode: Switch Mode
config_dir: Config Dir
rpc_portal: RPC Portal
enable_rpc_tcp_listen: Enable RPC port listening (TCP)
rpc_listen_port: RPC Listen Port
log_level: Log Level
log_dir: Log Dir
remote_rpc_address: Remote RPC Address
@@ -370,6 +374,7 @@ mode:
stop_service_success: Service stopped successfully
remote_rpc_address_empty: Remote RPC Address cannot be empty
service_config_empty: Service Config cannot be empty
rpc_connection_failed: "RPC connection failed: {error}"
config-server:
title: Config Server

173
pnpm-lock.yaml generated
View File

@@ -127,8 +127,8 @@ importers:
specifier: ^5.4.8
version: 5.4.19(@types/node@22.18.1)
vite-plugin-vue-devtools:
specifier: ^8.0.5
version: 8.0.5(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))
specifier: ^7.4.6
version: 7.4.6(rollup@4.50.1)(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))
vite-plugin-vue-layouts:
specifier: ^0.11.0
version: 0.11.0(vite@5.4.19(@types/node@22.18.1))(vue-router@4.5.1(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))
@@ -949,8 +949,8 @@ packages:
resolution: {integrity: sha512-BcmHpb5bQyeVNrptC3UhzpBZB/YHHDoEREOUERrmF2BRxsyOEuRrq+Z96C/D4+2KJb8kuHiouzAei7BXlG0YYw==}
engines: {node: '>= 16'}
'@intlify/shared@11.2.7':
resolution: {integrity: sha512-uvlkvc/0uQ4FDlHQZccpUnmcOwNcaI3i+69ck2YJ+GqM35AoVbuS63b+YfirV4G0SZh64Ij2UMcFRMmB4nr95w==}
'@intlify/shared@11.2.8':
resolution: {integrity: sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==}
engines: {node: '>= 16'}
'@intlify/shared@12.0.0-alpha.3':
@@ -1898,16 +1898,16 @@ packages:
'@vue/devtools-api@6.6.4':
resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
'@vue/devtools-core@8.0.5':
resolution: {integrity: sha512-dpCw8nl0GDBuiL9SaY0mtDxoGIEmU38w+TQiYEPOLhW03VDC0lfNMYXS/qhl4I0YlysGp04NLY4UNn6xgD0VIQ==}
'@vue/devtools-core@7.7.9':
resolution: {integrity: sha512-48jrBSwG4GVQRvVeeXn9p9+dlx+ISgasM7SxZZKczseohB0cBz+ITKr4YbLWjmJdy45UHL7UMPlR4Y0CWTRcSQ==}
peerDependencies:
vue: ^3.0.0
'@vue/devtools-kit@8.0.5':
resolution: {integrity: sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg==}
'@vue/devtools-kit@7.7.9':
resolution: {integrity: sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==}
'@vue/devtools-shared@8.0.5':
resolution: {integrity: sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg==}
'@vue/devtools-shared@7.7.9':
resolution: {integrity: sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==}
'@vue/language-core@2.1.10':
resolution: {integrity: sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ==}
@@ -2027,10 +2027,6 @@ packages:
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'}
ansis@4.2.0:
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
engines: {node: '>=14'}
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
@@ -2079,9 +2075,6 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
birpc@2.5.0:
resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==}
birpc@2.9.0:
resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==}
@@ -2303,8 +2296,8 @@ packages:
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
error-stack-parser-es@1.0.5:
resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
error-stack-parser-es@0.1.5:
resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==}
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
@@ -2578,6 +2571,10 @@ packages:
resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==}
engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0}
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
exsolve@1.0.7:
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
@@ -2695,6 +2692,10 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
get-stream@8.0.1:
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
engines: {node: '>=16'}
get-tsconfig@4.10.1:
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
@@ -2772,6 +2773,10 @@ packages:
resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
engines: {node: '>=14.18.0'}
human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -3264,9 +3269,6 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
ohash@2.0.11:
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
onetime@6.0.0:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
@@ -3354,8 +3356,8 @@ packages:
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
perfect-debounce@2.0.0:
resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==}
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -3603,6 +3605,10 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
sirv@2.0.4:
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
engines: {node: '>= 10'}
sirv@3.0.2:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
@@ -3880,10 +3886,6 @@ packages:
webpack:
optional: true
unplugin-utils@0.3.1:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
unplugin-vue-components@0.27.5:
resolution: {integrity: sha512-m9j4goBeNwXyNN8oZHHxvIIYiG8FQ9UfmKWeNllpDvhU7btKNNELGPt+o3mckQKuPwrE7e0PvCsx+IWuDSD9Vg==}
engines: {node: '>=14'}
@@ -3954,11 +3956,6 @@ packages:
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
vite-dev-rpc@1.1.0:
resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==}
peerDependencies:
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0
vite-hot-client@2.1.0:
resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==}
peerDependencies:
@@ -3973,12 +3970,12 @@ packages:
vite:
optional: true
vite-plugin-inspect@11.3.3:
resolution: {integrity: sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==}
vite-plugin-inspect@0.8.9:
resolution: {integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==}
engines: {node: '>=14'}
peerDependencies:
'@nuxt/kit': '*'
vite: ^6.0.0 || ^7.0.0-0
vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1
peerDependenciesMeta:
'@nuxt/kit':
optional: true
@@ -3990,11 +3987,11 @@ packages:
rollup: ^4.44.1
vite: ^5.4.11 || ^6.0.0 || ^7.0.0
vite-plugin-vue-devtools@8.0.5:
resolution: {integrity: sha512-p619BlKFOqQXJ6uDWS1vUPQzuJOD6xJTfftj57JXBGoBD/yeQCowR7pnWcr/FEX4/HVkFbreI6w2uuGBmQOh6A==}
vite-plugin-vue-devtools@7.4.6:
resolution: {integrity: sha512-lOKur3qovCB3BQStL0qfHEoIusqya1ngfxfWuqn9DTa6h9rlw6+S3PV4geOP5YBGYQ4NW1hRX70OD8I+sYr1dA==}
engines: {node: '>=v14.21.3'}
peerDependencies:
vite: ^6.0.0 || ^7.0.0-0
vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0
vite-plugin-vue-inspector@5.3.2:
resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==}
@@ -4068,12 +4065,14 @@ packages:
vue-i18n@10.0.8:
resolution: {integrity: sha512-mIjy4utxMz9lMMo6G9vYePv7gUFt4ztOMhY9/4czDJxZ26xPeJ49MAGa9wBAE3XuXbYCrtVPmPxNjej7JJJkZQ==}
engines: {node: '>= 16'}
deprecated: v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html
peerDependencies:
vue: ^3.0.0
vue-i18n@9.14.5:
resolution: {integrity: sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==}
engines: {node: '>= 16'}
deprecated: v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html
peerDependencies:
vue: ^3.0.0
@@ -4737,7 +4736,7 @@ snapshots:
'@intlify/shared@10.0.8': {}
'@intlify/shared@11.2.7': {}
'@intlify/shared@11.2.8': {}
'@intlify/shared@12.0.0-alpha.3': {}
@@ -4747,8 +4746,8 @@ snapshots:
dependencies:
'@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.5.1))
'@intlify/bundle-utils': 9.0.0(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))
'@intlify/shared': 11.2.7
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.2.7)(@vue/compiler-dom@3.5.21)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))
'@intlify/shared': 11.2.8
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.2.8)(@vue/compiler-dom@3.5.21)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))
'@rollup/pluginutils': 5.3.0(rollup@4.50.1)
'@typescript-eslint/scope-manager': 8.42.0
'@typescript-eslint/typescript-estree': 8.42.0(typescript@5.6.3)
@@ -4770,11 +4769,11 @@ snapshots:
- supports-color
- typescript
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.2.7)(@vue/compiler-dom@3.5.21)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))':
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.2.8)(@vue/compiler-dom@3.5.21)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))':
dependencies:
'@babel/parser': 7.28.4
optionalDependencies:
'@intlify/shared': 11.2.7
'@intlify/shared': 11.2.8
'@vue/compiler-dom': 3.5.21
vue: 3.5.21(typescript@5.6.3)
vue-i18n: 10.0.8(vue@3.5.21(typescript@5.6.3))
@@ -5774,10 +5773,10 @@ snapshots:
'@vue/devtools-api@6.6.4': {}
'@vue/devtools-core@8.0.5(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))':
'@vue/devtools-core@7.7.9(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))':
dependencies:
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
'@vue/devtools-kit': 7.7.9
'@vue/devtools-shared': 7.7.9
mitt: 3.0.1
nanoid: 5.1.5
pathe: 2.0.3
@@ -5786,17 +5785,17 @@ snapshots:
transitivePeerDependencies:
- vite
'@vue/devtools-kit@8.0.5':
'@vue/devtools-kit@7.7.9':
dependencies:
'@vue/devtools-shared': 8.0.5
'@vue/devtools-shared': 7.7.9
birpc: 2.9.0
hookable: 5.5.3
mitt: 3.0.1
perfect-debounce: 2.0.0
perfect-debounce: 1.0.0
speakingurl: 14.0.1
superjson: 2.2.2
'@vue/devtools-shared@8.0.5':
'@vue/devtools-shared@7.7.9':
dependencies:
rfdc: 1.4.1
@@ -5946,8 +5945,6 @@ snapshots:
ansi-styles@6.2.1: {}
ansis@4.2.0: {}
any-promise@1.3.0: {}
anymatch@3.1.3:
@@ -5999,8 +5996,6 @@ snapshots:
binary-extensions@2.3.0: {}
birpc@2.5.0: {}
birpc@2.9.0: {}
boolbase@1.0.0: {}
@@ -6196,7 +6191,7 @@ snapshots:
dependencies:
is-arrayish: 0.2.1
error-stack-parser-es@1.0.5: {}
error-stack-parser-es@0.1.5: {}
es-define-property@1.0.1: {}
@@ -6606,6 +6601,18 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 3.0.0
execa@8.0.1:
dependencies:
cross-spawn: 7.0.6
get-stream: 8.0.1
human-signals: 5.0.0
is-stream: 3.0.0
merge-stream: 2.0.0
npm-run-path: 5.3.0
onetime: 6.0.0
signal-exit: 4.1.0
strip-final-newline: 3.0.0
exsolve@1.0.7: {}
extend-shallow@2.0.1:
@@ -6721,6 +6728,8 @@ snapshots:
get-stream@6.0.1: {}
get-stream@8.0.1: {}
get-tsconfig@4.10.1:
dependencies:
resolve-pkg-maps: 1.0.0
@@ -6787,6 +6796,8 @@ snapshots:
human-signals@4.3.1: {}
human-signals@5.0.0: {}
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -7404,8 +7415,6 @@ snapshots:
object-hash@3.0.0: {}
ohash@2.0.11: {}
onetime@6.0.0:
dependencies:
mimic-fn: 4.0.0
@@ -7500,7 +7509,7 @@ snapshots:
pathe@2.0.3: {}
perfect-debounce@2.0.0: {}
perfect-debounce@1.0.0: {}
picocolors@1.1.1: {}
@@ -7740,6 +7749,12 @@ snapshots:
signal-exit@4.1.0: {}
sirv@2.0.4:
dependencies:
'@polka/url': 1.0.0-next.29
mrmime: 2.0.1
totalist: 3.0.1
sirv@3.0.2:
dependencies:
'@polka/url': 1.0.0-next.29
@@ -8024,11 +8039,6 @@ snapshots:
unplugin: 1.16.1
vite: 5.4.19(@types/node@22.18.1)
unplugin-utils@0.3.1:
dependencies:
pathe: 2.0.3
picomatch: 4.0.3
unplugin-vue-components@0.27.5(@babel/parser@7.28.4)(rollup@4.50.1)(vue@3.5.21(typescript@5.6.3)):
dependencies:
'@antfu/utils': 0.7.10
@@ -8192,12 +8202,6 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
vite-dev-rpc@1.1.0(vite@5.4.19(@types/node@22.18.1)):
dependencies:
birpc: 2.5.0
vite: 5.4.19(@types/node@22.18.1)
vite-hot-client: 2.1.0(vite@5.4.19(@types/node@22.18.1))
vite-hot-client@2.1.0(vite@5.4.19(@types/node@22.18.1)):
dependencies:
vite: 5.4.19(@types/node@22.18.1)
@@ -8221,19 +8225,20 @@ snapshots:
- rollup
- supports-color
vite-plugin-inspect@11.3.3(vite@5.4.19(@types/node@22.18.1)):
vite-plugin-inspect@0.8.9(rollup@4.50.1)(vite@5.4.19(@types/node@22.18.1)):
dependencies:
ansis: 4.2.0
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.3.0(rollup@4.50.1)
debug: 4.4.1
error-stack-parser-es: 1.0.5
ohash: 2.0.11
error-stack-parser-es: 0.1.5
fs-extra: 11.3.1
open: 10.2.0
perfect-debounce: 2.0.0
perfect-debounce: 1.0.0
picocolors: 1.1.1
sirv: 3.0.2
unplugin-utils: 0.3.1
vite: 5.4.19(@types/node@22.18.1)
vite-dev-rpc: 1.1.0(vite@5.4.19(@types/node@22.18.1))
transitivePeerDependencies:
- rollup
- supports-color
vite-plugin-singlefile@2.3.0(rollup@4.50.1)(vite@5.4.19(@types/node@22.18.1)):
@@ -8242,17 +8247,19 @@ snapshots:
rollup: 4.50.1
vite: 5.4.19(@types/node@22.18.1)
vite-plugin-vue-devtools@8.0.5(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3)):
vite-plugin-vue-devtools@7.4.6(rollup@4.50.1)(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3)):
dependencies:
'@vue/devtools-core': 8.0.5(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
sirv: 3.0.2
'@vue/devtools-core': 7.7.9(vite@5.4.19(@types/node@22.18.1))(vue@3.5.21(typescript@5.6.3))
'@vue/devtools-kit': 7.7.9
'@vue/devtools-shared': 7.7.9
execa: 8.0.1
sirv: 2.0.4
vite: 5.4.19(@types/node@22.18.1)
vite-plugin-inspect: 11.3.3(vite@5.4.19(@types/node@22.18.1))
vite-plugin-inspect: 0.8.9(rollup@4.50.1)(vite@5.4.19(@types/node@22.18.1))
vite-plugin-vue-inspector: 5.3.2(vite@5.4.19(@types/node@22.18.1))
transitivePeerDependencies:
- '@nuxt/kit'
- rollup
- supports-color
- vue