feat: support enable/disable mDNS

fix: remove redundant STUN server
perf:  support disable STUN server (for local networks)
perf:  update GOMEMLIMIT from 50 to 75
perf:  add `-b` parameter to `ether-wake`
chore: bump vite to v6.2.1
This commit is contained in:
wj-xiao
2025-03-07 17:22:57 +08:00
parent c91ce5ab62
commit b062569aab
19 changed files with 490 additions and 253 deletions

View File

@@ -21,7 +21,7 @@ var defaultConfig = &Config{
},
Stun: "stun.l.google.com:19302",
Turn: Turn{
TurnAddr: "turn.cloudflare.com:3478",
TurnAddr: "",
TurnUser: "",
TurnCred: "",
},

View File

@@ -83,3 +83,7 @@ type GetOLEDRsp struct {
type GetSSHStateRsp struct {
Enabled bool `json:"enabled"`
}
type GetMdnsStateRsp struct {
Enabled bool `json:"enabled"`
}

View File

@@ -39,4 +39,8 @@ func vmRouter(r *gin.Engine) {
api.GET("/vm/ssh", service.GetSSHState) // get SSH state
api.POST("/vm/ssh/enable", service.EnableSSH) // enable SSH
api.POST("/vm/ssh/disable", service.DisableSSH) // disable SSH
api.GET("/vm/mdns", service.GetMdnsState) // get mDNS state
api.POST("/vm/mdns/enable", service.EnableMdns) // enable mDNS
api.POST("/vm/mdns/disable", service.DisableMdns) // disable mDNS
}

View File

@@ -16,6 +16,8 @@ const (
TailscalePath = "/usr/bin/tailscale"
TailscaledPath = "/usr/sbin/tailscaled"
ConfigPath = "etc/sysctl.d/99-tailscale.conf"
GoMemLimit int64 = 75
)
var StateMap = map[string]proto.TailscaleState{
@@ -69,7 +71,7 @@ func (s *Service) Start(c *gin.Context) {
}
if !utils.IsGoMemLimitExist() {
_ = utils.SetGoMemLimit(50)
_ = utils.SetGoMemLimit(GoMemLimit)
}
rsp.OkRsp(c)
@@ -165,7 +167,7 @@ func (s *Service) Login(c *gin.Context) {
}
if !utils.IsGoMemLimitExist() {
_ = utils.SetGoMemLimit(50)
_ = utils.SetGoMemLimit(GoMemLimit)
}
rsp.OkRspWithData(c, &proto.LoginTailscaleRsp{

View File

@@ -33,7 +33,7 @@ func (s *Service) WakeOnLAN(c *gin.Context) {
return
}
command := fmt.Sprintf("ether-wake %s", mac)
command := fmt.Sprintf("ether-wake -b %s", mac)
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()

View File

@@ -39,7 +39,7 @@ func Connect(c *gin.Context) {
var iceServers []webrtc.ICEServer
if conf.Stun != "" {
if conf.Stun != "" && conf.Stun != "disable" {
iceServers = append(iceServers, webrtc.ICEServer{
URLs: []string{"stun:" + conf.Stun},
})
@@ -53,11 +53,9 @@ func Connect(c *gin.Context) {
})
}
rtc_config := webrtc.Configuration{
peerConn, err := webrtc.NewPeerConnection(webrtc.Configuration{
ICEServers: iceServers,
}
peerConn, err := webrtc.NewPeerConnection(rtc_config)
})
if err != nil {
log.Errorf("failed to create PeerConnection: %s", err)
return

View File

@@ -18,7 +18,7 @@ var imageVersionMap = map[string]string{
"2024-07-23-20-18-587710.img": "v1.1.0",
"2024-08-08-19-44-bef2ca.img": "v1.2.0",
"2024-11-13-09-59-9c961a.img": "v1.3.0",
"2025-02-17-16-59-3649fe.img": "v1.4.0",
"2025-02-17-19-08-3649fe.img": "v1.4.0",
}
func (s *Service) GetInfo(c *gin.Context) {
@@ -53,6 +53,10 @@ func getIp() string {
}
func getMdns() string {
if pid := getAvahiDaemonPid(); pid == "" {
return ""
}
content, err := os.ReadFile("/etc/hostname")
if err != nil {
return ""

91
server/service/vm/mdns.go Normal file
View File

@@ -0,0 +1,91 @@
package vm
import (
"NanoKVM-Server/proto"
"fmt"
"os"
"os/exec"
"strings"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)
const (
AvahiDaemonPid = "/run/avahi-daemon/pid"
AvahiDaemonScript = "/etc/init.d/S50avahi-daemon"
AvahiDaemonBackupScript = "/kvmapp/system/init.d/S50avahi-daemon"
)
func (s *Service) GetMdnsState(c *gin.Context) {
var rsp proto.Response
pid := getAvahiDaemonPid()
rsp.OkRspWithData(c, &proto.GetMdnsStateRsp{
Enabled: pid != "",
})
}
func (s *Service) EnableMdns(c *gin.Context) {
var rsp proto.Response
pid := getAvahiDaemonPid()
if pid != "" {
rsp.OkRsp(c)
return
}
commands := []string{
fmt.Sprintf("cp -f %s %s", AvahiDaemonBackupScript, AvahiDaemonScript),
fmt.Sprintf("%s start", AvahiDaemonScript),
}
command := strings.Join(commands, " && ")
err := exec.Command("sh", "-c", command).Run()
if err != nil {
log.Errorf("failed to start avahi-daemon: %s", err)
rsp.ErrRsp(c, -1, "failed to enable mdns")
return
}
rsp.OkRsp(c)
log.Debugf("avahi-daemon started")
}
func (s *Service) DisableMdns(c *gin.Context) {
var rsp proto.Response
pid := getAvahiDaemonPid()
if pid == "" {
rsp.OkRsp(c)
return
}
command := fmt.Sprintf("kill -9 %s", pid)
err := exec.Command("sh", "-c", command).Run()
if err != nil {
log.Errorf("failed to stop avahi-daemon: %s", err)
rsp.ErrRsp(c, -1, "failed to disable mdns")
return
}
_ = os.Remove(AvahiDaemonPid)
rsp.OkRsp(c)
log.Debugf("avahi-daemon stopped")
}
func getAvahiDaemonPid() string {
if _, err := os.Stat(AvahiDaemonPid); err != nil {
return ""
}
content, err := os.ReadFile(AvahiDaemonPid)
if err != nil {
log.Errorf("failed to read mdns pid: %s", err)
return ""
}
return strings.ReplaceAll(string(content), "\n", "")
}

View File

@@ -59,7 +59,7 @@
"prettier-plugin-tailwindcss": "^0.6.9",
"tailwindcss": "^3.4.14",
"typescript": "^5.6.3",
"vite": "^5.4.14",
"vite": "^6.2.1",
"vite-tsconfig-paths": "^4.3.2"
},
"msw": {

471
web/pnpm-lock.yaml generated
View File

@@ -110,7 +110,7 @@ importers:
version: 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3)
'@vitejs/plugin-react':
specifier: ^4.3.3
version: 4.3.3(vite@5.4.14(@types/node@22.9.0))
version: 4.3.3(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0))
autoprefixer:
specifier: ^10.4.20
version: 10.4.20(postcss@8.4.47)
@@ -148,11 +148,11 @@ importers:
specifier: ^5.6.3
version: 5.6.3
vite:
specifier: ^5.4.14
version: 5.4.14(@types/node@22.9.0)
specifier: ^6.2.1
version: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0)
vite-tsconfig-paths:
specifier: ^4.3.2
version: 4.3.2(typescript@5.6.3)(vite@5.4.14(@types/node@22.9.0))
version: 4.3.2(typescript@5.6.3)(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0))
packages:
@@ -300,141 +300,153 @@ packages:
'@emotion/unitless@0.7.5':
resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==}
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
'@esbuild/aix-ppc64@0.25.0':
resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.21.5':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
'@esbuild/android-arm64@0.25.0':
resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.21.5':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
'@esbuild/android-arm@0.25.0':
resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.21.5':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
'@esbuild/android-x64@0.25.0':
resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.21.5':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
'@esbuild/darwin-arm64@0.25.0':
resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.21.5':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
'@esbuild/darwin-x64@0.25.0':
resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.21.5':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
'@esbuild/freebsd-arm64@0.25.0':
resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.21.5':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
'@esbuild/freebsd-x64@0.25.0':
resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.21.5':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
'@esbuild/linux-arm64@0.25.0':
resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.21.5':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
'@esbuild/linux-arm@0.25.0':
resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.21.5':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
'@esbuild/linux-ia32@0.25.0':
resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.21.5':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
'@esbuild/linux-loong64@0.25.0':
resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.21.5':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
'@esbuild/linux-mips64el@0.25.0':
resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.21.5':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
'@esbuild/linux-ppc64@0.25.0':
resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.21.5':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
'@esbuild/linux-riscv64@0.25.0':
resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.21.5':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
'@esbuild/linux-s390x@0.25.0':
resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.21.5':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
'@esbuild/linux-x64@0.25.0':
resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
'@esbuild/netbsd-arm64@0.25.0':
resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.25.0':
resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-x64@0.21.5':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
'@esbuild/openbsd-arm64@0.25.0':
resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.25.0':
resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.21.5':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
'@esbuild/sunos-x64@0.25.0':
resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.21.5':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
'@esbuild/win32-arm64@0.25.0':
resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.21.5':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
'@esbuild/win32-ia32@0.25.0':
resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.21.5':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
'@esbuild/win32-x64@0.25.0':
resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -793,98 +805,98 @@ packages:
resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==}
engines: {node: '>=14.0.0'}
'@rollup/rollup-android-arm-eabi@4.34.4':
resolution: {integrity: sha512-gGi5adZWvjtJU7Axs//CWaQbQd/vGy8KGcnEaCWiyCqxWYDxwIlAHFuSe6Guoxtd0SRvSfVTDMPd5H+4KE2kKA==}
'@rollup/rollup-android-arm-eabi@4.34.9':
resolution: {integrity: sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==}
cpu: [arm]
os: [android]
'@rollup/rollup-android-arm64@4.34.4':
resolution: {integrity: sha512-1aRlh1gqtF7vNPMnlf1vJKk72Yshw5zknR/ZAVh7zycRAGF2XBMVDAHmFQz/Zws5k++nux3LOq/Ejj1WrDR6xg==}
'@rollup/rollup-android-arm64@4.34.9':
resolution: {integrity: sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==}
cpu: [arm64]
os: [android]
'@rollup/rollup-darwin-arm64@4.34.4':
resolution: {integrity: sha512-drHl+4qhFj+PV/jrQ78p9ch6A0MfNVZScl/nBps5a7u01aGf/GuBRrHnRegA9bP222CBDfjYbFdjkIJ/FurvSQ==}
'@rollup/rollup-darwin-arm64@4.34.9':
resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==}
cpu: [arm64]
os: [darwin]
'@rollup/rollup-darwin-x64@4.34.4':
resolution: {integrity: sha512-hQqq/8QALU6t1+fbNmm6dwYsa0PDD4L5r3TpHx9dNl+aSEMnIksHZkSO3AVH+hBMvZhpumIGrTFj8XCOGuIXjw==}
'@rollup/rollup-darwin-x64@4.34.9':
resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==}
cpu: [x64]
os: [darwin]
'@rollup/rollup-freebsd-arm64@4.34.4':
resolution: {integrity: sha512-/L0LixBmbefkec1JTeAQJP0ETzGjFtNml2gpQXA8rpLo7Md+iXQzo9kwEgzyat5Q+OG/C//2B9Fx52UxsOXbzw==}
'@rollup/rollup-freebsd-arm64@4.34.9':
resolution: {integrity: sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==}
cpu: [arm64]
os: [freebsd]
'@rollup/rollup-freebsd-x64@4.34.4':
resolution: {integrity: sha512-6Rk3PLRK+b8L/M6m/x6Mfj60LhAUcLJ34oPaxufA+CfqkUrDoUPQYFdRrhqyOvtOKXLJZJwxlOLbQjNYQcRQfw==}
'@rollup/rollup-freebsd-x64@4.34.9':
resolution: {integrity: sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==}
cpu: [x64]
os: [freebsd]
'@rollup/rollup-linux-arm-gnueabihf@4.34.4':
resolution: {integrity: sha512-kmT3x0IPRuXY/tNoABp2nDvI9EvdiS2JZsd4I9yOcLCCViKsP0gB38mVHOhluzx+SSVnM1KNn9k6osyXZhLoCA==}
'@rollup/rollup-linux-arm-gnueabihf@4.34.9':
resolution: {integrity: sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.34.4':
resolution: {integrity: sha512-3iSA9tx+4PZcJH/Wnwsvx/BY4qHpit/u2YoZoXugWVfc36/4mRkgGEoRbRV7nzNBSCOgbWMeuQ27IQWgJ7tRzw==}
'@rollup/rollup-linux-arm-musleabihf@4.34.9':
resolution: {integrity: sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.34.4':
resolution: {integrity: sha512-7CwSJW+sEhM9sESEk+pEREF2JL0BmyCro8UyTq0Kyh0nu1v0QPNY3yfLPFKChzVoUmaKj8zbdgBxUhBRR+xGxg==}
'@rollup/rollup-linux-arm64-gnu@4.34.9':
resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-arm64-musl@4.34.4':
resolution: {integrity: sha512-GZdafB41/4s12j8Ss2izofjeFXRAAM7sHCb+S4JsI9vaONX/zQ8cXd87B9MRU/igGAJkKvmFmJJBeeT9jJ5Cbw==}
'@rollup/rollup-linux-arm64-musl@4.34.9':
resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-loongarch64-gnu@4.34.4':
resolution: {integrity: sha512-uuphLuw1X6ur11675c2twC6YxbzyLSpWggvdawTUamlsoUv81aAXRMPBC1uvQllnBGls0Qt5Siw8reSIBnbdqQ==}
'@rollup/rollup-linux-loongarch64-gnu@4.34.9':
resolution: {integrity: sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==}
cpu: [loong64]
os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.34.4':
resolution: {integrity: sha512-KvLEw1os2gSmD6k6QPCQMm2T9P2GYvsMZMRpMz78QpSoEevHbV/KOUbI/46/JRalhtSAYZBYLAnT9YE4i/l4vg==}
'@rollup/rollup-linux-powerpc64le-gnu@4.34.9':
resolution: {integrity: sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==}
cpu: [ppc64]
os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.34.4':
resolution: {integrity: sha512-wcpCLHGM9yv+3Dql/CI4zrY2mpQ4WFergD3c9cpRowltEh5I84pRT/EuHZsG0In4eBPPYthXnuR++HrFkeqwkA==}
'@rollup/rollup-linux-riscv64-gnu@4.34.9':
resolution: {integrity: sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.34.4':
resolution: {integrity: sha512-nLbfQp2lbJYU8obhRQusXKbuiqm4jSJteLwfjnunDT5ugBKdxqw1X9KWwk8xp1OMC6P5d0WbzxzhWoznuVK6XA==}
'@rollup/rollup-linux-s390x-gnu@4.34.9':
resolution: {integrity: sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==}
cpu: [s390x]
os: [linux]
'@rollup/rollup-linux-x64-gnu@4.34.4':
resolution: {integrity: sha512-JGejzEfVzqc/XNiCKZj14eb6s5w8DdWlnQ5tWUbs99kkdvfq9btxxVX97AaxiUX7xJTKFA0LwoS0KU8C2faZRg==}
'@rollup/rollup-linux-x64-gnu@4.34.9':
resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==}
cpu: [x64]
os: [linux]
'@rollup/rollup-linux-x64-musl@4.34.4':
resolution: {integrity: sha512-/iFIbhzeyZZy49ozAWJ1ZR2KW6ZdYUbQXLT4O5n1cRZRoTpwExnHLjlurDXXPKEGxiAg0ujaR9JDYKljpr2fDg==}
'@rollup/rollup-linux-x64-musl@4.34.9':
resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==}
cpu: [x64]
os: [linux]
'@rollup/rollup-win32-arm64-msvc@4.34.4':
resolution: {integrity: sha512-qORc3UzoD5UUTneiP2Afg5n5Ti1GAW9Gp5vHPxzvAFFA3FBaum9WqGvYXGf+c7beFdOKNos31/41PRMUwh1tpA==}
'@rollup/rollup-win32-arm64-msvc@4.34.9':
resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==}
cpu: [arm64]
os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.34.4':
resolution: {integrity: sha512-5g7E2PHNK2uvoD5bASBD9aelm44nf1w4I5FEI7MPHLWcCSrR8JragXZWgKPXk5i2FU3JFfa6CGZLw2RrGBHs2Q==}
'@rollup/rollup-win32-ia32-msvc@4.34.9':
resolution: {integrity: sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==}
cpu: [ia32]
os: [win32]
'@rollup/rollup-win32-x64-msvc@4.34.4':
resolution: {integrity: sha512-p0scwGkR4kZ242xLPBuhSckrJ734frz6v9xZzD+kHVYRAkSUmdSLCIJRfql6H5//aF8Q10K+i7q8DiPfZp0b7A==}
'@rollup/rollup-win32-x64-msvc@4.34.9':
resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==}
cpu: [x64]
os: [win32]
@@ -1344,9 +1356,9 @@ packages:
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
engines: {node: '>=0.12'}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
esbuild@0.25.0:
resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==}
engines: {node: '>=18'}
hasBin: true
escalade@3.2.0:
@@ -2047,6 +2059,10 @@ packages:
resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
engines: {node: ^10 || ^12 || >=14}
postcss@8.5.3:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -2508,8 +2524,8 @@ packages:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
rollup@4.34.4:
resolution: {integrity: sha512-spF66xoyD7rz3o08sHP7wogp1gZ6itSq22SGa/IZTcUDXDlOyrShwMwkVSB+BUxFRZZCUYqdb3KWDEOMVQZxuw==}
rollup@4.34.9:
resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -2788,22 +2804,27 @@ packages:
vite:
optional: true
vite@5.4.14:
resolution: {integrity: sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==}
engines: {node: ^18.0.0 || >=20.0.0}
vite@6.2.1:
resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
jiti: '>=1.21.0'
less: '*'
lightningcss: ^1.21.0
sass: '*'
sass-embedded: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
terser: ^5.16.0
tsx: ^4.8.1
yaml: ^2.4.2
peerDependenciesMeta:
'@types/node':
optional: true
jiti:
optional: true
less:
optional: true
lightningcss:
@@ -2818,6 +2839,10 @@ packages:
optional: true
terser:
optional: true
tsx:
optional: true
yaml:
optional: true
void-elements@3.1.0:
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
@@ -3086,73 +3111,79 @@ snapshots:
'@emotion/unitless@0.7.5': {}
'@esbuild/aix-ppc64@0.21.5':
'@esbuild/aix-ppc64@0.25.0':
optional: true
'@esbuild/android-arm64@0.21.5':
'@esbuild/android-arm64@0.25.0':
optional: true
'@esbuild/android-arm@0.21.5':
'@esbuild/android-arm@0.25.0':
optional: true
'@esbuild/android-x64@0.21.5':
'@esbuild/android-x64@0.25.0':
optional: true
'@esbuild/darwin-arm64@0.21.5':
'@esbuild/darwin-arm64@0.25.0':
optional: true
'@esbuild/darwin-x64@0.21.5':
'@esbuild/darwin-x64@0.25.0':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
'@esbuild/freebsd-arm64@0.25.0':
optional: true
'@esbuild/freebsd-x64@0.21.5':
'@esbuild/freebsd-x64@0.25.0':
optional: true
'@esbuild/linux-arm64@0.21.5':
'@esbuild/linux-arm64@0.25.0':
optional: true
'@esbuild/linux-arm@0.21.5':
'@esbuild/linux-arm@0.25.0':
optional: true
'@esbuild/linux-ia32@0.21.5':
'@esbuild/linux-ia32@0.25.0':
optional: true
'@esbuild/linux-loong64@0.21.5':
'@esbuild/linux-loong64@0.25.0':
optional: true
'@esbuild/linux-mips64el@0.21.5':
'@esbuild/linux-mips64el@0.25.0':
optional: true
'@esbuild/linux-ppc64@0.21.5':
'@esbuild/linux-ppc64@0.25.0':
optional: true
'@esbuild/linux-riscv64@0.21.5':
'@esbuild/linux-riscv64@0.25.0':
optional: true
'@esbuild/linux-s390x@0.21.5':
'@esbuild/linux-s390x@0.25.0':
optional: true
'@esbuild/linux-x64@0.21.5':
'@esbuild/linux-x64@0.25.0':
optional: true
'@esbuild/netbsd-x64@0.21.5':
'@esbuild/netbsd-arm64@0.25.0':
optional: true
'@esbuild/openbsd-x64@0.21.5':
'@esbuild/netbsd-x64@0.25.0':
optional: true
'@esbuild/sunos-x64@0.21.5':
'@esbuild/openbsd-arm64@0.25.0':
optional: true
'@esbuild/win32-arm64@0.21.5':
'@esbuild/openbsd-x64@0.25.0':
optional: true
'@esbuild/win32-ia32@0.21.5':
'@esbuild/sunos-x64@0.25.0':
optional: true
'@esbuild/win32-x64@0.21.5':
'@esbuild/win32-arm64@0.25.0':
optional: true
'@esbuild/win32-ia32@0.25.0':
optional: true
'@esbuild/win32-x64@0.25.0':
optional: true
'@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(jiti@1.21.6))':
@@ -3512,61 +3543,61 @@ snapshots:
'@remix-run/router@1.20.0': {}
'@rollup/rollup-android-arm-eabi@4.34.4':
'@rollup/rollup-android-arm-eabi@4.34.9':
optional: true
'@rollup/rollup-android-arm64@4.34.4':
'@rollup/rollup-android-arm64@4.34.9':
optional: true
'@rollup/rollup-darwin-arm64@4.34.4':
'@rollup/rollup-darwin-arm64@4.34.9':
optional: true
'@rollup/rollup-darwin-x64@4.34.4':
'@rollup/rollup-darwin-x64@4.34.9':
optional: true
'@rollup/rollup-freebsd-arm64@4.34.4':
'@rollup/rollup-freebsd-arm64@4.34.9':
optional: true
'@rollup/rollup-freebsd-x64@4.34.4':
'@rollup/rollup-freebsd-x64@4.34.9':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.34.4':
'@rollup/rollup-linux-arm-gnueabihf@4.34.9':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.34.4':
'@rollup/rollup-linux-arm-musleabihf@4.34.9':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.34.4':
'@rollup/rollup-linux-arm64-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-arm64-musl@4.34.4':
'@rollup/rollup-linux-arm64-musl@4.34.9':
optional: true
'@rollup/rollup-linux-loongarch64-gnu@4.34.4':
'@rollup/rollup-linux-loongarch64-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.34.4':
'@rollup/rollup-linux-powerpc64le-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.34.4':
'@rollup/rollup-linux-riscv64-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.34.4':
'@rollup/rollup-linux-s390x-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-x64-gnu@4.34.4':
'@rollup/rollup-linux-x64-gnu@4.34.9':
optional: true
'@rollup/rollup-linux-x64-musl@4.34.4':
'@rollup/rollup-linux-x64-musl@4.34.9':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.34.4':
'@rollup/rollup-win32-arm64-msvc@4.34.9':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.34.4':
'@rollup/rollup-win32-ia32-msvc@4.34.9':
optional: true
'@rollup/rollup-win32-x64-msvc@4.34.4':
'@rollup/rollup-win32-x64-msvc@4.34.9':
optional: true
'@types/babel__core@7.20.5':
@@ -3702,14 +3733,14 @@ snapshots:
'@typescript-eslint/types': 8.19.1
eslint-visitor-keys: 4.2.0
'@vitejs/plugin-react@4.3.3(vite@5.4.14(@types/node@22.9.0))':
'@vitejs/plugin-react@4.3.3(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
'@types/babel__core': 7.20.5
react-refresh: 0.14.2
vite: 5.4.14(@types/node@22.9.0)
vite: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0)
transitivePeerDependencies:
- supports-color
@@ -4194,31 +4225,33 @@ snapshots:
d: 1.0.2
ext: 1.7.0
esbuild@0.21.5:
esbuild@0.25.0:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
'@esbuild/android-arm': 0.21.5
'@esbuild/android-arm64': 0.21.5
'@esbuild/android-x64': 0.21.5
'@esbuild/darwin-arm64': 0.21.5
'@esbuild/darwin-x64': 0.21.5
'@esbuild/freebsd-arm64': 0.21.5
'@esbuild/freebsd-x64': 0.21.5
'@esbuild/linux-arm': 0.21.5
'@esbuild/linux-arm64': 0.21.5
'@esbuild/linux-ia32': 0.21.5
'@esbuild/linux-loong64': 0.21.5
'@esbuild/linux-mips64el': 0.21.5
'@esbuild/linux-ppc64': 0.21.5
'@esbuild/linux-riscv64': 0.21.5
'@esbuild/linux-s390x': 0.21.5
'@esbuild/linux-x64': 0.21.5
'@esbuild/netbsd-x64': 0.21.5
'@esbuild/openbsd-x64': 0.21.5
'@esbuild/sunos-x64': 0.21.5
'@esbuild/win32-arm64': 0.21.5
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
'@esbuild/aix-ppc64': 0.25.0
'@esbuild/android-arm': 0.25.0
'@esbuild/android-arm64': 0.25.0
'@esbuild/android-x64': 0.25.0
'@esbuild/darwin-arm64': 0.25.0
'@esbuild/darwin-x64': 0.25.0
'@esbuild/freebsd-arm64': 0.25.0
'@esbuild/freebsd-x64': 0.25.0
'@esbuild/linux-arm': 0.25.0
'@esbuild/linux-arm64': 0.25.0
'@esbuild/linux-ia32': 0.25.0
'@esbuild/linux-loong64': 0.25.0
'@esbuild/linux-mips64el': 0.25.0
'@esbuild/linux-ppc64': 0.25.0
'@esbuild/linux-riscv64': 0.25.0
'@esbuild/linux-s390x': 0.25.0
'@esbuild/linux-x64': 0.25.0
'@esbuild/netbsd-arm64': 0.25.0
'@esbuild/netbsd-x64': 0.25.0
'@esbuild/openbsd-arm64': 0.25.0
'@esbuild/openbsd-x64': 0.25.0
'@esbuild/sunos-x64': 0.25.0
'@esbuild/win32-arm64': 0.25.0
'@esbuild/win32-ia32': 0.25.0
'@esbuild/win32-x64': 0.25.0
escalade@3.2.0: {}
@@ -4906,6 +4939,12 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
postcss@8.5.3:
dependencies:
nanoid: 3.3.8
picocolors: 1.1.1
source-map-js: 1.2.1
prelude-ls@1.2.1: {}
prettier-plugin-tailwindcss@0.6.9(@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.4.2))(prettier@3.4.2):
@@ -5399,29 +5438,29 @@ snapshots:
reusify@1.0.4: {}
rollup@4.34.4:
rollup@4.34.9:
dependencies:
'@types/estree': 1.0.6
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.34.4
'@rollup/rollup-android-arm64': 4.34.4
'@rollup/rollup-darwin-arm64': 4.34.4
'@rollup/rollup-darwin-x64': 4.34.4
'@rollup/rollup-freebsd-arm64': 4.34.4
'@rollup/rollup-freebsd-x64': 4.34.4
'@rollup/rollup-linux-arm-gnueabihf': 4.34.4
'@rollup/rollup-linux-arm-musleabihf': 4.34.4
'@rollup/rollup-linux-arm64-gnu': 4.34.4
'@rollup/rollup-linux-arm64-musl': 4.34.4
'@rollup/rollup-linux-loongarch64-gnu': 4.34.4
'@rollup/rollup-linux-powerpc64le-gnu': 4.34.4
'@rollup/rollup-linux-riscv64-gnu': 4.34.4
'@rollup/rollup-linux-s390x-gnu': 4.34.4
'@rollup/rollup-linux-x64-gnu': 4.34.4
'@rollup/rollup-linux-x64-musl': 4.34.4
'@rollup/rollup-win32-arm64-msvc': 4.34.4
'@rollup/rollup-win32-ia32-msvc': 4.34.4
'@rollup/rollup-win32-x64-msvc': 4.34.4
'@rollup/rollup-android-arm-eabi': 4.34.9
'@rollup/rollup-android-arm64': 4.34.9
'@rollup/rollup-darwin-arm64': 4.34.9
'@rollup/rollup-darwin-x64': 4.34.9
'@rollup/rollup-freebsd-arm64': 4.34.9
'@rollup/rollup-freebsd-x64': 4.34.9
'@rollup/rollup-linux-arm-gnueabihf': 4.34.9
'@rollup/rollup-linux-arm-musleabihf': 4.34.9
'@rollup/rollup-linux-arm64-gnu': 4.34.9
'@rollup/rollup-linux-arm64-musl': 4.34.9
'@rollup/rollup-linux-loongarch64-gnu': 4.34.9
'@rollup/rollup-linux-powerpc64le-gnu': 4.34.9
'@rollup/rollup-linux-riscv64-gnu': 4.34.9
'@rollup/rollup-linux-s390x-gnu': 4.34.9
'@rollup/rollup-linux-x64-gnu': 4.34.9
'@rollup/rollup-linux-x64-musl': 4.34.9
'@rollup/rollup-win32-arm64-msvc': 4.34.9
'@rollup/rollup-win32-ia32-msvc': 4.34.9
'@rollup/rollup-win32-x64-msvc': 4.34.9
fsevents: 2.3.3
run-parallel@1.2.0:
@@ -5741,25 +5780,27 @@ snapshots:
- '@types/react'
- '@types/react-dom'
vite-tsconfig-paths@4.3.2(typescript@5.6.3)(vite@5.4.14(@types/node@22.9.0)):
vite-tsconfig-paths@4.3.2(typescript@5.6.3)(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0)):
dependencies:
debug: 4.3.7
globrex: 0.1.2
tsconfck: 3.1.4(typescript@5.6.3)
optionalDependencies:
vite: 5.4.14(@types/node@22.9.0)
vite: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0)
transitivePeerDependencies:
- supports-color
- typescript
vite@5.4.14(@types/node@22.9.0):
vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0):
dependencies:
esbuild: 0.21.5
postcss: 8.4.47
rollup: 4.34.4
esbuild: 0.25.0
postcss: 8.5.3
rollup: 4.34.9
optionalDependencies:
'@types/node': 22.9.0
fsevents: 2.3.3
jiti: 1.21.6
yaml: 2.6.0
void-elements@3.1.0: {}

View File

@@ -76,3 +76,18 @@ export function enableSSH() {
export function disableSSH() {
return http.post('/api/vm/ssh/disable');
}
// get mDNS state
export function getMdnsState() {
return http.get('/api/vm/mdns');
}
// enable mDNS
export function enableMdns() {
return http.post('/api/vm/mdns/enable');
}
// disable mDNS
export function disableMdns() {
return http.post('/api/vm/mdns/disable');
}

View File

@@ -1,15 +1,15 @@
import { Button } from 'antd';
import { t } from 'i18next';
import { useTranslation } from 'react-i18next';
export const MainError = () => {
const { t } = useTranslation();
return (
<div
className="flex h-screen w-screen flex-col items-center justify-center space-y-5"
role="alert"
>
<h2 className="text-lg font-semibold text-red-500">
{t('error.title')}
</h2>
<h2 className="text-lg font-semibold text-red-500">{t('error.title')}</h2>
<Button type="primary" danger onClick={() => window.location.assign(window.location.origin)}>
{t('error.refresh')}
</Button>

View File

@@ -200,6 +200,10 @@ const en = {
description: 'Enable SSH remote access',
tip: 'Set a strong password before enabling (Account - Change Password)'
},
mdns: {
description: 'Enable mDNS discovery service',
tip: "Turning it off if it's not needed"
},
disk: 'Virtual Disk',
diskDesc: 'Mount virtual U-disk on the remote host',
network: 'Virtual Network',
@@ -209,7 +213,7 @@ const en = {
title: 'Tailscale',
memory: {
title: 'Memory optimization',
tip: "When memory usage exceeds the limit, garbage collection is performed more aggressively to attempt to free up memory. It's recommended to set to 50MB if using Tailscale. A Tailscale restart is required for the change to take effect.",
tip: "When memory usage exceeds the limit, garbage collection is performed more aggressively to attempt to free up memory. It's recommended to set to 75MB if using Tailscale. A Tailscale restart is required for the change to take effect.",
disable: 'Disable'
},
restart: 'Restart Tailscale?',
@@ -261,15 +265,15 @@ const en = {
}
},
error: {
title: 'We\'ve ran into an issue',
refresh: 'Refresh',
title: "We've ran into an issue",
refresh: 'Refresh'
},
fullscreen: {
toggle: 'Toggle Fullscreen',
toggle: 'Toggle Fullscreen'
},
menu: {
collapse: 'Collapse Menu',
expand: 'Expand Menu',
expand: 'Expand Menu'
}
}
};

View File

@@ -193,6 +193,10 @@ const zh = {
description: '启用 SSH 远程访问',
tip: '启用前请务必设置强密码(帐号 - 修改密码)'
},
mdns: {
description: '启用 mDNS 发现服务',
tip: '如果您未使用此功能,建议将其关闭'
},
disk: '虚拟U盘',
diskDesc: '在远程主机中挂载虚拟U盘',
network: '虚拟网卡',

View File

@@ -39,10 +39,12 @@ export const Information = () => {
<span>{information ? information.ip : '-'}</span>
</div>
<div className="flex w-full items-center justify-between">
<span>{t('settings.about.mdns')}</span>
<span>{information ? information.mdns : '-'}</span>
</div>
{!!information?.mdns && (
<div className="flex w-full items-center justify-between">
<span>{t('settings.about.mdns')}</span>
<span>{information.mdns}</span>
</div>
)}
<div className="flex w-full items-center justify-between">
<div className="flex items-center space-x-2">

View File

@@ -1,6 +1,7 @@
import { Divider } from 'antd';
import { useTranslation } from 'react-i18next';
import { Mdns } from './mdns.tsx';
import { Oled } from './oled.tsx';
import { Ssh } from './ssh.tsx';
import { VirtualDevices } from './virtual-devices.tsx';
@@ -18,6 +19,7 @@ export const Device = () => {
<Oled />
<Wifi />
<Ssh />
<Mdns />
<VirtualDevices />
</div>
</>

View File

@@ -0,0 +1,64 @@
import { useEffect, useState } from 'react';
import { Switch, Tooltip } from 'antd';
import { CircleAlertIcon } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import * as api from '@/api/vm.ts';
export const Mdns = () => {
const { t } = useTranslation();
const [isEnabled, setIsEnabled] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
api
.getMdnsState()
.then((rsp) => {
if (rsp.data?.enabled) {
setIsEnabled(true);
}
})
.finally(() => {
setIsLoading(false);
});
}, []);
async function update() {
if (isLoading) return;
setIsLoading(true);
const rsp = isEnabled ? await api.disableMdns() : await api.enableMdns();
setIsLoading(false);
if (rsp.code !== 0) {
console.log(rsp.msg);
return;
}
setIsEnabled(!isEnabled);
}
return (
<div className="flex items-center justify-between">
<div className="flex flex-col">
<span>mDNS</span>
<div className="flex items-center space-x-1">
<span className="text-xs text-neutral-500">{t('settings.device.mdns.description')}</span>
<Tooltip
title={t('settings.device.mdns.tip')}
className="cursor-pointer text-neutral-500"
placement="bottom"
>
<CircleAlertIcon size={16} />
</Tooltip>
</div>
</div>
<Switch checked={isEnabled} loading={isLoading} onChange={update} />
</div>
);
};

View File

@@ -115,16 +115,18 @@ export const Update = ({ setIsLocked }: UpdateProps) => {
{status === 'failed' && <Result subTitle={errMsg} />}
<div className="flex justify-center">
<Button
type="link"
size="small"
href="https://github.com/sipeed/NanoKVM/blob/main/CHANGELOG.md"
target="_blank"
>
CHANGELOG
</Button>
</div>
{status !== 'loading' && (
<div className="flex justify-center">
<Button
type="link"
size="small"
href="https://github.com/sipeed/NanoKVM/blob/main/CHANGELOG.md"
target="_blank"
>
CHANGELOG
</Button>
</div>
)}
</>
);
};

View File

@@ -18,10 +18,13 @@ export const H264 = () => {
let heartbeatTimer: any;
const videoElement = document.getElementById('screen') as HTMLVideoElement;
const url = `${getBaseUrl('ws')}/api/stream/h264`;
const ws = new W3cWebSocket(url);
const pc = new RTCPeerConnection({
iceServers: [
{
urls: ['stun:stun.l.google.com:19302', 'stun:turn.cloudflare.com:3478']
urls: ['stun:stun.l.google.com:19302']
}
]
});
@@ -34,9 +37,6 @@ export const H264 = () => {
videoElement.srcObject = event.streams[0];
};
const url = `${getBaseUrl('ws')}/api/stream/h264`;
const ws = new W3cWebSocket(url);
ws.onopen = () => {
pc.onicecandidate = (event) => {
if (event.candidate) {