From 0e30a26db42cbc08416662b49a88a5d16ad93424 Mon Sep 17 00:00:00 2001 From: wj-xiao Date: Wed, 26 Nov 2025 10:57:30 +0800 Subject: [PATCH] Streaming Refactor: - H.264 WebRTC: Refactored to significantly reduce video latency - H.264 Direct: Optimized data transmission; data parsing now continues correctly even when the tab is in the background - MJPEG: Refactored to ensure the correct data length is sent Bug Fixes - Fixed an issue where certain keyboard modifier keys were not recognized - Fixed vertical mouse cursor drift when the page is zoomed in or out Optimizations - Optimized HID write logic and updated the HID reset mechanism - Added support for deleting images - Added a Swap Memory option to the Tailscale page - Added a confirmation dialog when uninstalling Tailscale to prevent accidental removal - Improved the logic for updating the web page title - Improved the UI for the Clipboard, Settings, Image Mounting, and App Update pages Security - Added a mandatory delay after failed login attempts to prevent brute-force attacks - Updated dependencies to patch known security vulnerabilities --- server/build.sh | 64 + server/common/{cgo.go => kvm_vision.go} | 17 +- server/config/hardware.go | 22 +- server/go.mod | 22 +- server/go.sum | 53 +- server/proto/storage.go | 4 + server/router/application.go | 4 - server/router/hid.go | 2 +- server/router/storage.go | 1 + server/router/stream.go | 4 +- server/service/application/settings.go | 63 - server/service/application/update.go | 21 + server/service/auth/login.go | 4 + server/service/extensions/tailscale/cli.go | 2 - .../service/extensions/tailscale/service.go | 4 +- server/service/hid/hid.go | 143 +- server/service/hid/keyboard.go | 24 +- server/service/hid/mouse.go | 43 +- server/service/hid/operation.go | 73 - server/service/hid/paste.go | 98 +- server/service/hid/reset.go | 82 - server/service/hid/{mode.go => status.go} | 51 +- server/service/storage/image.go | 28 + server/service/stream/direct/h264.go | 85 +- server/service/stream/direct/pool.go | 12 + server/service/stream/direct/streamer.go | 123 ++ .../stream/{frame-rate.go => frame_rate.go} | 0 server/service/stream/h264/sender.go | 4 +- server/service/stream/mjpeg/mjpeg.go | 85 +- server/service/stream/mjpeg/streamer.go | 131 ++ server/service/stream/webrtc/client.go | 112 + server/service/stream/webrtc/h264.go | 158 ++ server/service/stream/webrtc/manager.go | 96 + server/service/stream/webrtc/signaling.go | 149 ++ server/service/stream/webrtc/track.go | 53 + server/service/stream/webrtc/types.go | 38 + server/service/vm/jiggler/jiggler.go | 15 + server/service/vm/jiggler/mouse.go | 55 - .../vm/{mouse-jiggler.go => mouse_jiggler.go} | 0 .../service/vm/{web-title.go => web_title.go} | 0 server/utils/{move-file.go => move_file.go} | 0 web/package.json | 20 +- web/pnpm-lock.yaml | 1851 ++++++++++------- web/src/api/application.ts | 7 - web/src/api/storage.ts | 7 + web/src/i18n/locales/en.ts | 31 +- web/src/i18n/locales/zh.ts | 19 +- web/src/jotai/settings.ts | 2 - web/src/pages/desktop/keyboard/index.tsx | 99 +- web/src/pages/desktop/menu/image/images.tsx | 168 +- web/src/pages/desktop/menu/image/index.tsx | 99 +- web/src/pages/desktop/menu/image/tips.tsx | 5 +- web/src/pages/desktop/menu/index.tsx | 9 +- web/src/pages/desktop/menu/keyboard/paste.tsx | 141 +- web/src/pages/desktop/menu/screen/index.tsx | 11 +- .../desktop/menu/settings/about/community.tsx | 2 +- .../desktop/menu/settings/about/hostname.tsx | 11 +- .../menu/settings/about/information.tsx | 20 +- .../menu/settings/appearance/web-title.tsx | 30 +- .../menu/settings/device/advanced/index.tsx | 3 +- .../menu/settings/device/advanced/swap.tsx | 8 +- .../desktop/menu/settings/device/index.tsx | 22 +- web/src/pages/desktop/menu/settings/index.tsx | 30 +- .../menu/settings/tailscale/header.tsx | 2 + .../desktop/menu/settings/tailscale/index.tsx | 7 +- .../menu/settings/tailscale/install.tsx | 92 +- .../menu/settings/tailscale/memory.tsx | 32 +- .../desktop/menu/settings/tailscale/run.tsx | 54 + .../desktop/menu/settings/tailscale/swap.tsx | 71 + .../menu/settings/tailscale/uninstall.tsx | 63 +- .../desktop/menu/settings/update/index.tsx | 85 +- web/src/pages/desktop/mouse/absolute.tsx | 80 +- web/src/pages/desktop/screen/direct.worker.ts | 147 ++ web/src/pages/desktop/screen/h264-direct.tsx | 144 +- web/src/pages/desktop/screen/h264-webrtc.tsx | 150 +- web/tsconfig.json | 2 +- 76 files changed, 3401 insertions(+), 2068 deletions(-) create mode 100755 server/build.sh rename server/common/{cgo.go => kvm_vision.go} (86%) delete mode 100644 server/service/application/settings.go delete mode 100644 server/service/hid/operation.go delete mode 100644 server/service/hid/reset.go rename server/service/hid/{mode.go => status.go} (74%) create mode 100644 server/service/stream/direct/pool.go create mode 100644 server/service/stream/direct/streamer.go rename server/service/stream/{frame-rate.go => frame_rate.go} (100%) create mode 100644 server/service/stream/mjpeg/streamer.go create mode 100644 server/service/stream/webrtc/client.go create mode 100644 server/service/stream/webrtc/h264.go create mode 100644 server/service/stream/webrtc/manager.go create mode 100644 server/service/stream/webrtc/signaling.go create mode 100644 server/service/stream/webrtc/track.go create mode 100644 server/service/stream/webrtc/types.go delete mode 100644 server/service/vm/jiggler/mouse.go rename server/service/vm/{mouse-jiggler.go => mouse_jiggler.go} (100%) rename server/service/vm/{web-title.go => web_title.go} (100%) rename server/utils/{move-file.go => move_file.go} (100%) create mode 100644 web/src/pages/desktop/menu/settings/tailscale/run.tsx create mode 100644 web/src/pages/desktop/menu/settings/tailscale/swap.tsx create mode 100644 web/src/pages/desktop/screen/direct.worker.ts diff --git a/server/build.sh b/server/build.sh new file mode 100755 index 0000000..b0f143e --- /dev/null +++ b/server/build.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +set -e + +# Configuration Variables +BINARY_NAME="NanoKVM-Server" +CC_COMPILER="riscv64-unknown-linux-musl-gcc" +CGO_CFLAGS_OPTS="-mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d" + +# Define colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Helper function to check if a command exists +check_dependency() { + if ! command -v "$1" &> /dev/null; then + echo -e "${RED}[ERROR] Required command '$1' not found.${NC}" + echo "Please install it or ensure it is in your PATH." + exit 1 + fi +} + +# ------------------------------------------------------------------------------ +# Step 1: Check Prerequisites +# ------------------------------------------------------------------------------ +echo -e "${YELLOW}[INFO] Checking build environment...${NC}" + +check_dependency "go" +check_dependency "patchelf" +check_dependency "$CC_COMPILER" + +echo -e "${GREEN}[OK] All dependencies found.${NC}" + +# ------------------------------------------------------------------------------ +# Step 2: Build the Binary +# ------------------------------------------------------------------------------ +echo -e "${YELLOW}[INFO] Starting cross-compilation for RISC-V 64-bit (BoringCrypto enabled)...${NC}" + +export CGO_ENABLED=1 +export GOOS=linux +export GOARCH=riscv64 +export GOEXPERIMENT=boringcrypto +export CC="$CC_COMPILER" +export CGO_CFLAGS="$CGO_CFLAGS_OPTS" + +go build -o "$BINARY_NAME" -v + +if [ -f "$BINARY_NAME" ]; then + echo -e "${GREEN}[SUCCESS] Binary '$BINARY_NAME' created successfully.${NC}" +else + echo -e "${RED}[ERROR] Build failed. Binary not found.${NC}" + exit 1 +fi + +# ------------------------------------------------------------------------------ +# Step 3: Patch RPATH +# ------------------------------------------------------------------------------ +echo -e "${YELLOW}[INFO] Patching RPATH with patchelf...${NC}" + +patchelf --add-rpath '$ORIGIN/dl_lib' "$BINARY_NAME" + +echo -e "${GREEN}[DONE] Build script completed successfully!${NC}" diff --git a/server/common/cgo.go b/server/common/kvm_vision.go similarity index 86% rename from server/common/cgo.go rename to server/common/kvm_vision.go index 0a040fd..99d3a95 100644 --- a/server/common/cgo.go +++ b/server/common/kvm_vision.go @@ -7,8 +7,6 @@ package common */ import "C" import ( - "NanoKVM-Server/config" - "strings" "sync" "unsafe" @@ -26,15 +24,8 @@ func GetKvmVision() *KvmVision { kvmVisionOnce.Do(func() { kvmVision = &KvmVision{} - conf := config.GetInstance() - logLevel := strings.ToLower(conf.Logger.Level) - - logEnable := C.uint8_t(0) - if logLevel == "debug" { - logEnable = C.uint8_t(1) - } - - C.kvmv_init(logEnable) + logLevel := C.uint8_t(0) + C.kvmv_init(logLevel) log.Debugf("kvm vision initialized") }) @@ -62,8 +53,6 @@ func (k *KvmVision) ReadMjpeg(width uint16, height uint16, quality uint16) (data defer C.free_kvmv_data(&kvmData) data = C.GoBytes(unsafe.Pointer(kvmData), C.int(dataSize)) - - log.Debugf("read kvm image: %v", result) return } @@ -88,8 +77,6 @@ func (k *KvmVision) ReadH264(width uint16, height uint16, bitRate uint16) (data defer C.free_kvmv_data(&kvmData) data = C.GoBytes(unsafe.Pointer(kvmData), C.int(dataSize)) - - log.Debugf("read kvm image: %v", result) return } diff --git a/server/config/hardware.go b/server/config/hardware.go index 1913707..bea3872 100644 --- a/server/config/hardware.go +++ b/server/config/hardware.go @@ -11,10 +11,8 @@ type HWVersion int const ( HWVersionAlpha HWVersion = iota - HWVersionPro HWVersionBeta HWVersionPcie - HWVersionATX HWVersionFile = "/etc/kvm/hw" ) @@ -43,14 +41,6 @@ var HWPcie = Hardware{ GPIOHDDLed: "", } -var HWPro = Hardware{ - Version: HWVersionPro, - GPIOReset: "/sys/class/gpio/gpio35/value", - GPIOPower: "/sys/class/gpio/gpio7/value", - GPIOPowerLED: "/sys/class/gpio/gpio75/value", - GPIOHDDLed: "/sys/class/gpio/gpio74/value", -} - func (h HWVersion) String() string { switch h { case HWVersionAlpha: @@ -59,8 +49,6 @@ func (h HWVersion) String() string { return "Beta" case HWVersionPcie: return "PCIE" - case HWVersionPro: - return "Pro" default: return "Unknown" } @@ -80,10 +68,6 @@ func GetHwVersion() HWVersion { return HWVersionBeta case "pcie": return HWVersionPcie - case "atx": - return HWVersionATX - case "pro": - return HWVersionPro default: return HWVersionAlpha } @@ -102,12 +86,10 @@ func getHardware() (h Hardware) { case HWVersionPcie: h = HWPcie - case HWVersionPro: - h = HWPro - default: h = HWAlpha log.Errorf("Unsupported hardware version: %s", version) } - return h + + return } diff --git a/server/go.mod b/server/go.mod index a356ee1..eff0892 100644 --- a/server/go.mod +++ b/server/go.mod @@ -1,8 +1,6 @@ module NanoKVM-Server -go 1.23.0 - -toolchain go1.23.2 +go 1.24.0 require ( github.com/creack/pty v1.1.24 @@ -12,12 +10,14 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.2 github.com/gorilla/websocket v1.5.3 github.com/mervick/aes-everywhere/go/aes256 v0.0.0-20240803013625-6759956693c0 + github.com/pion/dtls/v3 v3.0.3 + github.com/pion/rtp v1.8.18 github.com/pion/webrtc/v4 v4.0.1 github.com/rs/cors/wrapper/gin v0.0.0-20240830163046-1084d89a1692 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.19.0 github.com/unrolled/secure v1.15.0 - golang.org/x/crypto v0.37.0 + golang.org/x/crypto v0.45.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -44,14 +44,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pion/datachannel v1.5.9 // indirect - github.com/pion/dtls/v3 v3.0.3 // indirect github.com/pion/ice/v4 v4.0.2 // indirect - github.com/pion/interceptor v0.1.37 // indirect - github.com/pion/logging v0.2.2 // indirect + github.com/pion/interceptor v0.1.39 // indirect + github.com/pion/logging v0.2.3 // indirect github.com/pion/mdns/v2 v2.0.7 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.14 // indirect - github.com/pion/rtp v1.8.9 // indirect + github.com/pion/rtcp v1.2.15 // indirect github.com/pion/sctp v1.8.33 // indirect github.com/pion/sdp/v3 v3.0.9 // indirect github.com/pion/srtp/v3 v3.0.4 // indirect @@ -73,9 +71,9 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/server/go.sum b/server/go.sum index 717f849..2ada1f1 100644 --- a/server/go.sum +++ b/server/go.sum @@ -34,8 +34,6 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= @@ -80,18 +78,18 @@ github.com/pion/dtls/v3 v3.0.3 h1:j5ajZbQwff7Z8k3pE3S+rQ4STvKvXUdKsi/07ka+OWM= github.com/pion/dtls/v3 v3.0.3/go.mod h1:weOTUyIV4z0bQaVzKe8kpaP17+us3yAuiQsEAG1STMU= github.com/pion/ice/v4 v4.0.2 h1:1JhBRX8iQLi0+TfcavTjPjI6GO41MFn4CeTBX+Y9h5s= github.com/pion/ice/v4 v4.0.2/go.mod h1:DCdqyzgtsDNYN6/3U8044j3U7qsJ9KFJC92VnOWHvXg= -github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI= -github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/interceptor v0.1.39 h1:Y6k0bN9Y3Lg/Wb21JBWp480tohtns8ybJ037AGr9UuA= +github.com/pion/interceptor v0.1.39/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= +github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= +github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= -github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= -github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= -github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.18 h1:yEAb4+4a8nkPCecWzQB6V/uEU18X1lQCGAQCjP+pyvU= +github.com/pion/rtp v1.8.18/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw= github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= @@ -141,8 +139,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -160,35 +159,19 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/server/proto/storage.go b/server/proto/storage.go index 33c25cf..8741da3 100644 --- a/server/proto/storage.go +++ b/server/proto/storage.go @@ -16,3 +16,7 @@ type GetMountedImageRsp struct { type GetCdRomRsp struct { Cdrom int64 `json:"cdrom"` } + +type DeleteImageReq struct { + File string `json:"file" validate:"required"` +} diff --git a/server/router/application.go b/server/router/application.go index 351e0ce..1c4d269 100644 --- a/server/router/application.go +++ b/server/router/application.go @@ -16,8 +16,4 @@ func applicationRouter(r *gin.Engine) { api.GET("/application/preview", service.GetPreview) // get preview updates state api.POST("/application/preview", service.SetPreview) // set preview updates state - - api.GET("/application/settings/disabled-items", service.GetDisableItems) // get disable items list - api.GET("/application/menu/disabled-items", service.GetDisableMenus) - } diff --git a/server/router/hid.go b/server/router/hid.go index bba4a08..edfd358 100644 --- a/server/router/hid.go +++ b/server/router/hid.go @@ -11,9 +11,9 @@ func hidRouter(r *gin.Engine) { service := hid.NewService() api := r.Group("/api").Use(middleware.CheckToken()) - api.POST("/hid/reset", service.Reset) // reset hid api.POST("/hid/paste", service.Paste) // paste api.GET("/hid/mode", service.GetHidMode) // get hid mode api.POST("/hid/mode", service.SetHidMode) // set hid mode + api.POST("/hid/reset", service.ResetHid) // reset hid } diff --git a/server/router/storage.go b/server/router/storage.go index d29a327..008f354 100644 --- a/server/router/storage.go +++ b/server/router/storage.go @@ -15,4 +15,5 @@ func storageRouter(r *gin.Engine) { api.GET("/storage/image/mounted", service.GetMountedImage) // get mounted image api.POST("/storage/image/mount", service.MountImage) // mount image api.GET("/storage/cdrom", service.GetCdRom) // get CD-ROM flag + api.POST("/storage/image/delete", service.DeleteImage) // delete image } diff --git a/server/router/stream.go b/server/router/stream.go index b4eb7a6..44fb5a8 100644 --- a/server/router/stream.go +++ b/server/router/stream.go @@ -3,8 +3,8 @@ package router import ( "NanoKVM-Server/middleware" "NanoKVM-Server/service/stream/direct" - "NanoKVM-Server/service/stream/h264" "NanoKVM-Server/service/stream/mjpeg" + "NanoKVM-Server/service/stream/webrtc" "github.com/gin-gonic/gin" ) @@ -16,6 +16,6 @@ func streamRouter(r *gin.Engine) { api.POST("/stream/mjpeg/detect", mjpeg.UpdateFrameDetect) // update frame detect api.POST("/stream/mjpeg/detect/stop", mjpeg.StopFrameDetect) // temporary stop frame detect - api.GET("/stream/h264", h264.Connect) // h264 stream (webrtc) + api.GET("/stream/h264", webrtc.Connect) // h264 stream (webrtc) api.GET("/stream/h264/direct", direct.Connect) // h264 stream (http) } diff --git a/server/service/application/settings.go b/server/service/application/settings.go deleted file mode 100644 index 9b8ef48..0000000 --- a/server/service/application/settings.go +++ /dev/null @@ -1,63 +0,0 @@ -package application - -import ( - "NanoKVM-Server/config" - "NanoKVM-Server/proto" - - "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" -) - -const ( - DeviceTLS = "device:tls" - DeviceSSH = "device:ssh" - DeviceMDNS = "device:mdns" - DeviceHDMI = "device:hdmi" - DeviceWIFI = "device:wifi" - DeviceMouse = "device:mouse" - DeviceReboot = "device:reboot" - DeviceOLED = "device:oled" - DeviceAdvance = "device:advance" - DeviceAdvancedSwap = "device:advance:swap" -) - -const ( - MenuScript = "script" - MenuImage = "image" - MenuDownload = "download" - MenuTerminal = "terminal" - MenuScreen = "screen" - MenuScreenResolution = "screen:resolution" -) - -func (s *Service) GetDisableItems(ctx *gin.Context) { - var rsp proto.Response - switch config.GetHwVersion() { - case config.HWVersionPcie, config.HWVersionATX: - rsp.OkRspWithData(ctx, []string{ - DeviceAdvancedSwap, - DeviceAdvance, - MenuScreenResolution, - }) - log.Debugf("disable menus items %s", DeviceAdvancedSwap) - return - default: - rsp.OkRspWithData(ctx, []string{}) - } -} - -func (s *Service) GetDisableMenus(ctx *gin.Context) { - var rsp proto.Response - switch config.GetHwVersion() { - case config.HWVersionPcie, config.HWVersionATX: - rsp.OkRspWithData(ctx, []string{ - DeviceAdvancedSwap, - DeviceAdvance, - MenuScreenResolution, - }) - log.Debugf("disable menus items %s", DeviceAdvancedSwap) - return - default: - rsp.OkRspWithData(ctx, []string{}) - } -} diff --git a/server/service/application/update.go b/server/service/application/update.go index e40533c..9993397 100644 --- a/server/service/application/update.go +++ b/server/service/application/update.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "os/exec" + "sync" "time" "github.com/gin-gonic/gin" @@ -21,9 +22,29 @@ const ( maxTries = 3 ) +var ( + updateMutex sync.Mutex + isUpdating bool +) + func (s *Service) Update(c *gin.Context) { var rsp proto.Response + updateMutex.Lock() + if isUpdating { + updateMutex.Unlock() + rsp.ErrRsp(c, -1, "update already in progress") + return + } + isUpdating = true + updateMutex.Unlock() + + defer func() { + updateMutex.Lock() + isUpdating = false + updateMutex.Unlock() + }() + if err := update(); err != nil { rsp.ErrRsp(c, -1, fmt.Sprintf("update failed: %s", err)) return diff --git a/server/service/auth/login.go b/server/service/auth/login.go index 8e9ba28..c933ec1 100644 --- a/server/service/auth/login.go +++ b/server/service/auth/login.go @@ -4,6 +4,7 @@ import ( "NanoKVM-Server/config" "NanoKVM-Server/middleware" "NanoKVM-Server/proto" + "time" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -23,17 +24,20 @@ func (s *Service) Login(c *gin.Context) { } if err := proto.ParseFormRequest(c, &req); err != nil { + time.Sleep(3 * time.Second) rsp.ErrRsp(c, -1, "invalid parameters") return } if ok := CompareAccount(req.Username, req.Password); !ok { + time.Sleep(2 * time.Second) rsp.ErrRsp(c, -2, "invalid username or password") return } token, err := middleware.GenerateJWT(req.Username) if err != nil { + time.Sleep(1 * time.Second) rsp.ErrRsp(c, -3, "generate token failed") return } diff --git a/server/service/extensions/tailscale/cli.go b/server/service/extensions/tailscale/cli.go index 1fa4cc9..300c2b1 100644 --- a/server/service/extensions/tailscale/cli.go +++ b/server/service/extensions/tailscale/cli.go @@ -69,8 +69,6 @@ func (c *Cli) Stop() error { return err } - _ = os.Remove(ConfigPath) - return os.Remove(ScriptPath) } diff --git a/server/service/extensions/tailscale/service.go b/server/service/extensions/tailscale/service.go index eac2ff3..8075bbd 100644 --- a/server/service/extensions/tailscale/service.go +++ b/server/service/extensions/tailscale/service.go @@ -15,7 +15,6 @@ type Service struct{} const ( TailscalePath = "/usr/bin/tailscale" TailscaledPath = "/usr/sbin/tailscaled" - ConfigPath = "etc/sysctl.d/99-tailscale.conf" GoMemLimit int64 = 75 ) @@ -40,6 +39,8 @@ func (s *Service) Install(c *gin.Context) { rsp.ErrRsp(c, -1, "install failed") return } + + _ = NewCli().Start() } rsp.OkRsp(c) @@ -54,7 +55,6 @@ func (s *Service) Uninstall(c *gin.Context) { _ = os.Remove(TailscalePath) _ = os.Remove(TailscaledPath) - _ = os.Remove(ConfigPath) rsp.OkRsp(c) log.Debugf("uninstall tailscale successfully") diff --git a/server/service/hid/hid.go b/server/service/hid/hid.go index a580101..85e86b4 100644 --- a/server/service/hid/hid.go +++ b/server/service/hid/hid.go @@ -1,13 +1,12 @@ package hid import ( + "errors" "os" "sync" -) + "time" -var ( - hid *Hid - hidOnce sync.Once + log "github.com/sirupsen/logrus" ) type Hid struct { @@ -18,6 +17,24 @@ type Hid struct { mouseMutex sync.Mutex } +const ( + HID0 = "/dev/hidg0" + HID1 = "/dev/hidg1" + HID2 = "/dev/hidg2" +) + +var ( + hid *Hid + hidOnce sync.Once +) + +func GetHid() *Hid { + hidOnce.Do(func() { + hid = &Hid{} + }) + return hid +} + func (h *Hid) Lock() { h.kbMutex.Lock() h.mouseMutex.Lock() @@ -28,9 +45,117 @@ func (h *Hid) Unlock() { h.mouseMutex.Unlock() } -func GetHid() *Hid { - hidOnce.Do(func() { - hid = &Hid{} - }) - return hid +func (h *Hid) OpenNoLock() { + var err error + h.CloseNoLock() + + h.g0, err = os.OpenFile(HID0, os.O_WRONLY, 0o666) + if err != nil { + log.Errorf("open %s failed: %s", HID0, err) + } + + h.g1, err = os.OpenFile(HID1, os.O_WRONLY, 0o666) + if err != nil { + log.Errorf("open %s failed: %s", HID1, err) + } + + h.g2, err = os.OpenFile(HID2, os.O_WRONLY, 0o666) + if err != nil { + log.Errorf("open %s failed: %s", HID2, err) + } +} + +func (h *Hid) CloseNoLock() { + for _, file := range []*os.File{h.g0, h.g1, h.g2} { + if file != nil { + _ = file.Sync() + _ = file.Close() + } + } +} + +func (h *Hid) Open() { + h.kbMutex.Lock() + defer h.kbMutex.Unlock() + h.mouseMutex.Lock() + defer h.mouseMutex.Unlock() + + h.CloseNoLock() + + h.OpenNoLock() +} + +func (h *Hid) Close() { + h.kbMutex.Lock() + defer h.kbMutex.Unlock() + h.mouseMutex.Lock() + defer h.mouseMutex.Unlock() + + h.CloseNoLock() +} + +func (h *Hid) WriteHid0(data []byte) { + h.kbMutex.Lock() + _, err := h.g0.Write(data) + h.kbMutex.Unlock() + + if err != nil { + if errors.Is(err, os.ErrClosed) { + log.Errorf("hid already closed, reopen it...") + h.OpenNoLock() + } else { + log.Debugf("write to %s failed: %s", HID0, err) + } + return + } + + log.Debugf("write to %s: %v", HID0, data) +} + +func (h *Hid) WriteHid1(data []byte) { + deadline := time.Now().Add(8 * time.Millisecond) + + h.mouseMutex.Lock() + _ = h.g1.SetWriteDeadline(deadline) + _, err := h.g1.Write(data) + h.mouseMutex.Unlock() + + if err != nil { + switch { + case errors.Is(err, os.ErrClosed): + log.Errorf("hid already closed, reopen it...") + h.OpenNoLock() + case errors.Is(err, os.ErrDeadlineExceeded): + log.Debugf("write to %s timeout", HID1) + default: + log.Errorf("write to %s failed: %s", HID1, err) + } + return + } + + log.Debugf("write to %s: %v", HID1, data) +} + +func (h *Hid) WriteHid2(data []byte) { + deadline := time.Now().Add(8 * time.Millisecond) + + h.mouseMutex.Lock() + _ = h.g2.SetWriteDeadline(deadline) + _, err := h.g2.Write(data) + h.mouseMutex.Unlock() + + if err != nil { + switch { + case errors.Is(err, os.ErrClosed): + log.Errorf("hid already closed, reopen it...") + h.OpenNoLock() + case errors.Is(err, os.ErrDeadlineExceeded): + log.Debugf("write to %s timeout", HID2) + default: + log.Errorf("write to %s failed: %s", HID2, err) + } + return + } + + log.Debugf("write to %s: %v", HID2, data) } diff --git a/server/service/hid/keyboard.go b/server/service/hid/keyboard.go index cc9db3f..72e1676 100644 --- a/server/service/hid/keyboard.go +++ b/server/service/hid/keyboard.go @@ -2,20 +2,14 @@ package hid func (h *Hid) Keyboard(queue <-chan []int) { for event := range queue { - h.kbMutex.Lock() - h.writeKeyboard(event) - h.kbMutex.Unlock() + code := byte(event[0]) + + var modifier byte = 0x00 + if code > 0 { + modifier = byte(event[1]) | byte(event[2]) | byte(event[3]) | byte(event[4]) + } + + data := []byte{modifier, 0x00, code, 0x00, 0x00, 0x00, 0x00, 0x00} + h.WriteHid0(data) } } - -func (h *Hid) writeKeyboard(event []int) { - code := byte(event[0]) - - var modifier byte = 0x00 - if code > 0 { - modifier = byte(event[1]) | byte(event[2]) | byte(event[3]) | byte(event[4]) - } - - data := []byte{modifier, 0x00, code, 0x00, 0x00, 0x00, 0x00, 0x00} - h.Write(h.g0, data) -} diff --git a/server/service/hid/mouse.go b/server/service/hid/mouse.go index 60415e6..9acda14 100644 --- a/server/service/hid/mouse.go +++ b/server/service/hid/mouse.go @@ -2,9 +2,6 @@ package hid import ( "encoding/binary" - "errors" - "os" - "time" log "github.com/sirupsen/logrus" ) @@ -25,7 +22,6 @@ var mouseButtonMap = map[byte]bool{ func (h *Hid) Mouse(queue <-chan []int) { for event := range queue { - h.mouseMutex.Lock() switch event[0] { case MouseDown: @@ -39,10 +35,8 @@ func (h *Hid) Mouse(queue <-chan []int) { case MouseScroll: h.mouseScroll(event) default: - log.Debugf("invalid mouse event: %+v", event) + log.Debugf("invalid mouse event: %v", event) } - - h.mouseMutex.Unlock() } } @@ -50,17 +44,17 @@ func (h *Hid) mouseDown(event []int) { button := byte(event[1]) if _, ok := mouseButtonMap[button]; !ok { - log.Debugf("invalid mouse button: %+v", event) + log.Errorf("invalid mouse button: %v", event) return } data := []byte{button, 0, 0, 0} - h.writeWithTimeout(h.g1, data) + h.WriteHid1(data) } func (h *Hid) mouseUp() { data := []byte{0, 0, 0, 0} - h.writeWithTimeout(h.g1, data) + h.WriteHid1(data) } func (h *Hid) mouseScroll(event []int) { @@ -70,9 +64,8 @@ func (h *Hid) mouseScroll(event []int) { } data := []byte{0, 0, 0, byte(direction)} - h.writeWithTimeout(h.g1, data) + h.WriteHid1(data) } - func (h *Hid) mouseMoveAbsolute(event []int) { x := make([]byte, 2) y := make([]byte, 2) @@ -80,32 +73,10 @@ func (h *Hid) mouseMoveAbsolute(event []int) { binary.LittleEndian.PutUint16(y, uint16(event[3])) data := []byte{0, x[0], x[1], y[0], y[1], 0} - h.writeWithTimeout(h.g2, data) + h.WriteHid2(data) } func (h *Hid) mouseMoveRelative(event []int) { data := []byte{byte(event[1]), byte(event[2]), byte(event[3]), 0} - h.writeWithTimeout(h.g1, data) -} - -func (h *Hid) writeWithTimeout(file *os.File, data []byte) { - deadline := time.Now().Add(8 * time.Millisecond) - _ = file.SetWriteDeadline(deadline) - - _, err := file.Write(data) - if err != nil { - switch { - case errors.Is(err, os.ErrClosed): - log.Debugf("hid already closed, reopen it...") - h.OpenNoLock() - case errors.Is(err, os.ErrDeadlineExceeded): - log.Debugf("write to hid timeout") - default: - log.Errorf("write to hid failed: %s", err) - } - - return - } - - log.Debugf("write to hid: %+v", data) + h.WriteHid1(data) } diff --git a/server/service/hid/operation.go b/server/service/hid/operation.go deleted file mode 100644 index 3b84e63..0000000 --- a/server/service/hid/operation.go +++ /dev/null @@ -1,73 +0,0 @@ -package hid - -import ( - "errors" - "os" - - log "github.com/sirupsen/logrus" -) - -func (h *Hid) OpenNoLock() { - var err error - h.CloseNoLock() - - h.g0, err = os.OpenFile("/dev/hidg0", os.O_WRONLY, 0o666) - if err != nil { - log.Errorf("open /dev/hidg0 failed: %s", err) - } - - h.g1, err = os.OpenFile("/dev/hidg1", os.O_WRONLY, 0o666) - if err != nil { - log.Errorf("open /dev/hidg1 failed: %s", err) - } - - h.g2, err = os.OpenFile("/dev/hidg2", os.O_WRONLY, 0o666) - if err != nil { - log.Errorf("open /dev/hidg2 failed: %s", err) - } -} - -func (h *Hid) Open() { - h.kbMutex.Lock() - defer h.kbMutex.Unlock() - h.mouseMutex.Lock() - defer h.mouseMutex.Unlock() - - h.CloseNoLock() - - h.OpenNoLock() -} - -func (h *Hid) CloseNoLock() { - for _, file := range []*os.File{h.g0, h.g1, h.g2} { - if file != nil { - _ = file.Sync() - _ = file.Close() - } - } -} - -func (h *Hid) Close() { - h.kbMutex.Lock() - defer h.kbMutex.Unlock() - h.mouseMutex.Lock() - defer h.mouseMutex.Unlock() - - h.CloseNoLock() -} - -func (h *Hid) Write(file *os.File, data []byte) { - _, err := file.Write(data) - if err != nil { - if errors.Is(err, os.ErrClosed) { - log.Debugf("hid already closed, reopen it...") - h.OpenNoLock() - } else { - log.Errorf("write to hid failed: %s", err) - } - - return - } - - log.Debugf("write to hid: %+v", data) -} diff --git a/server/service/hid/paste.go b/server/service/hid/paste.go index b4511dd..1f8e701 100644 --- a/server/service/hid/paste.go +++ b/server/service/hid/paste.go @@ -16,7 +16,7 @@ type Char struct { type PasteReq struct { Content string `form:"content" validate:"required"` - Langue string `form:"langue"` + Langue string `form:"langue"` } func LangueSwitch(base map[rune]Char, lang string) map[rune]Char { @@ -48,41 +48,41 @@ func LangueSwitch(base map[rune]Char, lang string) map[rune]Char { m['\u00DF'] = Char{0, 45} // ß //Tauschen - m['^'] = Char{0, 53} // muss doppelt sein - m['/'] = Char{2, 36} // Shift + 7 - m['('] = Char{2, 37} // Shift + 8 - m['&'] = Char{2, 35} // Shift + 6 - m[')'] = Char{2, 38} // Shift + 9 - m['`'] = Char{2, 46} // Grave Accent / Backtick - m['"'] = Char{2, 31} // Shift + 2 - m['?'] = Char{2, 45} // Shift + ß - m['{'] = Char{0x40, 36} // ALt Gr + 7 - m['['] = Char{0x40, 37} // ALt Gr + 8 - m[']'] = Char{0x40, 38} // ALt Gr + 6 - m['}'] = Char{0x40, 39} // ALt Gr + 0 + m['^'] = Char{0, 53} // muss doppelt sein + m['/'] = Char{2, 36} // Shift + 7 + m['('] = Char{2, 37} // Shift + 8 + m['&'] = Char{2, 35} // Shift + 6 + m[')'] = Char{2, 38} // Shift + 9 + m['`'] = Char{2, 46} // Grave Accent / Backtick + m['"'] = Char{2, 31} // Shift + 2 + m['?'] = Char{2, 45} // Shift + ß + m['{'] = Char{0x40, 36} // ALt Gr + 7 + m['['] = Char{0x40, 37} // ALt Gr + 8 + m[']'] = Char{0x40, 38} // ALt Gr + 6 + m['}'] = Char{0x40, 39} // ALt Gr + 0 m['\\'] = Char{0x40, 45} // ALt Gr + ß - m['@'] = Char{0x40, 20} // ALt Gr + q - m['+'] = Char{0, 48} // Shift + + - m['*'] = Char{2, 48} // Shift + + - m['~'] = Char{0x40, 48} // Shift + + - m['#'] = Char{0, 49} // Shift + # - m['\''] = Char{2, 49} // Shift + # - m['<'] = Char{0, 100} // Shift + < - m['>'] = Char{2, 100} // Shift + < + m['@'] = Char{0x40, 20} // ALt Gr + q + m['+'] = Char{0, 48} // Shift + + + m['*'] = Char{2, 48} // Shift + + + m['~'] = Char{0x40, 48} // Shift + + + m['#'] = Char{0, 49} // Shift + # + m['\''] = Char{2, 49} // Shift + # + m['<'] = Char{0, 100} // Shift + < + m['>'] = Char{2, 100} // Shift + < m['|'] = Char{0x40, 100} // ALt Gr + < - m[';'] = Char{2, 54} // Shift + , - m[':'] = Char{2, 55} // Shift + . - m['-'] = Char{0, 56} // Shift + - - m['_'] = Char{2, 56} // Shift + - + m[';'] = Char{2, 54} // Shift + , + m[':'] = Char{2, 55} // Shift + . + m['-'] = Char{0, 56} // Shift + - + m['_'] = Char{2, 56} // Shift + - //neu - m['\u00B4'] = Char{0, 46} // ´ - m['\u00B0'] = Char{2, 53} // ° - m['\u00A7'] = Char{2, 32} // § - m['\u20AC'] = Char{0x40, 8} // € + m['\u00B4'] = Char{0, 46} // ´ + m['\u00B0'] = Char{2, 53} // ° + m['\u00A7'] = Char{2, 32} // § + m['\u20AC'] = Char{0x40, 8} // € m['\u00B2'] = Char{0x40, 31} // ² m['\u00B3'] = Char{0x40, 32} // ³ - + } return m } @@ -90,17 +90,19 @@ func LangueSwitch(base map[rune]Char, lang string) map[rune]Char { func (s *Service) Paste(c *gin.Context) { var req PasteReq var rsp proto.Response + if err := proto.ParseFormRequest(c, &req); err != nil { rsp.ErrRsp(c, -1, "invalid arguments") return } - charMapLocal := LangueSwitch(charMap, req.Langue) + if len(req.Content) > 1024 { rsp.ErrRsp(c, -2, "content too long") return } - s.hid.kbMutex.Lock() - defer s.hid.kbMutex.Unlock() + + charMapLocal := LangueSwitch(charMap, req.Langue) + keyUp := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} for _, char := range req.Content { @@ -109,10 +111,12 @@ func (s *Service) Paste(c *gin.Context) { log.Debugf("unknown key '%c' (rune: %d)", char, char) continue } + keyDown := []byte{byte(key.Modifiers), 0x00, byte(key.Code), 0x00, 0x00, 0x00, 0x00, 0x00} - s.hid.Write(s.hid.g0, keyDown) - s.hid.Write(s.hid.g0, keyUp) - time.Sleep(50 * time.Millisecond) + + hid.WriteHid0(keyDown) + hid.WriteHid0(keyUp) + time.Sleep(30 * time.Millisecond) } rsp.OkRsp(c) @@ -178,16 +182,16 @@ var charMap = map[rune]Char{ '/': {0, 56}, // Slash // Shifted symbols - '_': {2, 45}, // Underscore (Shift + Hyphen) - '+': {2, 46}, // Plus (Shift + Equals) - '{': {2, 47}, // Left Curly Brace (Shift + Left Square Bracket) - '}': {2, 48}, // Right Curly Brace (Shift + Right Square Bracket) - '|': {2, 49}, // Pipe (Shift + Backslash) + '_': {2, 45}, // Underscore (Shift + Hyphen) + '+': {2, 46}, // Plus (Shift + Equals) + '{': {2, 47}, // Left Curly Brace (Shift + Left Square Bracket) + '}': {2, 48}, // Right Curly Brace (Shift + Right Square Bracket) + '|': {2, 49}, // Pipe (Shift + Backslash) - ':': {2, 51}, // Colon (Shift + Semicolon) - '"': {2, 52}, // Double Quote (Shift + Apostrophe) - '~': {2, 53}, // Tilde (Shift + Grave Accent) - '<': {2, 54}, // Less Than (Shift + Comma) - '>': {2, 55}, // Greater Than (Shift + Period) - '?': {2, 56}, // Question Mark (Shift + Slash) + ':': {2, 51}, // Colon (Shift + Semicolon) + '"': {2, 52}, // Double Quote (Shift + Apostrophe) + '~': {2, 53}, // Tilde (Shift + Grave Accent) + '<': {2, 54}, // Less Than (Shift + Comma) + '>': {2, 55}, // Greater Than (Shift + Period) + '?': {2, 56}, // Question Mark (Shift + Slash) } diff --git a/server/service/hid/reset.go b/server/service/hid/reset.go deleted file mode 100644 index 4cdbffa..0000000 --- a/server/service/hid/reset.go +++ /dev/null @@ -1,82 +0,0 @@ -package hid - -import ( - "NanoKVM-Server/proto" - "os" - "time" - - "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" -) - -func (s *Service) Reset(c *gin.Context) { - var rsp proto.Response - - h := GetHid() - h.Lock() - h.CloseNoLock() - defer func() { - h.OpenNoLock() - h.Unlock() - }() - - // reset USB - f, err := os.OpenFile("/sys/kernel/config/usb_gadget/g0/UDC", os.O_WRONLY, 0644) - if err != nil { - log.Errorf("open /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) - rsp.ErrRsp(c, -1, "open usb gadget file failed") - return - } - err = f.Truncate(0) - if err != nil { - _ = f.Close() - log.Errorf("truncate /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) - rsp.ErrRsp(c, -1, "truncate usb gadget file failed") - return - } - _, err = f.Seek(0, 0) - if err != nil { - _ = f.Close() - log.Errorf("seek to 0 failed: %s", err) - rsp.ErrRsp(c, -1, "seek to 0 in usb gadget file failed") - return - } - _, err = f.WriteString("\n") - if err != nil { - _ = f.Close() - log.Errorf("write to /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) - rsp.ErrRsp(c, -1, "write to usb gadget file failed") - return - } - _ = f.Close() - - time.Sleep(1 * time.Second) - - devices, err := os.ReadDir("/sys/class/udc/") - if err != nil { - log.Errorf("read udc directory failed: %s", err) - rsp.ErrRsp(c, -1, "read udc directory failed") - return - } - - f, err = os.OpenFile("/sys/kernel/config/usb_gadget/g0/UDC", os.O_WRONLY, 0644) - if err != nil { - log.Errorf("open /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) - rsp.ErrRsp(c, -1, "open usb gadget file failed") - return - } - for _, device := range devices { - _, err = f.WriteString(device.Name() + "\n") - if err != nil { - _ = f.Close() - log.Errorf("write to /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) - rsp.ErrRsp(c, -1, "write to usb gadget file failed") - return - } - } - - _ = f.Close() - - rsp.OkRsp(c) - log.Debugf("reset hid success") -} diff --git a/server/service/hid/mode.go b/server/service/hid/status.go similarity index 74% rename from server/service/hid/mode.go rename to server/service/hid/status.go index 9a77cb9..08c06a1 100644 --- a/server/service/hid/mode.go +++ b/server/service/hid/status.go @@ -3,6 +3,7 @@ package hid import ( "NanoKVM-Server/proto" "errors" + "fmt" "io" "os" "os/exec" @@ -16,11 +17,12 @@ import ( const ( ModeNormal = "normal" ModeHidOnly = "hid-only" + ModeFlag = "/sys/kernel/config/usb_gadget/g0/bcdDevice" - ModeFlag = "/sys/kernel/config/usb_gadget/g0/bcdDevice" - NormalModeScript = "/kvmapp/system/init.d/S03usbdev" - HidOnlyModeScript = "/kvmapp/system/init.d/S03usbhid" - TargetModeScript = "/etc/init.d/S03usbdev" + ModeNormalScript = "/kvmapp/system/init.d/S03usbdev" + ModeHidOnlyScript = "/kvmapp/system/init.d/S03usbhid" + + USBDevScript = "/etc/init.d/S03usbdev" ) var modeMap = map[string]string{ @@ -61,9 +63,17 @@ func (s *Service) SetHidMode(c *gin.Context) { return } - srcScript := NormalModeScript + h := GetHid() + h.Lock() + h.CloseNoLock() + defer func() { + h.OpenNoLock() + h.Unlock() + }() + + srcScript := ModeNormalScript if req.Mode == ModeHidOnly { - srcScript = HidOnlyModeScript + srcScript = ModeHidOnlyScript } if err := copyModeFile(srcScript); err != nil { @@ -78,6 +88,29 @@ func (s *Service) SetHidMode(c *gin.Context) { _ = exec.Command("reboot").Run() } +func (s *Service) ResetHid(c *gin.Context) { + var rsp proto.Response + + h := GetHid() + h.Lock() + h.CloseNoLock() + defer func() { + h.OpenNoLock() + h.Unlock() + }() + + command := fmt.Sprintf("%s restart_phy", USBDevScript) + err := exec.Command("sh", "-c", command).Run() + if err != nil { + log.Errorf("failed to reset hid: %v", err) + rsp.ErrRsp(c, -1, "failed to reset hid") + return + } + + rsp.OkRsp(c) + log.Debugf("reset hid success") +} + func copyModeFile(srcScript string) error { // open the source file srcFile, err := os.Open(srcScript) @@ -98,7 +131,7 @@ func copyModeFile(srcScript string) error { // create and copy to temporary file tmpFile, err := os.CreateTemp("/etc/init.d/", ".S03usbdev-") if err != nil { - log.Errorf("failed to create temp %s: %s", TargetModeScript, err) + log.Errorf("failed to create temp %s: %s", USBDevScript, err) return err } tmpPath := tmpFile.Name() @@ -131,12 +164,12 @@ func copyModeFile(srcScript string) error { } // replace the target file with the temporary file - if err := os.Rename(tmpPath, TargetModeScript); err != nil { + if err := os.Rename(tmpPath, USBDevScript); err != nil { log.Errorf("failed to rename %s: %s", tmpPath, err) return err } - log.Debugf("copy %s to %s successful", srcScript, TargetModeScript) + log.Debugf("copy %s to %s successful", srcScript, USBDevScript) return nil } diff --git a/server/service/storage/image.go b/server/service/storage/image.go index c064fb3..4e0be46 100644 --- a/server/service/storage/image.go +++ b/server/service/storage/image.go @@ -190,3 +190,31 @@ func (s *Service) GetCdRom(c *gin.Context) { rsp.OkRspWithData(c, data) } + +func (s *Service) DeleteImage(c *gin.Context) { + var req proto.DeleteImageReq + var rsp proto.Response + + if err := proto.ParseFormRequest(c, &req); err != nil { + rsp.ErrRsp(c, -1, "invalid arguments") + return + } + + filename := strings.ToLower(req.File) + validPrefix := strings.HasPrefix(filename, imageDirectory) + validSuffix := strings.HasSuffix(filename, ".iso") || strings.HasSuffix(filename, ".img") + + if !validPrefix || !validSuffix { + rsp.ErrRsp(c, -2, "invalid arguments") + return + } + + if err := os.Remove(req.File); err != nil { + rsp.ErrRsp(c, -3, "remove file failed") + log.Errorf("failed to remove file %s: %s", req.File, err) + return + } + + rsp.OkRsp(c) + log.Debugf("delete image %s success", req.File) +} diff --git a/server/service/stream/direct/h264.go b/server/service/stream/direct/h264.go index 0803836..ea65d73 100644 --- a/server/service/stream/direct/h264.go +++ b/server/service/stream/direct/h264.go @@ -1,30 +1,17 @@ package direct import ( - "encoding/base64" - "encoding/json" "net/http" - "sync" "time" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" log "github.com/sirupsen/logrus" - - "NanoKVM-Server/common" ) -type Frame struct { - IsKeyFrame bool `json:"isKeyFrame"` - Data string `json:"data"` - Timestamp int64 `json:"timestamp"` -} - var ( - mutex = sync.Mutex{} - wsMap = make(map[*websocket.Conn]bool) - isSending = false - upgrader = websocket.Upgrader{ + streamer = newStreamer() + upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, @@ -34,74 +21,24 @@ var ( func Connect(c *gin.Context) { ws, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { - log.Errorf("failed to create websocket: %s", err) + log.Errorf("failed to upgrade to websocket: %s", err) return } - defer func() { _ = ws.Close() - log.Debugf("h264 websocket disconnected") + log.Debugf("h264 websocket disconnected: %s", ws.RemoteAddr()) }() + log.Debugf("h264 websocket connected: %s", ws.RemoteAddr()) - var zeroTime time.Time - _ = ws.SetReadDeadline(zeroTime) + _ = ws.SetReadDeadline(time.Time{}) - mutex.Lock() - wsMap[ws] = true - if len(wsMap) == 1 && !isSending { - go send() - } - mutex.Unlock() + streamer.addClient(ws) + defer streamer.removeClient(ws) - _, _, err = ws.ReadMessage() - if err != nil { - mutex.Lock() - delete(wsMap, ws) - mutex.Unlock() - log.Debugf("failed to read message: %s", err) - } -} - -func send() { - isSending = true - screen := common.GetScreen() - common.CheckScreen() - - fps := screen.FPS - duration := time.Second / time.Duration(fps) - - ticker := time.NewTicker(duration) - defer ticker.Stop() - - vision := common.GetKvmVision() - startTime := time.Now() - - for range ticker.C { - if len(wsMap) == 0 { - isSending = false + for { + if _, _, err := ws.ReadMessage(); err != nil { + log.Debugf("failed to read message (client disconnected): %s", err) return } - - data, result := vision.ReadH264(screen.Width, screen.Height, screen.BitRate) - if result < 0 { - continue - } - - frameMsg := Frame{ - IsKeyFrame: result == 3, - Data: base64.StdEncoding.EncodeToString(data), - Timestamp: time.Since(startTime).Microseconds(), - } - - frameJSON, err := json.Marshal(frameMsg) - if err != nil { - continue - } - - for ws := range wsMap { - if err := ws.WriteMessage(websocket.TextMessage, frameJSON); err != nil { - log.Debugf("failed to write message: %s", err) - } - } } } diff --git a/server/service/stream/direct/pool.go b/server/service/stream/direct/pool.go new file mode 100644 index 0000000..1f2fe06 --- /dev/null +++ b/server/service/stream/direct/pool.go @@ -0,0 +1,12 @@ +package direct + +import ( + "bytes" + "sync" +) + +var BufferPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} diff --git a/server/service/stream/direct/streamer.go b/server/service/stream/direct/streamer.go new file mode 100644 index 0000000..0f87653 --- /dev/null +++ b/server/service/stream/direct/streamer.go @@ -0,0 +1,123 @@ +package direct + +import ( + "NanoKVM-Server/common" + "NanoKVM-Server/service/stream" + "bytes" + "encoding/binary" + "sync" + "sync/atomic" + "time" + + "github.com/gorilla/websocket" + log "github.com/sirupsen/logrus" +) + +type Streamer struct { + mutex sync.RWMutex + clients map[*websocket.Conn]bool + running int32 +} + +func newStreamer() *Streamer { + return &Streamer{ + clients: make(map[*websocket.Conn]bool), + } +} + +func (s *Streamer) addClient(ws *websocket.Conn) { + s.mutex.Lock() + s.clients[ws] = true + s.mutex.Unlock() + + if atomic.CompareAndSwapInt32(&s.running, 0, 1) { + go s.run() + log.Debug("h264 stream started") + } +} + +func (s *Streamer) removeClient(ws *websocket.Conn) { + s.mutex.Lock() + delete(s.clients, ws) + s.mutex.Unlock() + + log.Debugf("h264 websocket disconnected, remaining clients: %d", len(s.clients)) +} + +func (s *Streamer) getClientCount() int { + s.mutex.RLock() + defer s.mutex.RUnlock() + + return len(s.clients) +} + +func (s *Streamer) run() { + defer atomic.StoreInt32(&s.running, 0) + + duration := time.Second / time.Duration(120) + ticker := time.NewTicker(duration) + defer ticker.Stop() + + screen := common.GetScreen() + vision := common.GetKvmVision() + startTime := time.Now() + + for range ticker.C { + if s.getClientCount() == 0 { + log.Debug("h264 stream stopped due to no clients") + return + } + + data, result := vision.ReadH264(screen.Width, screen.Height, screen.BitRate) + if result < 0 || len(data) == 0 { + continue + } + + isKeyFrame := byte(0) + if result == 3 { + isKeyFrame = byte(1) + } + + timestamp := time.Since(startTime).Microseconds() + + if err := s.send(isKeyFrame, timestamp, data); err != nil { + continue + } + + stream.GetFrameRateCounter().Update() + } +} + +func (s *Streamer) send(isKeyFrame byte, timestamp int64, data []byte) error { + buf := BufferPool.Get().(*bytes.Buffer) + defer BufferPool.Put(buf) + + buf.Reset() + + if err := buf.WriteByte(isKeyFrame); err != nil { + log.Errorf("failed to write keyframe flag: %s", err) + return err + } + + tsBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(tsBytes, uint64(timestamp)) + if _, err := buf.Write(tsBytes); err != nil { + log.Errorf("failed to write timestamp: %s", err) + return err + } + + if _, err := buf.Write(data); err != nil { + log.Errorf("failed to write h264 data: %s", err) + return err + } + + for client := range s.clients { + if err := client.WriteMessage(websocket.BinaryMessage, buf.Bytes()); err != nil { + log.Errorf("failed to write message to client %s: %s.", client.RemoteAddr(), err) + + s.removeClient(client) + } + } + + return nil +} diff --git a/server/service/stream/frame-rate.go b/server/service/stream/frame_rate.go similarity index 100% rename from server/service/stream/frame-rate.go rename to server/service/stream/frame_rate.go diff --git a/server/service/stream/h264/sender.go b/server/service/stream/h264/sender.go index 4f0c95b..e59f57f 100644 --- a/server/service/stream/h264/sender.go +++ b/server/service/stream/h264/sender.go @@ -25,7 +25,7 @@ func send() { } data, result := vision.ReadH264(screen.Width, screen.Height, screen.BitRate) - if result < 0 { + if result < 0 || len(data) == 0 { continue } @@ -40,8 +40,6 @@ func send() { } } - log.Debugf("send h264 data: %d", len(data)) - if screen.FPS != fps { fps = screen.FPS duration = time.Second / time.Duration(fps) diff --git a/server/service/stream/mjpeg/mjpeg.go b/server/service/stream/mjpeg/mjpeg.go index ffeb067..d09f818 100644 --- a/server/service/stream/mjpeg/mjpeg.go +++ b/server/service/stream/mjpeg/mjpeg.go @@ -1,99 +1,22 @@ package mjpeg import ( - "NanoKVM-Server/common" - "NanoKVM-Server/service/stream" - "sync" "time" "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" ) -var ( - chanMap = make(map[*gin.Context]bool) - mutex = sync.Mutex{} - exitSig = make(chan bool, 1) -) +var streamer = NewStreamer() func Connect(c *gin.Context) { c.Header("Content-Type", "multipart/x-mixed-replace; boundary=frame") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") c.Header("Pragma", "no-cache") + c.Header("X-Server-Date", time.Now().Format(time.RFC1123)) - mutex.Lock() - chanMap[c] = true - if len(chanMap) == 1 { - go send() - } - mutex.Unlock() + streamer.AddClient(c) + defer streamer.RemoveClient(c) <-c.Request.Context().Done() - - mutex.Lock() - delete(chanMap, c) - if len(chanMap) == 0 { - exitSig <- true - } - mutex.Unlock() -} - -func send() { - screen := common.GetScreen() - common.CheckScreen() - - fps := screen.FPS - - ticker := time.NewTicker(time.Second / time.Duration(fps)) - defer ticker.Stop() - - vision := common.GetKvmVision() - for { - select { - case <-ticker.C: - data, result := vision.ReadMjpeg(screen.Width, screen.Height, screen.Quality) - if result < 0 || result == 5 { - continue - } - - for c := range chanMap { - if err := write(c, data); err != nil { - log.Debugf("failed to write mjpeg data: %s", err) - } - } - log.Debugf("send mjpeg data: %d", len(data)) - - stream.GetFrameRateCounter().Update() - - if screen.FPS != fps { - fps = screen.FPS - ticker.Reset(time.Second / time.Duration(fps)) - } - - case <-exitSig: - return - } - } -} - -func write(c *gin.Context, data []byte) (err error) { - if _, err = c.Writer.Write([]byte("--frame\r\n")); err != nil { - return - } - - if _, err = c.Writer.Write([]byte("Content-Type: image/jpeg\r\n\r\n")); err != nil { - return - } - - if _, err = c.Writer.Write(data); err != nil { - return - } - - if _, err = c.Writer.Write([]byte("\r\n")); err != nil { - return - } - - c.Writer.Flush() - return } diff --git a/server/service/stream/mjpeg/streamer.go b/server/service/stream/mjpeg/streamer.go new file mode 100644 index 0000000..5bddc20 --- /dev/null +++ b/server/service/stream/mjpeg/streamer.go @@ -0,0 +1,131 @@ +package mjpeg + +import ( + "NanoKVM-Server/common" + "NanoKVM-Server/service/stream" + "fmt" + "strconv" + "sync" + "sync/atomic" + "time" + + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +type Streamer struct { + mutex sync.RWMutex + clients map[*gin.Context]bool + running int32 +} + +func NewStreamer() *Streamer { + return &Streamer{ + clients: make(map[*gin.Context]bool), + } +} + +func (s *Streamer) AddClient(c *gin.Context) { + s.mutex.Lock() + s.clients[c] = true + s.mutex.Unlock() + + if atomic.CompareAndSwapInt32(&s.running, 0, 1) { + go s.run() + log.Debug("mjpeg stream started") + } +} + +func (s *Streamer) RemoveClient(c *gin.Context) { + s.mutex.Lock() + delete(s.clients, c) + s.mutex.Unlock() + + log.Debugf("mjpeg connection removed, remaining clients: %d", len(s.clients)) +} + +func (s *Streamer) getClients() []*gin.Context { + s.mutex.RLock() + defer s.mutex.RUnlock() + + clients := make([]*gin.Context, 0, len(s.clients)) + for c := range s.clients { + clients = append(clients, c) + } + + return clients +} + +func (s *Streamer) getClientCount() int { + s.mutex.RLock() + defer s.mutex.RUnlock() + + return len(s.clients) +} + +func (s *Streamer) run() { + defer atomic.StoreInt32(&s.running, 0) + + screen := common.GetScreen() + common.CheckScreen() + fps := screen.FPS + + vision := common.GetKvmVision() + + ticker := time.NewTicker(time.Second / time.Duration(fps)) + defer ticker.Stop() + + for range ticker.C { + if s.getClientCount() == 0 { + log.Debug("mjpeg stream stopped due to no clients") + return + } + + data, result := vision.ReadMjpeg(screen.Width, screen.Height, screen.Quality) + if result < 0 || result == 5 || len(data) == 0 { + continue + } + + clients := s.getClients() + for _, client := range clients { + if err := writeFrame(client, data); err != nil { + log.Errorf("failed to write mjpeg frame for client %s: %s", client.Request.RemoteAddr, err) + s.RemoveClient(client) + } + } + + if screen.FPS != fps && screen.FPS != 0 { + fps = screen.FPS + ticker.Reset(time.Second / time.Duration(fps)) + } + + stream.GetFrameRateCounter().Update() + } +} + +func writeFrame(c *gin.Context, data []byte) (err error) { + defer func() { + if r := recover(); r != nil { + err = c.Request.Context().Err() + if err == nil { + err = fmt.Errorf("panic recovered in writeFrame: %v", r) + } + } + }() + + header := "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: " + strconv.Itoa(len(data)) + "\r\n\r\n" + if _, err = c.Writer.WriteString(header); err != nil { + return err + } + + if _, err = c.Writer.Write(data); err != nil { + return err + } + + if _, err = c.Writer.Write([]byte("\r\n")); err != nil { + return err + } + + c.Writer.Flush() + return nil +} diff --git a/server/service/stream/webrtc/client.go b/server/service/stream/webrtc/client.go new file mode 100644 index 0000000..1ace3cd --- /dev/null +++ b/server/service/stream/webrtc/client.go @@ -0,0 +1,112 @@ +package webrtc + +import ( + "encoding/json" + "errors" + + "github.com/gorilla/websocket" + "github.com/pion/rtp" + "github.com/pion/rtp/codecs" + "github.com/pion/webrtc/v4" + log "github.com/sirupsen/logrus" + + "sync" +) + +func NewClient(ws *websocket.Conn, videoConn *webrtc.PeerConnection) *Client { + return &Client{ + ws: ws, + video: videoConn, + mutex: sync.Mutex{}, + } +} + +func (c *Client) WriteMessage(event string, data string) error { + c.mutex.Lock() + defer c.mutex.Unlock() + + message := &Message{ + Event: event, + Data: data, + } + + if err := c.ws.WriteJSON(message); err != nil { + log.Errorf("failed to send message %s: %v", event, err) + return err + } + + log.Debugf("sent message %s", event) + return nil +} + +func (c *Client) ReadMessage() (*Message, error) { + _, raw, err := c.ws.ReadMessage() + if err != nil { + log.Errorf("failed to read message: %v", err) + return nil, err + } + + var message Message + if err := json.Unmarshal(raw, &message); err != nil { + log.Errorf("failed to unmarshal message: %v", err) + return nil, nil + } + + return &message, nil +} + +func (c *Client) AddTrack() error { + // video track + videoTrack, err := webrtc.NewTrackLocalStaticRTP( + webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH264}, + "video", + "pion-video", + ) + if err != nil { + log.Errorf("failed to create video track: %s", err) + return err + } + + videoPacketizer := rtp.NewPacketizer( + 1200, + 100, + 0x1234ABCD, + &codecs.H264Payloader{}, + rtp.NewRandomSequencer(), + 90000, + ) + if videoPacketizer == nil { + err := errors.New("failed to create rtp packetizer") + log.Error(err) + return err + } + + videoSender, err := c.video.AddTrack(videoTrack) + if err != nil { + log.Errorf("failed to add video track: %s", err) + return err + } + go startRTCPReader(videoSender) + + track := &Track{ + videoPacketizer: videoPacketizer, + video: videoTrack, + } + track.updateExtension() + + c.mutex.Lock() + c.track = track + c.mutex.Unlock() + + return nil +} + +func startRTCPReader(sender *webrtc.RTPSender) { + rtcpBuf := make([]byte, 1500) + for { + if _, _, err := sender.Read(rtcpBuf); err != nil { + log.Debugf("RTCP reader error: %v", err) + return + } + } +} diff --git a/server/service/stream/webrtc/h264.go b/server/service/stream/webrtc/h264.go new file mode 100644 index 0000000..f2217c7 --- /dev/null +++ b/server/service/stream/webrtc/h264.go @@ -0,0 +1,158 @@ +package webrtc + +import ( + "NanoKVM-Server/config" + "net/http" + "sync" + "time" + + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" + "github.com/pion/dtls/v3" + "github.com/pion/webrtc/v4" + log "github.com/sirupsen/logrus" +) + +var ( + upgrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, + } + globalManager *WebRTCManager + managerOnce sync.Once +) + +func getManager() *WebRTCManager { + managerOnce.Do(func() { + globalManager = NewWebRTCManager() + }) + return globalManager +} + +func Connect(c *gin.Context) { + // create WebSocket connection + wsConn, err := upgrader.Upgrade(c.Writer, c.Request, nil) + if err != nil { + log.Errorf("failed to create h264 websocket: %s", err) + return + } + defer func() { + _ = wsConn.Close() + log.Debugf("h264 websocket disconnected: %s", c.ClientIP()) + }() + log.Debugf("h264 websocket connected: %s", c.ClientIP()) + + var zeroTime time.Time + _ = wsConn.SetReadDeadline(zeroTime) + + // create video connection + iceServers := createICEServers() + + mediaEngine, err := createMediaEngine() + if err != nil { + log.Errorf("failed to create h264 media engine: %s", err) + return + } + + videoConn, err := createPeerConnection(iceServers, mediaEngine) + if err != nil { + log.Errorf("failed to create h264 video peer connection: %s", err) + return + } + defer func() { + _ = videoConn.Close() + log.Debugf("h264 video peer disconnected: %s", c.ClientIP()) + }() + + // create client + client := NewClient(wsConn, videoConn) + if err := client.AddTrack(); err != nil { + log.Errorf("failed to add track: %s", err) + return + } + + manager := getManager() + manager.AddClient(wsConn, client) + defer manager.RemoveClient(wsConn) + + // handle signaling + signalingHandler := NewSignalingHandler(client) + signalingHandler.RegisterCallbacks() + + // read and wait + for { + message, err := client.ReadMessage() + if err != nil { + return + } + if message != nil { + if err := signalingHandler.HandleMessage(message); err != nil { + log.Errorf("failed to handle signaling message: %s", err) + } + } + } +} + +func createICEServers() []webrtc.ICEServer { + var iceServers []webrtc.ICEServer + + conf := config.GetInstance() + + if conf.Stun != "" && conf.Stun != "disable" { + iceServers = append(iceServers, webrtc.ICEServer{ + URLs: []string{"stun:" + conf.Stun}, + }) + } + + if conf.Turn.TurnAddr != "" && conf.Turn.TurnUser != "" && conf.Turn.TurnCred != "" { + iceServers = append(iceServers, webrtc.ICEServer{ + URLs: []string{"turn:" + conf.Turn.TurnAddr}, + Username: conf.Turn.TurnUser, + Credential: conf.Turn.TurnCred, + }) + } + + return iceServers +} + +func createMediaEngine() (*webrtc.MediaEngine, error) { + mediaEngine := &webrtc.MediaEngine{} + + if err := mediaEngine.RegisterDefaultCodecs(); err != nil { + log.Errorf("failed to register default codecs: %s", err) + return nil, err + } + + if err := mediaEngine.RegisterHeaderExtension( + webrtc.RTPHeaderExtensionCapability{URI: "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay"}, + webrtc.RTPCodecTypeVideo, + ); err != nil { + log.Errorf("failed to register header extension: %s", err) + return nil, err + } + + return mediaEngine, nil +} + +func createPeerConnection(iceServers []webrtc.ICEServer, mediaEngine *webrtc.MediaEngine) (*webrtc.PeerConnection, error) { + settingEngine := webrtc.SettingEngine{} + settingEngine.SetSRTPProtectionProfiles( + dtls.SRTP_AEAD_AES_128_GCM, + dtls.SRTP_AES128_CM_HMAC_SHA1_80, + ) + + apiOptions := []func(api *webrtc.API){ + webrtc.WithSettingEngine(settingEngine), + } + if mediaEngine != nil { + apiOptions = append(apiOptions, webrtc.WithMediaEngine(mediaEngine)) + } + + api := webrtc.NewAPI(apiOptions...) + + return api.NewPeerConnection(webrtc.Configuration{ + ICEServers: iceServers, + SDPSemantics: webrtc.SDPSemanticsUnifiedPlan, + }) +} diff --git a/server/service/stream/webrtc/manager.go b/server/service/stream/webrtc/manager.go new file mode 100644 index 0000000..59d03d0 --- /dev/null +++ b/server/service/stream/webrtc/manager.go @@ -0,0 +1,96 @@ +package webrtc + +import ( + "NanoKVM-Server/common" + "NanoKVM-Server/service/stream" + "sync" + "sync/atomic" + "time" + + "github.com/gorilla/websocket" + "github.com/pion/webrtc/v4/pkg/media" + log "github.com/sirupsen/logrus" +) + +func NewWebRTCManager() *WebRTCManager { + return &WebRTCManager{ + clients: make(map[*websocket.Conn]*Client), + videoSending: 0, + mutex: sync.RWMutex{}, + } +} + +func (m *WebRTCManager) AddClient(ws *websocket.Conn, client *Client) { + client.track.updateExtension() + + m.mutex.Lock() + m.clients[ws] = client + m.mutex.Unlock() + + log.Debugf("added client %s, total clients: %d", ws.RemoteAddr(), len(m.clients)) +} + +func (m *WebRTCManager) RemoveClient(ws *websocket.Conn) { + m.mutex.Lock() + delete(m.clients, ws) + m.mutex.Unlock() + + log.Debugf("removed client %s, total clients: %d", ws.RemoteAddr(), len(m.clients)) +} + +func (m *WebRTCManager) GetClientCount() int { + m.mutex.RLock() + defer m.mutex.RUnlock() + + return len(m.clients) +} + +func (m *WebRTCManager) StartVideoStream() { + if atomic.CompareAndSwapInt32(&m.videoSending, 0, 1) { + go m.sendVideoStream() + log.Debugf("start sending h264 stream") + } +} + +func (m *WebRTCManager) sendVideoStream() { + defer atomic.StoreInt32(&m.videoSending, 0) + + screen := common.GetScreen() + common.CheckScreen() + fps := screen.FPS + duration := time.Second / time.Duration(fps) + + vision := common.GetKvmVision() + + ticker := time.NewTicker(duration) + defer ticker.Stop() + + for range ticker.C { + if m.GetClientCount() == 0 { + log.Debugf("stop sending h264 stream") + return + } + + data, result := vision.ReadH264(screen.Width, screen.Height, screen.BitRate) + if result < 0 || len(data) == 0 { + continue + } + + sample := media.Sample{ + Data: data, + Duration: duration, + } + + for _, client := range m.clients { + client.track.writeVideo(sample) + } + + if screen.FPS != fps && screen.FPS != 0 { + fps = screen.FPS + duration = time.Second / time.Duration(fps) + ticker.Reset(duration) + } + + stream.GetFrameRateCounter().Update() + } +} diff --git a/server/service/stream/webrtc/signaling.go b/server/service/stream/webrtc/signaling.go new file mode 100644 index 0000000..7423989 --- /dev/null +++ b/server/service/stream/webrtc/signaling.go @@ -0,0 +1,149 @@ +package webrtc + +import ( + "encoding/json" + "errors" + + "github.com/pion/webrtc/v4" + log "github.com/sirupsen/logrus" +) + +func NewSignalingHandler(client *Client) *SignalingHandler { + return &SignalingHandler{ + client: client, + } +} + +// RegisterCallbacks Register callback functions +func (s *SignalingHandler) RegisterCallbacks() { + // video ICE candidate + s.client.video.OnICECandidate(func(candidate *webrtc.ICECandidate) { + if candidate == nil { + return + } + + candidateByte, err := json.Marshal(candidate.ToJSON()) + if err != nil { + log.Errorf("failed to marshal video candidate: %s", err) + return + } + + if err := s.client.WriteMessage("video-candidate", string(candidateByte)); err != nil { + log.Errorf("failed to send video candidate: %s", err) + } + }) + + manager := getManager() + + // video connection state change + s.client.video.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) { + if state == webrtc.ICEConnectionStateConnected { + manager.StartVideoStream() + } + + log.Debugf("video connection state changed to %s", state.String()) + }) +} + +// HandleMessage handle the received message +func (s *SignalingHandler) HandleMessage(message *Message) error { + switch message.Event { + case "video-offer": + return s.handleVideoOffer(message.Data) + case "video-candidate": + return s.handleVideoCandidate(message.Data) + case "heartbeat": + return s.handleHeartbeat() + default: + log.Debugf("Unhandled message event: %s", message.Event) + return nil + } +} + +func (s *SignalingHandler) handleVideoOffer(data string) error { + if s.client.video.SignalingState() != webrtc.SignalingStateStable { + err := errors.New("video signaling is not stable") + log.Error(err) + return err + } + + offer := webrtc.SessionDescription{} + if err := json.Unmarshal([]byte(data), &offer); err != nil { + log.Errorf("failed to unmarshal video offer: %s", err) + return err + } + + if err := s.client.video.SetRemoteDescription(offer); err != nil { + log.Errorf("failed to set remote description: %s", err) + return err + } + + answer, err := s.client.video.CreateAnswer(nil) + if err != nil { + log.Errorf("failed to create answer: %s", err) + return err + } + + if err := s.client.video.SetLocalDescription(answer); err != nil { + log.Errorf("failed to set local description: %s", err) + return err + } + + if err := s.updateHeaderExtensionID(); err != nil { + log.Errorf("could not update header extension ID: %v", err) + return err + } + + answerByte, err := json.Marshal(answer) + if err != nil { + log.Errorf("failed to marshal answer: %s", err) + return err + } + + return s.client.WriteMessage("video-answer", string(answerByte)) +} + +// set extension ID +func (s *SignalingHandler) updateHeaderExtensionID() error { + receivers := s.client.video.GetReceivers() + if len(receivers) == 0 { + return errors.New("no RTP receiver found for video") + } + + params := receivers[0].GetParameters() + if len(params.HeaderExtensions) == 0 { + return errors.New("no header extensions found in negotiated parameters") + } + + for _, ext := range params.HeaderExtensions { + if ext.URI == "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" { + s.client.track.playoutDelayExtensionID = uint8(ext.ID) + log.Debugf("found and set playout delay extension ID to: %d", ext.ID) + return nil + } + } + + log.Warnf("no track extension found in negotiated parameters, use default value 5") + return nil +} + +// handle video candidate +func (s *SignalingHandler) handleVideoCandidate(data string) error { + candidate := webrtc.ICECandidateInit{} + if err := json.Unmarshal([]byte(data), &candidate); err != nil { + log.Errorf("failed to unmarshal candidate: %s", err) + return err + } + + if err := s.client.video.AddICECandidate(candidate); err != nil { + log.Errorf("failed to add ICECandidate: %s", err) + return err + } + + return nil +} + +// handle heartbeat +func (s *SignalingHandler) handleHeartbeat() error { + return s.client.WriteMessage("heartbeat", "") +} diff --git a/server/service/stream/webrtc/track.go b/server/service/stream/webrtc/track.go new file mode 100644 index 0000000..3c3b279 --- /dev/null +++ b/server/service/stream/webrtc/track.go @@ -0,0 +1,53 @@ +package webrtc + +import ( + "github.com/pion/rtp" + "github.com/pion/webrtc/v4/pkg/media" + log "github.com/sirupsen/logrus" +) + +func (t *Track) updateExtension() { + if t.playoutDelayExtensionID == 0 { + t.playoutDelayExtensionID = 5 + } + + if t.playoutDelayExtensionData == nil || len(t.playoutDelayExtensionData) == 0 { + playoutDelay := &rtp.PlayoutDelayExtension{ + MinDelay: 0, + MaxDelay: 0, + } + playoutDelayExtensionData, err := playoutDelay.Marshal() + if err == nil { + t.playoutDelayExtensionData = playoutDelayExtensionData + } + } +} + +func (t *Track) writeVideoSample(sample media.Sample) error { + samples := uint32(sample.Duration.Seconds() * 90000) + packets := t.videoPacketizer.Packetize(sample.Data, samples) + + for _, p := range packets { + p.Header.Extension = true + p.Header.ExtensionProfile = 0xBEDE + + if err := p.Header.SetExtension(t.playoutDelayExtensionID, t.playoutDelayExtensionData); err != nil { + log.Errorf("Failed to set extension: %v", err) + return err + } + + if err := t.video.WriteRTP(p); err != nil { + log.Errorf("failed to write RTP: %v", err) + return err + } + } + + return nil +} + +func (t *Track) writeVideo(sample media.Sample) { + err := t.writeVideoSample(sample) + if err != nil { + log.Errorf("failed to write h264 video: %s", err) + } +} diff --git a/server/service/stream/webrtc/types.go b/server/service/stream/webrtc/types.go new file mode 100644 index 0000000..e109254 --- /dev/null +++ b/server/service/stream/webrtc/types.go @@ -0,0 +1,38 @@ +package webrtc + +import ( + "sync" + + "github.com/gorilla/websocket" + "github.com/pion/rtp" + "github.com/pion/webrtc/v4" +) + +type WebRTCManager struct { + clients map[*websocket.Conn]*Client + videoSending int32 + mutex sync.RWMutex +} + +type Client struct { + ws *websocket.Conn + video *webrtc.PeerConnection + track *Track + mutex sync.Mutex +} + +type SignalingHandler struct { + client *Client +} + +type Track struct { + playoutDelayExtensionID uint8 + playoutDelayExtensionData []byte + videoPacketizer rtp.Packetizer + video *webrtc.TrackLocalStaticRTP +} + +type Message struct { + Event string `json:"event"` + Data string `json:"data"` +} diff --git a/server/service/vm/jiggler/jiggler.go b/server/service/vm/jiggler/jiggler.go index 19621a4..4cac43f 100644 --- a/server/service/vm/jiggler/jiggler.go +++ b/server/service/vm/jiggler/jiggler.go @@ -1,6 +1,7 @@ package jiggler import ( + "NanoKVM-Server/service/hid" "os" "strings" "sync" @@ -117,3 +118,17 @@ func (j *Jiggler) IsEnabled() bool { func (j *Jiggler) GetMode() string { return j.mode } + +func move(mode string) { + h := hid.GetHid() + + if mode == "absolute" { + h.WriteHid2([]byte{0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00}) + time.Sleep(100 * time.Millisecond) + h.WriteHid2([]byte{0x00, 0xff, 0x3f, 0xff, 0x3f, 0x00}) + } else { + h.WriteHid1([]byte{0x00, 0xa, 0xa, 0x00}) + time.Sleep(100 * time.Millisecond) + h.WriteHid1([]byte{0x00, 0xf6, 0xf6, 0x00}) + } +} diff --git a/server/service/vm/jiggler/mouse.go b/server/service/vm/jiggler/mouse.go deleted file mode 100644 index 7575088..0000000 --- a/server/service/vm/jiggler/mouse.go +++ /dev/null @@ -1,55 +0,0 @@ -package jiggler - -import ( - "os" - "time" - - log "github.com/sirupsen/logrus" -) - -func move(mode string) { - var ( - hid string - data [][]byte - ) - - if mode == "absolute" { - hid = "/dev/hidg2" - data = [][]byte{ - {0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00}, - {0x00, 0xff, 0x3f, 0xff, 0x3f, 0x00}, - } - } else { - hid = "/dev/hidg1" - data = [][]byte{ - {0x00, 0x0a, 0x0a, 0x00}, - {0x00, 0xf6, 0xf6, 0x00}, - } - } - - write(hid, data) -} - -func write(hid string, data [][]byte) { - file, err := os.OpenFile(hid, os.O_WRONLY, 0o666) - if err != nil { - log.Errorf("failed to open %s: %s", hid, err) - return - } - defer func() { - _ = file.Close() - }() - - for _, b := range data { - deadline := time.Now().Add(8 * time.Millisecond) - if err := file.SetWriteDeadline(deadline); err != nil { - log.Errorf("failed to set deadline: %s", err) - return - } - - if _, err := file.Write(b); err != nil { - log.Errorf("failed to write: %s", err) - return - } - } -} diff --git a/server/service/vm/mouse-jiggler.go b/server/service/vm/mouse_jiggler.go similarity index 100% rename from server/service/vm/mouse-jiggler.go rename to server/service/vm/mouse_jiggler.go diff --git a/server/service/vm/web-title.go b/server/service/vm/web_title.go similarity index 100% rename from server/service/vm/web-title.go rename to server/service/vm/web_title.go diff --git a/server/utils/move-file.go b/server/utils/move_file.go similarity index 100% rename from server/utils/move-file.go rename to server/utils/move_file.go diff --git a/web/package.json b/web/package.json index bed5178..ca97c7e 100644 --- a/web/package.json +++ b/web/package.json @@ -11,12 +11,12 @@ "preview": "vite preview" }, "dependencies": { - "@ant-design/icons": "^5.5.1", + "@ant-design/icons": "^5.6.1", "@xterm/addon-attach": "^0.11.0", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", - "antd": "^5.21.6", - "axios": "^1.8.4", + "antd": "^5.29.1", + "axios": "1.12.0", "clsx": "^2.1.1", "crypto-js": "^4.2.0", "i18next": "^23.16.4", @@ -38,18 +38,18 @@ "yocto-queue": "^1.2.1" }, "devDependencies": { - "@ianvs/prettier-plugin-sort-imports": "^4.3.1", + "@ianvs/prettier-plugin-sort-imports": "^4.7.0", "@types/crypto-js": "^4.2.2", "@types/js-cookie": "^3.0.6", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/semver": "^7.5.8", "@types/websocket": "^1.0.10", - "@typescript-eslint/eslint-plugin": "^8.19.1", - "@typescript-eslint/parser": "^8.19.1", - "@vitejs/plugin-react": "^4.3.3", + "@typescript-eslint/eslint-plugin": "^8.48.0", + "@typescript-eslint/parser": "^8.48.0", + "@vitejs/plugin-react": "^4.7.0", "autoprefixer": "^10.4.20", - "eslint": "^9.17.0", + "eslint": "^9.39.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.1.0", @@ -58,9 +58,9 @@ "postcss": "^8.4.47", "prettier": "^3.4.2", "prettier-plugin-tailwindcss": "^0.6.9", - "tailwindcss": "^3.4.14", + "tailwindcss": "^3.4.18", "typescript": "^5.6.3", - "vite": "^6.2.1", + "vite": "7.1.11", "vite-tsconfig-paths": "^4.3.2" }, "msw": { diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 36e5dbb..56aa94e 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@ant-design/icons': - specifier: ^5.5.1 - version: 5.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^5.6.1 + version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@xterm/addon-attach': specifier: ^0.11.0 version: 0.11.0(@xterm/xterm@5.5.0) @@ -21,11 +21,11 @@ importers: specifier: ^5.5.0 version: 5.5.0 antd: - specifier: ^5.21.6 - version: 5.21.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^5.29.1 + version: 5.29.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) axios: - specifier: ^1.8.4 - version: 1.8.4 + specifier: 1.12.0 + version: 1.12.0 clsx: specifier: ^2.1.1 version: 2.1.1 @@ -85,8 +85,8 @@ importers: version: 1.2.1 devDependencies: '@ianvs/prettier-plugin-sort-imports': - specifier: ^4.3.1 - version: 4.3.1(prettier@3.4.2) + specifier: ^4.7.0 + version: 4.7.0(prettier@3.4.2) '@types/crypto-js': specifier: ^4.2.2 version: 4.2.2 @@ -106,32 +106,32 @@ importers: specifier: ^1.0.10 version: 1.0.10 '@typescript-eslint/eslint-plugin': - specifier: ^8.19.1 - version: 8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) + specifier: ^8.48.0 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) '@typescript-eslint/parser': - specifier: ^8.19.1 - version: 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) + specifier: ^8.48.0 + version: 8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) '@vitejs/plugin-react': - specifier: ^4.3.3 - version: 4.3.3(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0)) + specifier: ^4.7.0 + version: 4.7.0(vite@7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0)) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.47) eslint: - specifier: ^9.17.0 - version: 9.17.0(jiti@1.21.6) + specifier: ^9.39.1 + version: 9.39.1(jiti@1.21.7) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.17.0(jiti@1.21.6)) + version: 9.1.0(eslint@9.39.1(jiti@1.21.7)) eslint-plugin-react: specifier: ^7.37.2 - version: 7.37.2(eslint@9.17.0(jiti@1.21.6)) + version: 7.37.2(eslint@9.39.1(jiti@1.21.7)) eslint-plugin-react-hooks: specifier: ^5.1.0 - version: 5.1.0(eslint@9.17.0(jiti@1.21.6)) + version: 5.1.0(eslint@9.39.1(jiti@1.21.7)) eslint-plugin-react-refresh: specifier: ^0.4.16 - version: 0.4.16(eslint@9.17.0(jiti@1.21.6)) + version: 0.4.16(eslint@9.39.1(jiti@1.21.7)) msw: specifier: ^2.6.0 version: 2.6.0(@types/node@22.9.0)(typescript@5.6.3) @@ -143,19 +143,19 @@ importers: version: 3.4.2 prettier-plugin-tailwindcss: specifier: ^0.6.9 - version: 0.6.9(@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.4.2))(prettier@3.4.2) + version: 0.6.9(@ianvs/prettier-plugin-sort-imports@4.7.0(prettier@3.4.2))(prettier@3.4.2) tailwindcss: - specifier: ^3.4.14 - version: 3.4.14 + specifier: ^3.4.18 + version: 3.4.18(yaml@2.6.0) typescript: specifier: ^5.6.3 version: 5.6.3 vite: - specifier: ^6.2.1 - version: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0) + specifier: 7.1.11 + version: 7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0) vite-tsconfig-paths: specifier: ^4.3.2 - 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)) + version: 4.3.2(typescript@5.6.3)(vite@7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0)) packages: @@ -163,21 +163,20 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@ant-design/colors@7.1.0': resolution: {integrity: sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==} - '@ant-design/cssinjs-utils@1.1.1': - resolution: {integrity: sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ==} + '@ant-design/colors@7.2.1': + resolution: {integrity: sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==} + + '@ant-design/cssinjs-utils@1.1.3': + resolution: {integrity: sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - '@ant-design/cssinjs@1.21.1': - resolution: {integrity: sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==} + '@ant-design/cssinjs@1.24.0': + resolution: {integrity: sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==} peerDependencies: react: '>=16.0.0' react-dom: '>=16.0.0' @@ -189,8 +188,8 @@ packages: '@ant-design/icons-svg@4.4.2': resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} - '@ant-design/icons@5.5.1': - resolution: {integrity: sha512-0UrM02MA2iDIgvLatWrj6YTCYe0F/cwXvVE0E2SqGrL7PZireQwgEKTKBisWpZyal5eXZLvuM98kju6YtYne8w==} + '@ant-design/icons@5.6.1': + resolution: {integrity: sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==} engines: {node: '>=8'} peerDependencies: react: '>=16.0.0' @@ -205,50 +204,70 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.2': - resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} '@babel/generator@7.26.2': resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} '@babel/parser@7.26.2': @@ -256,14 +275,19 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -276,14 +300,26 @@ packages: resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.25.9': resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.0': resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + '@bundled-es-modules/cookie@2.0.1': resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} @@ -453,8 +489,8 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -463,28 +499,32 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.19.1': - resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.9.1': - resolution: {integrity: sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.17.0': - resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.5': - resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.4': - resolution: {integrity: sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanfs/core@0.19.1': @@ -503,18 +543,27 @@ packages: resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@ianvs/prettier-plugin-sort-imports@4.3.1': - resolution: {integrity: sha512-ZHwbyjkANZOjaBm3ZosADD2OUYGFzQGxfy67HmGZU94mHqe7g1LCMA7YYKB1Cq+UTPCBqlAYapY0KXAjKEw8Sg==} + '@ianvs/prettier-plugin-sort-imports@4.7.0': + resolution: {integrity: sha512-soa2bPUJAFruLL4z/CnMfSEKGznm5ebz29fIa9PxYtu8HHyLKNE1NXAs6dylfw1jn/ilEIfO2oLLN6uAafb7DA==} peerDependencies: + '@prettier/plugin-oxc': ^0.0.4 '@vue/compiler-sfc': 2.7.x || 3.x - prettier: 2 || 3 + content-tag: ^4.0.0 + prettier: 2 || 3 || ^4.0.0-0 + prettier-plugin-ember-template-tag: ^2.1.0 peerDependenciesMeta: + '@prettier/plugin-oxc': + optional: true '@vue/compiler-sfc': optional: true + content-tag: + optional: true + prettier-plugin-ember-template-tag: + optional: true '@inquirer/confirm@5.0.1': resolution: {integrity: sha512-6ycMm7k7NUApiMGfVc32yIPp28iPKxhGRMqoNDiUjq2RyTAkbs5Fx0TdzBqhabcKvniDdAAvHCmsRjnNfTsogw==} @@ -536,14 +585,16 @@ packages: peerDependencies: '@types/node': '>=18' - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -555,9 +606,15 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@mswjs/interceptors@0.36.9': resolution: {integrity: sha512-mMRDUBwSNeCgjSMEWfjoh4Rm9fbyZ7xQ9SBq8eGHiiyRn1ieTip3pNEt0wxWVPPxR4i1Rv9bTkeEbkX7M4c15A==} engines: {node: '>=18'} @@ -583,10 +640,6 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} @@ -783,8 +836,8 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - '@rc-component/qrcode@1.0.0': - resolution: {integrity: sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==} + '@rc-component/qrcode@1.1.0': + resolution: {integrity: sha512-ABA80Yer0c6I2+moqNY0kF3Y1NxIT6wDP/EINIqbiRbfZKP1HtHpKMh8WuTXLgVGYsoWG2g9/n0PgM8KdnJb4Q==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' @@ -797,8 +850,8 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - '@rc-component/trigger@2.2.3': - resolution: {integrity: sha512-X1oFIpKoXAMXNDYCviOmTfuNuYxE4h5laBsyCqVAVMjNHxoF3/uiyA7XdegK1XbCvBbCZ6P6byWrEoDRpKL8+A==} + '@rc-component/trigger@2.3.0': + resolution: {integrity: sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' @@ -808,98 +861,116 @@ packages: resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==} engines: {node: '>=14.0.0'} - '@rollup/rollup-android-arm-eabi@4.34.9': - resolution: {integrity: sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==} + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.34.9': - resolution: {integrity: sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==} + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.34.9': - resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==} + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.9': - resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==} + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.34.9': - resolution: {integrity: sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==} + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.9': - resolution: {integrity: sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==} + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.34.9': - resolution: {integrity: sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.34.9': - resolution: {integrity: sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==} + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.34.9': - resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==} + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.34.9': - resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==} + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.34.9': - resolution: {integrity: sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==} + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': - resolution: {integrity: sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==} + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.34.9': - resolution: {integrity: sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==} + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.34.9': - resolution: {integrity: sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==} + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.34.9': - resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==} + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.34.9': - resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==} + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.34.9': - resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==} + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.9': - resolution: {integrity: sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==} + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.9': - resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==} + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} cpu: [x64] os: [win32] @@ -924,6 +995,9 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/js-cookie@3.0.6': resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} @@ -954,58 +1028,70 @@ packages: '@types/websocket@1.0.10': resolution: {integrity: sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww==} - '@typescript-eslint/eslint-plugin@8.19.1': - resolution: {integrity: sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==} + '@typescript-eslint/eslint-plugin@8.48.0': + resolution: {integrity: sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + '@typescript-eslint/parser': ^8.48.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.19.1': - resolution: {integrity: sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==} + '@typescript-eslint/parser@8.48.0': + resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.19.1': - resolution: {integrity: sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==} + '@typescript-eslint/project-service@8.48.0': + resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.48.0': + resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.19.1': - resolution: {integrity: sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==} + '@typescript-eslint/tsconfig-utils@8.48.0': + resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.48.0': + resolution: {integrity: sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.19.1': - resolution: {integrity: sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==} + '@typescript-eslint/types@8.48.0': + resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.19.1': - resolution: {integrity: sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==} + '@typescript-eslint/typescript-estree@8.48.0': + resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.19.1': - resolution: {integrity: sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==} + '@typescript-eslint/utils@8.48.0': + resolution: {integrity: sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.19.1': - resolution: {integrity: sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==} + '@typescript-eslint/visitor-keys@8.48.0': + resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@4.3.3': - resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==} + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 '@xterm/addon-attach@0.11.0': resolution: {integrity: sha512-JboCN0QAY6ZLY/SSB/Zl2cQ5zW1Eh4X3fH7BnuR1NB7xGRhzbqU2Npmpiw/3zFlxDaU88vtKzok44JKi2L2V2Q==} @@ -1025,8 +1111,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1041,20 +1127,12 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - antd@5.21.6: - resolution: {integrity: sha512-EviOde/VEu+OsIKH5t6YXTMmmNeg9R85m0W5zXAo+Np8Latg9q10691JvAqOTMpnrRmbdeKUQL1Krp69Bzbe/g==} + antd@5.29.1: + resolution: {integrity: sha512-TTFVbpKbyL6cPfEoKq6Ya3BIjTUr7uDW9+7Z+1oysRv1gpcN7kQ4luH8r/+rXXwz4n6BIz1iBJ1ezKCdsdNW0w==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' @@ -1084,9 +1162,6 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} - array-tree-filter@2.1.0: - resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} - array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -1121,21 +1196,25 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axios@1.8.4: - resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} + axios@1.12.0: + resolution: {integrity: sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + baseline-browser-mapping@2.8.31: + resolution: {integrity: sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==} + hasBin: true + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1146,10 +1225,19 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -1162,8 +1250,11 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001713: - resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} + caniuse-lite@1.0.30001756: + resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} + + caniuse-lite@1.0.30001757: + resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1241,6 +1332,9 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + d@1.0.2: resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} engines: {node: '>=0.12'} @@ -1277,6 +1371,15 @@ packages: supports-color: optional: true + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1305,8 +1408,12 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.260: + resolution: {integrity: sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==} electron-to-chromium@1.5.51: resolution: {integrity: sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==} @@ -1314,9 +1421,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - es-abstract@1.23.3: resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} @@ -1325,6 +1429,10 @@ packages: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} @@ -1337,10 +1445,18 @@ packages: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.3: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-shim-unscopables@1.0.2: resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} @@ -1395,20 +1511,20 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.17.0: - resolution: {integrity: sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1421,8 +1537,8 @@ packages: resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esquery@1.6.0: @@ -1450,8 +1566,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: @@ -1463,6 +1579,15 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -1494,12 +1619,8 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - - form-data@4.0.1: - resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} fraction.js@4.3.7: @@ -1532,10 +1653,18 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -1548,10 +1677,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -1570,6 +1695,10 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1595,6 +1724,10 @@ packages: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} @@ -1619,8 +1752,12 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} imurmurhash@0.1.4: @@ -1661,6 +1798,10 @@ packages: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-data-view@1.0.1: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} @@ -1755,11 +1896,8 @@ packages: resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} engines: {node: '>= 0.4'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jiti@1.21.6: - resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true jotai@2.10.1: @@ -1781,8 +1919,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsesc@3.0.2: @@ -1790,6 +1928,11 @@ packages: engines: {node: '>=6'} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -1818,12 +1961,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} lines-and-columns@1.2.4: @@ -1840,9 +1979,6 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -1854,6 +1990,10 @@ packages: matchmediaquery@0.4.2: resolution: {integrity: sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1877,10 +2017,6 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -1904,6 +2040,11 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1922,6 +2063,9 @@ packages: node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1977,9 +2121,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -1995,10 +2136,6 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - path-to-regexp@6.3.0: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} @@ -2009,12 +2146,16 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} - pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} possible-typed-array-names@1.0.0: @@ -2027,22 +2168,28 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true postcss-nested@6.2.0: @@ -2062,8 +2209,8 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2149,20 +2296,20 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - rc-cascader@3.28.2: - resolution: {integrity: sha512-8f+JgM83iLTvjgdkgU7GfI4qY8icXOBP0cGZjOdx2iJAkEe8ucobxDQAVE69UD/c3ehCxZlcgEHeD5hFmypbUw==} + rc-cascader@3.34.0: + resolution: {integrity: sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-checkbox@3.3.0: - resolution: {integrity: sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==} + rc-checkbox@3.5.0: + resolution: {integrity: sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-collapse@3.8.0: - resolution: {integrity: sha512-YVBkssrKPBG09TGfcWWGj8zJBYD9G3XuTy89t5iUmSXrIXEAnO1M+qjUxRW6b4Qi0+wNWG6MHJF/+US+nmIlzA==} + rc-collapse@3.9.0: + resolution: {integrity: sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' @@ -2173,82 +2320,82 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-drawer@7.2.0: - resolution: {integrity: sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==} + rc-drawer@7.3.0: + resolution: {integrity: sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-dropdown@4.2.0: - resolution: {integrity: sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==} + rc-dropdown@4.2.1: + resolution: {integrity: sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==} peerDependencies: react: '>=16.11.0' react-dom: '>=16.11.0' - rc-field-form@2.4.0: - resolution: {integrity: sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==} + rc-field-form@2.7.1: + resolution: {integrity: sha512-vKeSifSJ6HoLaAB+B8aq/Qgm8a3dyxROzCtKNCsBQgiverpc4kWDQihoUwzUj+zNWJOykwSY4dNX3QrGwtVb9A==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-image@7.11.0: - resolution: {integrity: sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==} + rc-image@7.12.0: + resolution: {integrity: sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-input-number@9.2.0: - resolution: {integrity: sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==} + rc-input-number@9.5.0: + resolution: {integrity: sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-input@1.6.3: - resolution: {integrity: sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==} + rc-input@1.8.0: + resolution: {integrity: sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==} peerDependencies: react: '>=16.0.0' react-dom: '>=16.0.0' - rc-mentions@2.16.1: - resolution: {integrity: sha512-GnhSTGP9Mtv6pqFFGQze44LlrtWOjHNrUUAcsdo9DnNAhN4pwVPEWy4z+2jpjkiGlJ3VoXdvMHcNDQdfI9fEaw==} + rc-mentions@2.20.0: + resolution: {integrity: sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-menu@9.15.1: - resolution: {integrity: sha512-UKporqU6LPfHnpPmtP6hdEK4iO5Q+b7BRv/uRpxdIyDGplZy9jwUjsnpev5bs3PQKB0H0n34WAPDfjAfn3kAPA==} + rc-menu@9.16.1: + resolution: {integrity: sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-motion@2.9.3: - resolution: {integrity: sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==} + rc-motion@2.9.5: + resolution: {integrity: sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-notification@5.6.2: - resolution: {integrity: sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g==} + rc-notification@5.6.4: + resolution: {integrity: sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-overflow@1.3.2: - resolution: {integrity: sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==} + rc-overflow@1.5.0: + resolution: {integrity: sha512-Lm/v9h0LymeUYJf0x39OveU52InkdRXqnn2aYXfWmo8WdOonIKB2kfau+GF0fWq6jPgtdO9yMqveGcK6aIhJmg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-pagination@4.3.0: - resolution: {integrity: sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g==} + rc-pagination@5.1.0: + resolution: {integrity: sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-picker@4.6.15: - resolution: {integrity: sha512-OWZ1yrMie+KN2uEUfYCfS4b2Vu6RC1FWwNI0s+qypsc3wRt7g+peuZKVIzXCTaJwyyZruo80+akPg2+GmyiJjw==} + rc-picker@4.11.3: + resolution: {integrity: sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==} engines: {node: '>=8.x'} peerDependencies: date-fns: '>= 2.x' @@ -2273,34 +2420,34 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-rate@2.13.0: - resolution: {integrity: sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==} + rc-rate@2.13.1: + resolution: {integrity: sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-resize-observer@1.4.0: - resolution: {integrity: sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==} + rc-resize-observer@1.4.3: + resolution: {integrity: sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-segmented@2.5.0: - resolution: {integrity: sha512-B28Fe3J9iUFOhFJET3RoXAPFJ2u47QvLSYcZWC4tFYNGPEjug5LAxEasZlA/PpAxhdOPqGWsGbSj7ftneukJnw==} + rc-segmented@2.7.0: + resolution: {integrity: sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==} peerDependencies: react: '>=16.0.0' react-dom: '>=16.0.0' - rc-select@14.15.2: - resolution: {integrity: sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw==} + rc-select@14.16.8: + resolution: {integrity: sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==} engines: {node: '>=8.x'} peerDependencies: react: '*' react-dom: '*' - rc-slider@11.1.7: - resolution: {integrity: sha512-ytYbZei81TX7otdC0QvoYD72XSlxvTihNth5OeZ6PMXyEDq/vHdWFulQmfDGyXK1NwKwSlKgpvINOa88uT5g2A==} + rc-slider@11.1.9: + resolution: {integrity: sha512-h8IknhzSh3FEM9u8ivkskh+Ef4Yo4JRIY2nj7MrH6GQmrwV6mcpJf5/4KgH5JaVI1H3E52yCdpOlVyGZIeph5A==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' @@ -2319,47 +2466,47 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-table@7.47.5: - resolution: {integrity: sha512-fzq+V9j/atbPIcvs3emuclaEoXulwQpIiJA6/7ey52j8+9cJ4P8DGmp4YzfUVDrb3qhgedcVeD6eRgUrokwVEQ==} + rc-table@7.54.0: + resolution: {integrity: sha512-/wDTkki6wBTjwylwAGjpLKYklKo9YgjZwAU77+7ME5mBoS32Q4nAwoqhA2lSge6fobLW3Tap6uc5xfwaL2p0Sw==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-tabs@15.3.0: - resolution: {integrity: sha512-lzE18r+zppT/jZWOAWS6ntdkDUKHOLJzqMi5UAij1LeKwOaQaupupAoI9Srn73GRzVpmGznkECMRrzkRusC40A==} + rc-tabs@15.7.0: + resolution: {integrity: sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-textarea@1.8.2: - resolution: {integrity: sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw==} + rc-textarea@1.10.2: + resolution: {integrity: sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-tooltip@6.2.1: - resolution: {integrity: sha512-rws0duD/3sHHsD905Nex7FvoUGy2UBQRhTkKxeEvr2FB+r21HsOxcDJI0TzyO8NHhnAA8ILr8pfbSBg5Jj5KBg==} + rc-tooltip@6.4.0: + resolution: {integrity: sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-tree-select@5.23.0: - resolution: {integrity: sha512-aQGi2tFSRw1WbXv0UVXPzHm09E0cSvUVZMLxQtMv3rnZZpNmdRXWrnd9QkLNlVH31F+X5rgghmdSFF3yZW0N9A==} + rc-tree-select@5.27.0: + resolution: {integrity: sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==} peerDependencies: react: '*' react-dom: '*' - rc-tree@5.9.0: - resolution: {integrity: sha512-CPrgOvm9d/9E+izTONKSngNzQdIEjMox2PBufWjS1wf7vxtvmCWzK1SlpHbRY6IaBfJIeZ+88RkcIevf729cRg==} + rc-tree@5.13.1: + resolution: {integrity: sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==} engines: {node: '>=10.x'} peerDependencies: react: '*' react-dom: '*' - rc-upload@4.8.1: - resolution: {integrity: sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==} + rc-upload@4.11.0: + resolution: {integrity: sha512-ZUyT//2JAehfHzjWowqROcwYJKnZkIUGWaTE/VogVrepSl7AFNbQf4+zGfX4zl9Vrj/Jm8scLO0R6UlPDKK4wA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' @@ -2370,8 +2517,14 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - rc-virtual-list@3.15.0: - resolution: {integrity: sha512-dF2YQztqrU3ijAeWOqscTshCEr7vpimzSqAVjO1AyAmaqcHulaXpnGR0ptK5PXfxTUy48VkJOiglMIxlkYGs0w==} + rc-util@5.44.4: + resolution: {integrity: sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-virtual-list@3.19.2: + resolution: {integrity: sha512-Ys6NcjwGkuwkeaWBDqfI3xWuZ7rDiQXlH1o2zLfFzATfEgXcqpk8CkgMfbJD81McqjcJVez25a3kPxCR807evA==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' @@ -2420,8 +2573,8 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} react-remove-scroll-bar@2.3.6: @@ -2515,8 +2668,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} hasBin: true resolve@2.0.0-next.5: @@ -2527,8 +2681,8 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.34.9: - resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==} + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2606,10 +2760,6 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} @@ -2632,19 +2782,15 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - stylis@4.3.4: - resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} - sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true @@ -2656,8 +2802,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwindcss@3.4.14: - resolution: {integrity: sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==} + tailwindcss@3.4.18: + resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -2672,6 +2818,10 @@ packages: resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2683,8 +2833,8 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2760,6 +2910,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2807,19 +2963,19 @@ packages: vite: optional: true - vite@6.2.1: - resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@7.1.11: + resolution: {integrity: sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': ^20.19.0 || >=22.12.0 jiti: '>=1.21.0' - less: '*' + less: ^4.0.0 lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 @@ -2887,10 +3043,6 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2931,34 +3083,33 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - '@ant-design/colors@7.1.0': dependencies: '@ctrl/tinycolor': 3.6.1 - '@ant-design/cssinjs-utils@1.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@ant-design/colors@7.2.1': dependencies: - '@ant-design/cssinjs': 1.21.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/fast-color': 2.0.6 + + '@ant-design/cssinjs-utils@1.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/cssinjs': 1.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@babel/runtime': 7.26.0 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@ant-design/cssinjs@1.21.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@ant-design/cssinjs@1.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/hash': 0.8.0 '@emotion/unitless': 0.7.5 classnames: 2.5.1 - csstype: 3.1.3 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + csstype: 3.2.3 + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - stylis: 4.3.4 + stylis: 4.3.6 '@ant-design/fast-color@2.0.6': dependencies: @@ -2966,7 +3117,7 @@ snapshots: '@ant-design/icons-svg@4.4.2': {} - '@ant-design/icons@5.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@ant-design/icons@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@ant-design/colors': 7.1.0 '@ant-design/icons-svg': 4.4.2 @@ -2991,22 +3142,28 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.2': {} - - '@babel/core@7.26.0': + '@babel/code-frame@7.27.1': dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.5': {} + + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.3.7 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3021,56 +3178,74 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 - '@babel/helper-compilation-targets@7.25.9': + '@babel/generator@7.28.5': dependencies: - '@babel/compat-data': 7.26.2 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.0 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.25.9': + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.25.9': {} + '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-option@7.25.9': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helpers@7.26.0': + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 '@babel/parser@7.26.2': dependencies: '@babel/types': 7.26.0 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': + '@babel/parser@7.28.5': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/types': 7.28.5 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 '@babel/runtime@7.26.0': dependencies: @@ -3082,6 +3257,12 @@ snapshots: '@babel/parser': 7.26.2 '@babel/types': 7.26.0 + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@babel/traverse@7.25.9': dependencies: '@babel/code-frame': 7.26.2 @@ -3094,11 +3275,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.26.0': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@bundled-es-modules/cookie@2.0.1': dependencies: cookie: 0.7.2 @@ -3193,45 +3391,50 @@ snapshots: '@esbuild/win32-x64@0.25.0': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(jiti@1.21.6))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@1.21.7))': dependencies: - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.19.1': + '@eslint/config-array@0.21.1': dependencies: - '@eslint/object-schema': 2.1.5 + '@eslint/object-schema': 2.1.7 debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/core@0.9.1': + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.2.0': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.3.7 - espree: 10.3.0 + espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 + import-fresh: 3.3.1 + js-yaml: 4.1.1 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.17.0': {} + '@eslint/js@9.39.1': {} - '@eslint/object-schema@2.1.5': {} + '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.2.4': + '@eslint/plugin-kit@0.4.1': dependencies: + '@eslint/core': 0.17.0 levn: 0.4.1 '@humanfs/core@0.19.1': {} @@ -3245,11 +3448,10 @@ snapshots: '@humanwhocodes/retry@0.3.1': {} - '@humanwhocodes/retry@0.4.1': {} + '@humanwhocodes/retry@0.4.3': {} - '@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.4.2)': + '@ianvs/prettier-plugin-sort-imports@4.7.0(prettier@3.4.2)': dependencies: - '@babel/core': 7.26.0 '@babel/generator': 7.26.2 '@babel/parser': 7.26.2 '@babel/traverse': 7.25.9 @@ -3285,14 +3487,10 @@ snapshots: dependencies: '@types/node': 22.9.0 - '@isaacs/cliui@8.0.2': + '@jridgewell/gen-mapping@0.3.13': dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/gen-mapping@0.3.5': dependencies: @@ -3300,17 +3498,29 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@mswjs/interceptors@0.36.9': dependencies: '@open-draft/deferred-promise': 2.2.0 @@ -3341,9 +3551,6 @@ snapshots: '@open-draft/until@2.1.0': {} - '@pkgjs/parseargs@0.11.0': - optional: true - '@radix-ui/primitive@1.1.0': {} '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.12)(react@18.3.1)': @@ -3488,14 +3695,14 @@ snapshots: '@ant-design/fast-color': 2.0.6 '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@rc-component/context@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3507,7 +3714,7 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3515,15 +3722,14 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@rc-component/qrcode@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@rc-component/qrcode@1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3531,80 +3737,91 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@rc-component/trigger@2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@rc-component/trigger@2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@remix-run/router@1.20.0': {} - '@rollup/rollup-android-arm-eabi@4.34.9': + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.53.3': optional: true - '@rollup/rollup-android-arm64@4.34.9': + '@rollup/rollup-android-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-arm64@4.34.9': + '@rollup/rollup-darwin-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-x64@4.34.9': + '@rollup/rollup-darwin-x64@4.53.3': optional: true - '@rollup/rollup-freebsd-arm64@4.34.9': + '@rollup/rollup-freebsd-arm64@4.53.3': optional: true - '@rollup/rollup-freebsd-x64@4.34.9': + '@rollup/rollup-freebsd-x64@4.53.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.9': + '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.9': + '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.9': + '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.9': + '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.9': + '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.9': + '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-musl@4.34.9': + '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.9': + '@rollup/rollup-linux-x64-musl@4.53.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.9': + '@rollup/rollup-openharmony-arm64@4.53.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.9': + '@rollup/rollup-win32-arm64-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.53.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true '@types/babel__core@7.20.5': @@ -3634,6 +3851,8 @@ snapshots: '@types/estree@1.0.6': {} + '@types/estree@1.0.8': {} + '@types/js-cookie@3.0.6': {} '@types/json-schema@7.0.15': {} @@ -3663,91 +3882,107 @@ snapshots: dependencies: '@types/node': 22.9.0 - '@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.19.1 - '@typescript-eslint/type-utils': 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) - '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.19.1 - eslint: 9.17.0(jiti@1.21.6) + '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.48.0 + eslint: 9.39.1(jiti@1.21.7) graphemer: 1.4.0 - ignore: 5.3.2 + ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.0.0(typescript@5.6.3) + ts-api-utils: 2.1.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3)': + '@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3)': dependencies: - '@typescript-eslint/scope-manager': 8.19.1 - '@typescript-eslint/types': 8.19.1 - '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.19.1 + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.48.0 debug: 4.3.7 - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.19.1': + '@typescript-eslint/project-service@8.48.0(typescript@5.6.3)': dependencies: - '@typescript-eslint/types': 8.19.1 - '@typescript-eslint/visitor-keys': 8.19.1 - - '@typescript-eslint/type-utils@8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.6.3) - '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.6.3) + '@typescript-eslint/types': 8.48.0 debug: 4.3.7 - eslint: 9.17.0(jiti@1.21.6) - ts-api-utils: 2.0.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.19.1': {} - - '@typescript-eslint/typescript-estree@8.19.1(typescript@5.6.3)': + '@typescript-eslint/scope-manager@8.48.0': dependencies: - '@typescript-eslint/types': 8.19.1 - '@typescript-eslint/visitor-keys': 8.19.1 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 + + '@typescript-eslint/tsconfig-utils@8.48.0(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + + '@typescript-eslint/type-utils@8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.6.3) + '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3) + debug: 4.4.3 + eslint: 9.39.1(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.48.0': {} + + '@typescript-eslint/typescript-estree@8.48.0(typescript@5.6.3)': + dependencies: + '@typescript-eslint/project-service': 8.48.0(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.6.3) + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 2.0.0(typescript@5.6.3) + tinyglobby: 0.2.15 + ts-api-utils: 2.1.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.19.1(eslint@9.17.0(jiti@1.21.6))(typescript@5.6.3)': + '@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.6.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@1.21.6)) - '@typescript-eslint/scope-manager': 8.19.1 - '@typescript-eslint/types': 8.19.1 - '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.6.3) - eslint: 9.17.0(jiti@1.21.6) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.6.3) + eslint: 9.39.1(jiti@1.21.7) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.19.1': + '@typescript-eslint/visitor-keys@8.48.0': dependencies: - '@typescript-eslint/types': 8.19.1 - eslint-visitor-keys: 4.2.0 + '@typescript-eslint/types': 8.48.0 + eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.3.3(vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0))': + '@vitejs/plugin-react@4.7.0(vite@7.1.11(@types/node@22.9.0)(jiti@1.21.7)(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) + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) + '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0) + react-refresh: 0.17.0 + vite: 7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0) transitivePeerDependencies: - supports-color @@ -3761,11 +3996,11 @@ snapshots: '@xterm/xterm@5.5.0': {} - acorn-jsx@5.3.2(acorn@8.14.0): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.0 + acorn: 8.15.0 - acorn@8.14.0: {} + acorn@8.15.0: {} ajv@6.12.6: dependencies: @@ -3780,63 +4015,59 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} - - antd@5.21.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + antd@5.29.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@ant-design/colors': 7.1.0 - '@ant-design/cssinjs': 1.21.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ant-design/cssinjs-utils': 1.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ant-design/icons': 5.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/colors': 7.2.1 + '@ant-design/cssinjs': 1.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/cssinjs-utils': 1.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@ant-design/fast-color': 2.0.6 + '@ant-design/icons': 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@ant-design/react-slick': 1.1.2(react@18.3.1) '@babel/runtime': 7.26.0 - '@ctrl/tinycolor': 3.6.1 '@rc-component/color-picker': 2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@rc-component/mutate-observer': 1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/qrcode': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/qrcode': 1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@rc-component/tour': 1.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 copy-to-clipboard: 3.3.3 dayjs: 1.11.13 - rc-cascader: 3.28.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-checkbox: 3.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-collapse: 3.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-cascader: 3.34.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-checkbox: 3.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-collapse: 3.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-dialog: 9.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-drawer: 7.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-dropdown: 4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-field-form: 2.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-image: 7.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-input: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-input-number: 9.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-mentions: 2.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-notification: 5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-pagination: 4.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-picker: 4.6.15(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-drawer: 7.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-dropdown: 4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-field-form: 2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-image: 7.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-input-number: 9.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-mentions: 2.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-menu: 9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-notification: 5.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-pagination: 5.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-picker: 4.11.3(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-progress: 4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-rate: 2.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-segmented: 2.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-select: 14.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-slider: 11.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-rate: 2.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-segmented: 2.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-select: 14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-slider: 11.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-steps: 6.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-switch: 4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-table: 7.47.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tabs: 15.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-textarea: 1.8.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tooltip: 6.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree-select: 5.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-upload: 4.8.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-table: 7.54.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tabs: 15.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-textarea: 1.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tooltip: 6.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tree: 5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tree-select: 5.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-upload: 4.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 @@ -3875,8 +4106,6 @@ snapshots: get-intrinsic: 1.2.4 is-string: 1.0.7 - array-tree-filter@2.1.0: {} - array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.7 @@ -3924,7 +4153,7 @@ snapshots: autoprefixer@10.4.20(postcss@8.4.47): dependencies: browserslist: 4.24.2 - caniuse-lite: 1.0.30001713 + caniuse-lite: 1.0.30001756 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -3935,24 +4164,26 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 - axios@1.8.4: + axios@1.12.0: dependencies: follow-redirects: 1.15.9 - form-data: 4.0.1 + form-data: 4.0.5 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug balanced-match@1.0.2: {} + baseline-browser-mapping@2.8.31: {} + binary-extensions@2.3.0: {} - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -3962,15 +4193,28 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001713 + caniuse-lite: 1.0.30001756 electron-to-chromium: 1.5.51 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) + browserslist@4.28.0: + dependencies: + baseline-browser-mapping: 2.8.31 + caniuse-lite: 1.0.30001757 + electron-to-chromium: 1.5.260 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.28.0) + bufferutil@4.0.8: dependencies: node-gyp-build: 4.8.2 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -3983,7 +4227,9 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001713: {} + caniuse-lite@1.0.30001756: {} + + caniuse-lite@1.0.30001757: {} chalk@4.1.2: dependencies: @@ -4054,6 +4300,8 @@ snapshots: csstype@3.1.3: {} + csstype@3.2.3: {} + d@1.0.2: dependencies: es5-ext: 0.10.64 @@ -4087,6 +4335,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + deep-is@0.1.4: {} define-data-property@1.1.4: @@ -4113,14 +4365,18 @@ snapshots: dependencies: esutils: 2.0.3 - eastasianwidth@0.2.0: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.260: {} electron-to-chromium@1.5.51: {} emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -4174,6 +4430,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} + es-errors@1.3.0: {} es-iterator-helpers@1.2.0: @@ -4198,12 +4456,23 @@ snapshots: dependencies: es-errors: 1.3.0 + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.2 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + es-shim-unscopables@1.0.2: dependencies: hasown: 2.0.2 @@ -4264,19 +4533,19 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@9.1.0(eslint@9.17.0(jiti@1.21.6)): + eslint-config-prettier@9.1.0(eslint@9.39.1(jiti@1.21.7)): dependencies: - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) - eslint-plugin-react-hooks@5.1.0(eslint@9.17.0(jiti@1.21.6)): + eslint-plugin-react-hooks@5.1.0(eslint@9.39.1(jiti@1.21.7)): dependencies: - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) - eslint-plugin-react-refresh@0.4.16(eslint@9.17.0(jiti@1.21.6)): + eslint-plugin-react-refresh@0.4.16(eslint@9.39.1(jiti@1.21.7)): dependencies: - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) - eslint-plugin-react@7.37.2(eslint@9.17.0(jiti@1.21.6)): + eslint-plugin-react@7.37.2(eslint@9.39.1(jiti@1.21.7)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -4284,7 +4553,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.0 - eslint: 9.17.0(jiti@1.21.6) + eslint: 9.39.1(jiti@1.21.7) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -4298,37 +4567,37 @@ snapshots: string.prototype.matchall: 4.0.11 string.prototype.repeat: 1.0.0 - eslint-scope@8.2.0: + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.0: {} + eslint-visitor-keys@4.2.1: {} - eslint@9.17.0(jiti@1.21.6): + eslint@9.39.1(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@1.21.6)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.1 - '@eslint/core': 0.9.1 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.17.0 - '@eslint/plugin-kit': 0.2.4 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 + '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.3.7 escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -4344,7 +4613,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 1.21.6 + jiti: 1.21.7 transitivePeerDependencies: - supports-color @@ -4355,11 +4624,11 @@ snapshots: event-emitter: 0.3.5 type: 2.7.3 - espree@10.3.0: + espree@10.4.0: dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 esquery@1.6.0: dependencies: @@ -4384,7 +4653,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-glob@3.3.2: + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 @@ -4400,6 +4669,10 @@ snapshots: dependencies: reusify: 1.0.4 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -4426,15 +4699,12 @@ snapshots: dependencies: is-callable: 1.2.7 - foreground-child@3.3.0: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data@4.0.1: + form-data@4.0.5: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 mime-types: 2.1.35 fraction.js@4.3.7: {} @@ -4465,8 +4735,26 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + get-nonce@1.0.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 @@ -4481,15 +4769,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.4.5: - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - globals@11.12.0: {} globals@14.0.0: {} @@ -4505,6 +4784,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + gopd@1.2.0: {} + graphemer@1.4.0: {} graphql@16.9.0: {} @@ -4521,6 +4802,8 @@ snapshots: has-symbols@1.0.3: {} + has-symbols@1.1.0: {} + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 @@ -4543,7 +4826,9 @@ snapshots: ignore@5.3.2: {} - import-fresh@3.3.0: + ignore@7.0.5: {} + + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 @@ -4588,6 +4873,10 @@ snapshots: dependencies: hasown: 2.0.2 + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 @@ -4672,13 +4961,7 @@ snapshots: reflect.getprototypeof: 1.0.6 set-function-name: 2.0.2 - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jiti@1.21.6: {} + jiti@1.21.7: {} jotai@2.10.1(@types/react@18.3.12)(react@18.3.1): optionalDependencies: @@ -4689,12 +4972,14 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 jsesc@3.0.2: {} + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} @@ -4723,9 +5008,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@2.1.0: {} - - lilconfig@3.1.2: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -4739,8 +5022,6 @@ snapshots: dependencies: js-tokens: 4.0.0 - lru-cache@10.4.3: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -4753,6 +5034,8 @@ snapshots: dependencies: css-mediaquery: 0.1.2 + math-intrinsics@1.1.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -4768,13 +5051,11 @@ snapshots: minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 1.1.12 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 - - minipass@7.1.2: {} + brace-expansion: 2.0.2 ms@2.0.0: {} @@ -4813,6 +5094,8 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + nanoid@3.3.11: {} + nanoid@3.3.8: {} natural-compare@1.4.0: {} @@ -4823,6 +5106,8 @@ snapshots: node-releases@2.0.18: {} + node-releases@2.0.27: {} + normalize-path@3.0.0: {} normalize-range@0.1.2: {} @@ -4880,8 +5165,6 @@ snapshots: dependencies: p-limit: 3.1.0 - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -4892,20 +5175,17 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - path-to-regexp@6.3.0: {} picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.3: {} + pify@2.3.0: {} - pirates@4.0.6: {} + pirates@4.0.7: {} possible-typed-array-names@1.0.0: {} @@ -4914,19 +5194,20 @@ snapshots: postcss: 8.4.47 postcss-value-parser: 4.2.0 read-cache: 1.0.0 - resolve: 1.22.8 + resolve: 1.22.11 - postcss-js@4.0.1(postcss@8.4.47): + postcss-js@4.1.0(postcss@8.4.47): dependencies: camelcase-css: 2.0.1 postcss: 8.4.47 - postcss-load-config@4.0.2(postcss@8.4.47): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.4.47)(yaml@2.6.0): dependencies: - lilconfig: 3.1.2 - yaml: 2.6.0 + lilconfig: 3.1.3 optionalDependencies: + jiti: 1.21.7 postcss: 8.4.47 + yaml: 2.6.0 postcss-nested@6.2.0(postcss@8.4.47): dependencies: @@ -4946,19 +5227,19 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.3: + postcss@8.5.6: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 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): + prettier-plugin-tailwindcss@0.6.9(@ianvs/prettier-plugin-sort-imports@4.7.0(prettier@3.4.2))(prettier@3.4.2): dependencies: prettier: 3.4.2 optionalDependencies: - '@ianvs/prettier-plugin-sort-imports': 4.3.1(prettier@3.4.2) + '@ianvs/prettier-plugin-sort-imports': 4.7.0(prettier@3.4.2) prettier@3.4.2: {} @@ -4978,31 +5259,30 @@ snapshots: queue-microtask@1.2.3: {} - rc-cascader@3.28.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-cascader@3.34.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - array-tree-filter: 2.1.0 classnames: 2.5.1 - rc-select: 14.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-select: 14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tree: 5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-checkbox@3.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-checkbox@3.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-collapse@3.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-collapse@3.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5011,132 +5291,132 @@ snapshots: '@babel/runtime': 7.26.0 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-drawer@7.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-drawer@7.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-dropdown@4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-dropdown@4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-field-form@2.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 '@rc-component/async-validator': 5.0.4 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-image@7.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-image@7.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-dialog: 9.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-input-number@9.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-input-number@9.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 '@rc-component/mini-decimal': 1.1.0 classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-input@1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-input@1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-mentions@2.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-mentions@2.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-textarea: 1.8.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-menu: 9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-textarea: 1.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-menu@9.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-menu@9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-overflow: 1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-motion@2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-motion@2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-notification@5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-notification@5.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-overflow@1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-overflow@1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-pagination@4.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-pagination@5.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-picker@4.6.15(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-picker@4.11.3(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-overflow: 1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: @@ -5146,53 +5426,53 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-rate@2.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-rate@2.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-resize-observer@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-resize-observer@1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) resize-observer-polyfill: 1.5.1 - rc-segmented@2.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-segmented@2.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-select@14.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-select@14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-overflow: 1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-virtual-list: 3.19.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-slider@11.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-slider@11.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5200,7 +5480,7 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5208,76 +5488,77 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-table@7.47.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-table@7.54.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 '@rc-component/context': 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-virtual-list: 3.19.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-tabs@15.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-tabs@15.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-dropdown: 4.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-menu: 9.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-dropdown: 4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-menu: 9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-textarea@1.8.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-textarea@1.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-tooltip@6.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-tooltip@6.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 - '@rc-component/trigger': 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rc-component/trigger': 2.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-tree-select@5.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-tree-select@5.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-select: 14.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-select: 14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tree: 5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-tree@5.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-tree@5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-motion: 2.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-virtual-list: 3.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-virtual-list: 3.19.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - rc-upload@4.8.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-upload@4.11.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5288,12 +5569,19 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - rc-virtual-list@3.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + rc-util@5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.26.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 18.3.1 + + rc-virtual-list@3.19.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5337,7 +5625,7 @@ snapshots: react-is@18.3.1: {} - react-refresh@0.14.2: {} + react-refresh@0.17.0: {} react-remove-scroll-bar@2.3.6(@types/react@18.3.12)(react@18.3.1): dependencies: @@ -5431,9 +5719,9 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.8: + resolve@1.22.11: dependencies: - is-core-module: 2.15.1 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -5445,29 +5733,32 @@ snapshots: reusify@1.0.4: {} - rollup@4.34.9: + rollup@4.53.3: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 optionalDependencies: - '@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 + '@rollup/rollup-android-arm-eabi': 4.53.3 + '@rollup/rollup-android-arm64': 4.53.3 + '@rollup/rollup-darwin-arm64': 4.53.3 + '@rollup/rollup-darwin-x64': 4.53.3 + '@rollup/rollup-freebsd-arm64': 4.53.3 + '@rollup/rollup-freebsd-x64': 4.53.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 + '@rollup/rollup-linux-arm64-musl': 4.53.3 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 + '@rollup/rollup-linux-x64-gnu': 4.53.3 + '@rollup/rollup-linux-x64-musl': 4.53.3 + '@rollup/rollup-openharmony-arm64': 4.53.3 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 + '@rollup/rollup-win32-x64-gnu': 4.53.3 + '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5548,12 +5839,6 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.7 @@ -5597,22 +5882,18 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-json-comments@3.1.1: {} - stylis@4.3.4: {} + stylis@4.3.6: {} - sucrase@3.35.0: + sucrase@3.35.1: dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 - glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 - pirates: 4.0.6 + pirates: 4.0.7 + tinyglobby: 0.2.15 ts-interface-checker: 0.1.13 supports-color@7.2.0: @@ -5621,32 +5902,33 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwindcss@3.4.14: + tailwindcss@3.4.18(yaml@2.6.0): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 chokidar: 3.6.0 didyoumean: 1.2.2 dlv: 1.1.3 - fast-glob: 3.3.2 + fast-glob: 3.3.3 glob-parent: 6.0.2 is-glob: 4.0.3 - jiti: 1.21.6 - lilconfig: 2.1.0 + jiti: 1.21.7 + lilconfig: 3.1.3 micromatch: 4.0.8 normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 postcss: 8.4.47 postcss-import: 15.1.0(postcss@8.4.47) - postcss-js: 4.0.1(postcss@8.4.47) - postcss-load-config: 4.0.2(postcss@8.4.47) + postcss-js: 4.1.0(postcss@8.4.47) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.4.47)(yaml@2.6.0) postcss-nested: 6.2.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 - resolve: 1.22.8 - sucrase: 3.35.0 + resolve: 1.22.11 + sucrase: 3.35.1 transitivePeerDependencies: - - ts-node + - tsx + - yaml thenify-all@1.6.0: dependencies: @@ -5658,6 +5940,11 @@ snapshots: throttle-debounce@5.0.2: {} + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -5671,7 +5958,7 @@ snapshots: universalify: 0.2.0 url-parse: 1.5.10 - ts-api-utils@2.0.0(typescript@5.6.3): + ts-api-utils@2.1.0(typescript@5.6.3): dependencies: typescript: 5.6.3 @@ -5748,6 +6035,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.1.4(browserslist@4.28.0): + dependencies: + browserslist: 4.28.0 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -5787,26 +6080,29 @@ snapshots: - '@types/react' - '@types/react-dom' - 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)): + vite-tsconfig-paths@4.3.2(typescript@5.6.3)(vite@7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.6.3) optionalDependencies: - vite: 6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0) + vite: 7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0) transitivePeerDependencies: - supports-color - typescript - vite@6.2.1(@types/node@22.9.0)(jiti@1.21.6)(yaml@2.6.0): + vite@7.1.11(@types/node@22.9.0)(jiti@1.21.7)(yaml@2.6.0): dependencies: esbuild: 0.25.0 - postcss: 8.5.3 - rollup: 4.34.9 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.3 + tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.9.0 fsevents: 2.3.3 - jiti: 1.21.6 + jiti: 1.21.7 yaml: 2.6.0 void-elements@3.1.0: {} @@ -5878,19 +6174,14 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - y18n@5.0.8: {} yaeti@0.0.6: {} yallist@3.1.1: {} - yaml@2.6.0: {} + yaml@2.6.0: + optional: true yargs-parser@21.1.1: {} diff --git a/web/src/api/application.ts b/web/src/api/application.ts index 4c69108..f3192ac 100644 --- a/web/src/api/application.ts +++ b/web/src/api/application.ts @@ -27,10 +27,3 @@ export function getPreviewUpdates() { return http.get('/api/application/preview'); } -export function getSettingsDisabledItems() { - return http.get('/api/application/settings/disabled-items'); -} - -export function getMenuDisableItems(){ - return http.get("/api/application/menu/disabled-items") -} diff --git a/web/src/api/storage.ts b/web/src/api/storage.ts index 9f6c1b8..250affe 100644 --- a/web/src/api/storage.ts +++ b/web/src/api/storage.ts @@ -23,3 +23,10 @@ export function mountImage(file?: string, cdrom?: boolean) { export function getCdRom() { return http.get('/api/storage/cdrom'); } + +export function deleteImage(file: string) { + const data = { + file + }; + return http.post('/api/storage/image/delete', data); +} diff --git a/web/src/i18n/locales/en.ts b/web/src/i18n/locales/en.ts index e9fa4c6..286b692 100644 --- a/web/src/i18n/locales/en.ts +++ b/web/src/i18n/locales/en.ts @@ -69,21 +69,15 @@ const en = { keyboard: { title: 'Keyboard', paste: 'Paste', - tips: 'Server keyboard layout', + tips: 'Only standard keyboard letters and symbols are supported', placeholder: 'Please input', submit: 'Submit', virtual: 'Keyboard', ctrlaltdel: 'Ctrl+Alt+Del', readClipboard: 'Read from Clipboard', - clipboardHint: 'Click to paste from your browser clipboard', - clipboardNotSupported: 'Clipboard API is not supported in this browser', - clipboardEmpty: 'Clipboard is empty', - clipboardRead: 'Clipboard content loaded', clipboardPermissionDenied: 'Clipboard permission denied. Please allow clipboard access in your browser.', clipboardReadError: 'Failed to read clipboard', - clipboardTooLong: 'Clipboard content exceeds 1024 characters', - nonAsciiError: 'Only ASCII characters are supported', dropdownEnglish: 'English', dropdownGerman: 'German' }, @@ -118,11 +112,18 @@ const en = { title: 'Images', loading: 'Loading...', empty: 'Nothing Found', - cdrom: 'Mount the image in CD-ROM mode', - mountFailed: 'Mount Failed', + mountMode: 'Mount mode', + mountFailed: 'Mount failed', mountDesc: - "In some systems, it's necessary to eject the virtual disk on the remote host before mounting the image.", + 'On some systems, you need to eject the virtual disk from the remote host before mounting the image.', + unmountFailed: 'Unmount failed', + unmountDesc: + 'On some systems, you need to manually eject from the remote host before unmounting the image.', refresh: 'Refresh the image list', + attention: 'Attention', + deleteConfirm: 'Are you sure you want to delete this image?', + okBtn: 'Yes', + cancelBtn: 'No', tips: { title: 'How to upload', usb1: 'Connect the NanoKVM to your computer via USB.', @@ -290,8 +291,11 @@ 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 75MB if using Tailscale. A Tailscale restart is required for the change to take effect.", - disable: 'Disable' + tip: 'When memory usage exceeds the limit, garbage collection is performed more aggressively to attempt to free up memory. A Tailscale restart is required for the change to take effect.' + }, + swap: { + title: 'Swap memory', + tip: 'If issues persist after enabling memory optimization, try enabling swap memory. This sets the swap file size to 256MB by default, which can be adjusted in "Settings > Device".' }, restart: 'Restart Tailscale?', stop: 'Stop Tailscale?', @@ -308,6 +312,8 @@ const en = { upTailscale: 'Upload tailscale to NanoKVM directory /usr/bin/', upTailscaled: 'Upload tailscaled to NanoKVM directory /usr/sbin/', refresh: 'Refresh current page', + notRunning: 'Tailscale is not running. Please start it to continue.', + run: 'Start', notLogin: 'The device has not been bound yet. Please login and bind this device to your account.', urlPeriod: 'This url is valid for 10 minutes', @@ -320,6 +326,7 @@ const en = { logout: 'Logout', logoutDesc: 'Are you sure you want to logout?', uninstall: 'Uninstall Tailscale', + uninstallDesc: 'Are you sure you want to uninstall Tailscale?', okBtn: 'Yes', cancelBtn: 'No' }, diff --git a/web/src/i18n/locales/zh.ts b/web/src/i18n/locales/zh.ts index eea448d..cbf0c06 100644 --- a/web/src/i18n/locales/zh.ts +++ b/web/src/i18n/locales/zh.ts @@ -104,9 +104,16 @@ const zh = { title: '镜像', loading: '加载中', empty: '无镜像文件', - cdrom: '以 CD-ROM 模式挂载镜像', + mountMode: '挂载模式', mountFailed: '挂载失败', mountDesc: '在某些系统中,需要在远程主机中弹出虚拟硬盘后再挂载镜像。', + unmountFailed: '卸载失败', + unmountDesc: '在某些系统中,需要在远程主机中手动弹出后再卸载镜像。', + refresh: '刷新镜像列表', + attention: '注意', + deleteConfirm: '确定要删除该镜像吗?', + okBtn: '确定', + cancelBtn: '取消', tips: { title: '如何上传', usb1: '将 NanoKVM 通过 USB 连接到你的电脑;', @@ -256,8 +263,11 @@ const zh = { title: 'Tailscale', memory: { title: '内存优化', - tip: '当内存占用超过限制时,会更积极地执行垃圾回收来尝试释放内存。如果使用 Tailscale 推荐设置为 50MB,需重启 Tailscale 后生效。', - disable: '关闭' + tip: '当内存占用超过限制时,会更积极地执行垃圾回收来尝试释放内存。需重启 Tailscale 后生效。' + }, + swap: { + title: '交换内存', + tip: '如果启用内存优化后依然存在问题,可以尝试开启交换内存。启用后会将交换文件设置为256MB,可以在「设置 - 设备」中修改该选项。' }, restart: '取定要重启 Tailscale 吗?', stop: '确定要停止 Tailscale 吗?', @@ -274,6 +284,8 @@ const zh = { upTailscale: '将 tailscale 文件上传到 /usr/bin/ 目录', upTailscaled: '将 tailscaled 文件上传到 /usr/sbin/ 目录', refresh: '刷新页面', + notRunning: 'Tailscale 尚未运行,请先执行启动操作', + run: '启动', notLogin: '该设备尚未绑定,请点击登录并将这台设备绑定到您的账号。', urlPeriod: '该链接10分钟内有效', login: '登录', @@ -285,6 +297,7 @@ const zh = { logout: '退出', logoutDesc: '确定要退出吗?', uninstall: '卸载 Tailscale', + uninstallDesc: '确定要卸载 Tailscale 吗?', reboot: '重启', rebootDesc: '你确定要重启 NanoKVM 吗?', okBtn: '确认', diff --git a/web/src/jotai/settings.ts b/web/src/jotai/settings.ts index 6b79508..82f9e49 100644 --- a/web/src/jotai/settings.ts +++ b/web/src/jotai/settings.ts @@ -3,7 +3,5 @@ import { atom } from 'jotai'; // menu bar disabled items export const menuDisabledItemsAtom = atom([]); - // web title export const webTitleAtom = atom(''); - diff --git a/web/src/pages/desktop/keyboard/index.tsx b/web/src/pages/desktop/keyboard/index.tsx index 56b9563..a963f7f 100644 --- a/web/src/pages/desktop/keyboard/index.tsx +++ b/web/src/pages/desktop/keyboard/index.tsx @@ -2,37 +2,24 @@ import { useEffect, useRef } from 'react'; import { client } from '@/lib/websocket.ts'; -import { KeyboardCodes, ModifierCodes } from './mappings.ts'; +import { KeyboardCodes } from './mappings.ts'; export const Keyboard = () => { - const lastCodeRef = useRef(''); - const modifierRef = useRef({ - ctrl: 0, - shift: 0, - alt: 0, - meta: 0 - }); + const pressedKeys = useRef>(new Set()); // listen keyboard events useEffect(() => { - const modifiers = ['Control', 'Shift', 'Alt', 'Meta']; - window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); + window.addEventListener('blur', releaseAllKeys); + document.addEventListener('visibilitychange', handleVisibilityChange); // press button function handleKeyDown(event: KeyboardEvent) { disableEvent(event); - lastCodeRef.current = event.code; - - if (modifiers.includes(event.key)) { - const code = ModifierCodes.get(event.code)!; - setModifier(event.key, code); - - if (event.key === 'Meta') { - return; - } + if (!pressedKeys.current.has(event.code)) { + pressedKeys.current.add(event.code); } sendKeyDown(event); @@ -42,58 +29,64 @@ export const Keyboard = () => { function handleKeyUp(event: KeyboardEvent) { disableEvent(event); - if (modifiers.includes(event.key)) { - if (event.key === 'Meta' && lastCodeRef.current === event.code) { - sendKeyDown(event, true); - sendKeyUp(); - } - - setModifier(event.key, 0); + if (pressedKeys.current.has(event.code)) { + pressedKeys.current.delete(event.code); } - if (event.key !== 'Meta') { - sendKeyUp(); + sendKeyUp(); + } + + function releaseAllKeys() { + if (pressedKeys.current.size === 0) { + return; + } + + sendKeyUp(); + pressedKeys.current.clear(); + } + + function handleVisibilityChange() { + if (document.hidden) { + releaseAllKeys(); } } return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); + window.removeEventListener('blur', releaseAllKeys); + document.removeEventListener('visibilitychange', handleVisibilityChange); }; }, []); - function setModifier(key: string, code: number) { - switch (key) { - case 'Control': - modifierRef.current.ctrl = code; - break; - case 'Alt': - modifierRef.current.alt = code; - break; - case 'Shift': - modifierRef.current.shift = code; - break; - case 'Meta': - modifierRef.current.meta = code; - break; - default: - console.log('unknown key: ', key); - } - } - - function sendKeyDown(event: KeyboardEvent, isMeta?: boolean) { + function sendKeyDown(event: KeyboardEvent) { const code = KeyboardCodes.get(event.code); if (!code) { console.log('unknown code: ', event.code); return; } - const ctrl = event.ctrlKey ? modifierRef.current.ctrl || 1 : 0; - const shift = event.shiftKey ? modifierRef.current.shift || 2 : 0; - const alt = event.altKey ? modifierRef.current.alt || 4 : 0; - const meta = event.metaKey || isMeta ? modifierRef.current.meta || 8 : 0; + let ctrl = 0; + if (event.ctrlKey) { + if (pressedKeys.current.has('ControlLeft')) { + ctrl = 1; + } else if (pressedKeys.current.has('ControlRight')) { + ctrl = 16; + } else if (pressedKeys.current.has('AltRight')) { + ctrl = 0; + } else { + ctrl = 1; + } + } - client.send([1, code, ctrl, shift, alt, meta]); + const modifiers = [ + ctrl, + event.shiftKey ? (pressedKeys.current.has('ShiftRight') ? 32 : 2) : 0, + event.altKey ? (pressedKeys.current.has('AltRight') ? 64 : 4) : 0, + event.metaKey ? (pressedKeys.current.has('MetaRight') ? 128 : 8) : 0 + ]; + + client.send([1, code, ...modifiers]); } function sendKeyUp() { diff --git a/web/src/pages/desktop/menu/image/images.tsx b/web/src/pages/desktop/menu/image/images.tsx index 2c9c474..1ad9fb0 100644 --- a/web/src/pages/desktop/menu/image/images.tsx +++ b/web/src/pages/desktop/menu/image/images.tsx @@ -1,12 +1,13 @@ import { useEffect, useState } from 'react'; -import { notification } from 'antd'; +import { Button, Modal, notification, Typography } from 'antd'; import clsx from 'clsx'; import { ArrowBigDownDashIcon, ArrowBigUpDashIcon, LoaderCircleIcon, PackageIcon, - PackageSearchIcon + PackageSearchIcon, + Trash2Icon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; @@ -27,6 +28,9 @@ export const Images = ({ isOpen, cdrom, setIsMounted }: ImagesProps) => { const [images, setImages] = useState([]); const [mountingImage, setMountingImage] = useState(''); const [mountedImage, setMountedImage] = useState(''); + const [isModalOpen, setIsModalOpen] = useState(false); + const [selectedImage, setSelectedImage] = useState(''); + const [deletingImage, setDeletingImage] = useState(''); useEffect(() => { if (isOpen) { @@ -34,6 +38,7 @@ export const Images = ({ isOpen, cdrom, setIsMounted }: ImagesProps) => { } }, [isOpen]); + // get image list function getImages() { if (isLoading) return; setIsLoading(true); @@ -59,32 +64,33 @@ export const Images = ({ isOpen, cdrom, setIsMounted }: ImagesProps) => { }); } - async function getMountedImage() { - try { - const rsp = await api.getMountedImage(); + // get mounted image + function getMountedImage() { + api.getMountedImage().then((rsp) => { if (rsp.code !== 0) return; const file = rsp.data?.file; setMountedImage(file); setIsMounted(!!file); - } catch (e) { - console.log(e); - } + }); } + // mount/unmount image function mountImage(image: string) { if (mountingImage) return; setMountingImage(image); client.close(); - const filename = mountedImage === image ? '' : image; + const isMounted = mountedImage === image; + const filename = isMounted ? '' : image; api .mountImage(filename, cdrom) .then((rsp) => { if (rsp.code !== 0) { - openNotification(); + console.log(rsp.msg); + openNotification(isMounted); return; } @@ -97,42 +103,90 @@ export const Images = ({ isOpen, cdrom, setIsMounted }: ImagesProps) => { }); } - function openNotification() { + // show delete image modal + function showDeleteModal(e: any, image: string) { + e.stopPropagation(); + + const isMounted = mountedImage === image; + const isDeleting = deletingImage !== ''; + + if (isMounted || isDeleting) { + return; + } + + setSelectedImage(image); + setIsModalOpen(true); + } + + // delete image + function deleteImage() { + if (!selectedImage || !!deletingImage) return; + setDeletingImage(selectedImage); + + setIsModalOpen(false); + + api + .deleteImage(selectedImage) + .then((rsp) => { + if (rsp.code !== 0) { + console.log(rsp.msg); + return; + } + + getImages(); + + setSelectedImage(''); + }) + .finally(() => { + setDeletingImage(''); + }); + } + + // show mount/unmount failed notification + function openNotification(isMounted: boolean) { + const message = isMounted ? 'image.unmountFailed' : 'image.mountFailed'; + const description = isMounted ? 'image.unmountDesc' : 'image.mountDesc'; + notify.open({ - message: t('image.mountFailed'), - description: t('image.mountDesc'), - duration: 6 + message: t(message), + description: t(description), + duration: 10 }); } + // loading + if (isLoading) { + return ( +
+ + {t('image.loading')} +
+ ); + } + + // empty image + if (images.length === 0) { + return ( +
+ + {t('image.empty')} +
+ ); + } + return ( <> - {contextHolder} - - {isLoading ? ( - // loading -
- - {t('image.loading')} -
- ) : images.length === 0 ? ( - // no image -
- - {t('image.empty')} -
- ) : ( - // image list - images.map((image) => ( +
+ {images.map((image) => (
mountImage(image)} > -
+
{mountingImage === image ? ( ) : ( @@ -142,16 +196,54 @@ export const Images = ({ isOpen, cdrom, setIsMounted }: ImagesProps) => {
{image.replace(/^.*[\\/]/, '')}
-
+
{mountedImage === image ? ( - + ) : ( - + + )} +
+ +
showDeleteModal(e, image)} + > + {deletingImage === image ? ( + + ) : ( + )}
- )) - )} + ))} +
+ + setIsModalOpen(false)} + > +
+

{t('image.deleteConfirm')}

+ {selectedImage} +
+ +
+ + +
+
+ + {contextHolder} ); }; diff --git a/web/src/pages/desktop/menu/image/index.tsx b/web/src/pages/desktop/menu/image/index.tsx index ae0f499..80e0c08 100644 --- a/web/src/pages/desktop/menu/image/index.tsx +++ b/web/src/pages/desktop/menu/image/index.tsx @@ -1,11 +1,10 @@ import { useEffect, useState } from 'react'; -import { Divider, Switch, Tooltip } from 'antd'; +import { Divider, Modal, Segmented } from 'antd'; import clsx from 'clsx'; -import { DiscIcon } from 'lucide-react'; +import { DiscIcon, HardDriveIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { getCdRom, getMountedImage } from '@/api/storage.ts'; -import { MenuItem } from '@/components/menu-item.tsx'; +import * as api from '@/api/storage.ts'; import { Images } from './images.tsx'; import { Tips } from './tips.tsx'; @@ -13,64 +12,76 @@ import { Tips } from './tips.tsx'; export const Image = () => { const { t } = useTranslation(); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); const [isMounted, setIsMounted] = useState(false); - const [cdrom, setCdrom] = useState(false); + const [mode, setMode] = useState('mass-storage'); + + const modes = [ + { + value: 'mass-storage', + label: ( +
+ + Mass Storage +
+ ) + }, + { + value: 'cd-rom', + label: ( +
+ + CD ROM +
+ ) + } + ]; useEffect(() => { - getMountedImage().then((rsp) => { + api.getMountedImage().then((rsp) => { if (rsp.code === 0) { setIsMounted(!!rsp.data?.file); } }); - getCdRom().then((rsp) => { + api.getCdRom().then((rsp) => { if (rsp.code === 0) { - setCdrom(rsp.data?.cdrom === 1); + setMode(rsp.data?.cdrom === 1 ? 'cd-rom' : 'mass-storage'); } }); }, []); - const content = ( -
-
+ return ( + <> +
setIsModalOpen(true)} + > + +
+ + setIsModalOpen(false)}>
- {t('image.title')} + {t('image.title')}
-
- -
- CD-ROM + - setCdrom(checked)} - > -
-
+
+
+ {t('image.mountMode')} + +
+ + + +
-
- - - - -
- ); - - return ( - } - content={content} - className={clsx( - 'flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700', - isMounted ? 'text-blue-500' : 'text-neutral-300 hover:text-white' - )} - fresh={true} - onOpenChange={setIsPopoverOpen} - /> + + ); }; diff --git a/web/src/pages/desktop/menu/image/tips.tsx b/web/src/pages/desktop/menu/image/tips.tsx index 516fe0e..e54644f 100644 --- a/web/src/pages/desktop/menu/image/tips.tsx +++ b/web/src/pages/desktop/menu/image/tips.tsx @@ -51,13 +51,10 @@ export const Tips = () => { return ( <>
setIsModalOpen(true)} > - {/**/} - {/* {t('image.tips.title')}*/} - {/**/}
{ const { t } = useTranslation(); @@ -35,13 +34,7 @@ export const Menu = () => { // disabled menu items const items = getMenuDisabledItems(); setMenuDisabledItems(items); - getMenuDisableItems().then(res=>{ - let disableItems = new Set(items) - if(res.code === 0){ - (res.data as string[]).forEach((ele)=>disableItems.add(ele)) - } - setMenuDisabledItems([...disableItems.values()]) - }) + // react-draggable bounds const handleResize = () => { if (!nodeRef.current) return; diff --git a/web/src/pages/desktop/menu/keyboard/paste.tsx b/web/src/pages/desktop/menu/keyboard/paste.tsx index ad5327c..5d4ff1b 100644 --- a/web/src/pages/desktop/menu/keyboard/paste.tsx +++ b/web/src/pages/desktop/menu/keyboard/paste.tsx @@ -1,5 +1,6 @@ -import { ChangeEvent, useRef, useState } from 'react'; -import { Button, Input, Modal, Select, message, type InputRef } from 'antd'; +import { ChangeEvent, useEffect, useRef, useState } from 'react'; +import { Button, Divider, Input, Modal, Select } from 'antd'; +import type { InputRef } from 'antd'; import clsx from 'clsx'; import { useSetAtom } from 'jotai'; import { ClipboardIcon, ClipboardPasteIcon } from 'lucide-react'; @@ -8,9 +9,7 @@ import { useTranslation } from 'react-i18next'; import { paste } from '@/api/hid'; import { isKeyboardEnableAtom } from '@/jotai/keyboard.ts'; -const { Option } = Select; - -const { TextArea } = Input; +type InputStatus = '' | 'error'; export const Paste = () => { const { t } = useTranslation(); @@ -18,14 +17,24 @@ export const Paste = () => { const [isModalOpen, setIsModalOpen] = useState(false); const [inputValue, setInputValue] = useState(''); - const [status, setStatus] = useState<'' | 'error'>(''); - const [isLoading, setIsLoading] = useState(false); - const [errMsg, setErrMsg] = useState(''); + const [isClipboardSupported, setIsClipboardSupported] = useState(false); const [isReadingClipboard, setIsReadingClipboard] = useState(false); const [langue, setLangue] = useState('en'); + const [status, setStatus] = useState(''); + const [errMsg, setErrMsg] = useState(''); + const [isLoading, setIsLoading] = useState(false); const inputRef = useRef(null); + const languages = [ + { value: 'en', label: t('keyboard.dropdownEnglish') }, + { value: 'de', label: t('keyboard.dropdownGerman') } + ]; + + useEffect(() => { + setIsClipboardSupported('clipboard' in navigator); + }, []); + function onChange(e: ChangeEvent) { const value = e.target.value; setStatus(isASCII(value) ? '' : 'error'); @@ -34,60 +43,27 @@ export const Paste = () => { async function readFromClipboard() { if (isReadingClipboard) return; - setIsReadingClipboard(true); + try { - // Check if clipboard API is available - if (!navigator.clipboard || !navigator.clipboard.readText) { - message.error(t('keyboard.clipboardNotSupported') || 'Clipboard API is not supported in this browser'); - return; - } - - // Read text from clipboard const text = await navigator.clipboard.readText(); - if (!text) { - message.warning(t('keyboard.clipboardEmpty') || 'Clipboard is empty'); return; } - - // Validate ASCII - if (!isASCII(text)) { - setStatus('error'); - setInputValue(text); - message.error(t('keyboard.nonAsciiError') || 'Only ASCII characters are supported'); - return; - } - - // Check length - if (text.length > 1024) { - message.warning(t('keyboard.clipboardTooLong') || 'Clipboard content exceeds 1024 characters'); - setInputValue(text.substring(0, 1024)); - setStatus(''); - return; - } - - setInputValue(text); - setStatus(''); - message.success(t('keyboard.clipboardRead') || 'Clipboard content loaded'); + setInputValue((value) => value + text); } catch (error) { - console.error('Failed to read clipboard:', error); - if (error instanceof Error) { - if (error.name === 'NotAllowedError') { - message.error(t('keyboard.clipboardPermissionDenied') || 'Clipboard permission denied. Please allow clipboard access in your browser.'); - } else { - message.error(t('keyboard.clipboardReadError') || `Failed to read clipboard: ${error.message}`); - } - } else { - message.error(t('keyboard.clipboardReadError') || 'Failed to read clipboard'); + if (error instanceof Error && error.name === 'NotAllowedError') { + setErrMsg(t('keyboard.clipboardPermissionDenied')); + return; } + setErrMsg(t('keyboard.clipboardReadError')); } finally { setIsReadingClipboard(false); } } function submit() { - if (isLoading) return; + if (isLoading || !inputValue) return; setIsLoading(true); paste(inputValue, langue) @@ -139,23 +115,27 @@ export const Paste = () => { setIsModalOpen(false)} afterOpenChange={afterOpenChange} > -
{t('keyboard.tips')}
+
+ {t('keyboard.paste')} + {t('keyboard.tips')} +
-
- -
+ + +
+ {isClipboardSupported && ( - - {t('keyboard.clipboardHint') || 'Click to paste from your browser clipboard'} - -
+ )} -