diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..cc36cf7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 10 + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 10 + - package-ecosystem: npm + directory: /ui + open-pull-requests-limit: 10 + schedule: + interval: monthly diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bf4b13..59053da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,9 +10,9 @@ on: jobs: build: - runs-on: buildjet-4vcpu-ubuntu-2204 + runs-on: ubuntu-latest name: Build - if: "github.event.review.state == 'approved' || github.event.event_type != 'pull_request_review'" + if: github.event_name != 'pull_request_review' || github.event.review.state == 'approved' steps: - name: Checkout uses: actions/checkout@v4 @@ -23,9 +23,9 @@ jobs: cache: "npm" cache-dependency-path: "**/package-lock.json" - name: Set up Golang - uses: actions/setup-go@v4 + uses: actions/setup-go@v5.5.0 with: - go-version: "1.24.3" + go-version: "1.24.4" - name: Build frontend run: | make frontend diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 0a74064..fa1fe22 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -24,9 +24,9 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@fa96338abe5531f6e34c5cc0bbe28c1a533d5505 # v4.2.1 with: - go-version: 1.24.3 + go-version: 1.24.4 - name: Create empty resource directory run: | mkdir -p static && touch static/.gitkeep diff --git a/.github/workflows/smoketest.yml b/.github/workflows/smoketest.yml index 46f0198..41aa07e 100644 --- a/.github/workflows/smoketest.yml +++ b/.github/workflows/smoketest.yml @@ -104,9 +104,9 @@ jobs: EOF ssh jkci "cat /tmp/device-tests.json" > device-tests.json - name: Set up Golang - uses: actions/setup-go@v4 + uses: actions/setup-go@v5.5.0 with: - go-version: "1.24.3" + go-version: "1.24.4" - name: Golang Test Report uses: becheran/go-testreport@v0.3.2 with: diff --git a/.github/workflows/ui-lint.yml b/.github/workflows/ui-lint.yml index 492a5fe..ad002fc 100644 --- a/.github/workflows/ui-lint.yml +++ b/.github/workflows/ui-lint.yml @@ -14,16 +14,16 @@ permissions: jobs: ui-lint: name: UI Lint - runs-on: buildjet-4vcpu-ubuntu-2204 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: v21.1.0 + node-version: "22" cache: "npm" - cache-dependency-path: "ui/package-lock.json" + cache-dependency-path: "**/package-lock.json" - name: Install dependencies run: | cd ui diff --git a/.golangci.yml b/.golangci.yml index 23e2762..dd8a079 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,9 @@ linters: - linters: - errcheck path: _test.go + - linters: + - forbidigo + path: cmd/main.go - linters: - gochecknoinits path: internal/logging/sse.go diff --git a/Makefile b/Makefile index 8262698..c696dca 100644 --- a/Makefile +++ b/Makefile @@ -2,12 +2,14 @@ BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) BUILDDATE ?= $(shell date -u +%FT%T%z) BUILDTS ?= $(shell date -u +%s) REVISION ?= $(shell git rev-parse HEAD) -VERSION_DEV := 0.4.2-dev$(shell date +%Y%m%d%H%M) -VERSION := 0.4.1 +VERSION_DEV ?= 0.4.7-dev$(shell date +%Y%m%d%H%M) +VERSION ?= 0.4.6 PROMETHEUS_TAG := github.com/prometheus/common/version KVM_PKG_NAME := github.com/jetkvm/kvm +GO_BUILD_ARGS := -tags netgo +GO_RELEASE_BUILD_ARGS := -trimpath $(GO_BUILD_ARGS) GO_LDFLAGS := \ -s -w \ -X $(PROMETHEUS_TAG).Branch=$(BRANCH) \ @@ -27,7 +29,7 @@ build_dev: hash_resource @echo "Building..." $(GO_CMD) build \ -ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \ - -trimpath \ + $(GO_RELEASE_BUILD_ARGS) \ -o $(BIN_DIR)/jetkvm_app cmd/main.go build_test2json: @@ -50,6 +52,7 @@ build_dev_test: build_test2json build_gotestsum test_filename=$$(echo $$test_pkg_name | sed 's/\//__/g')_test; \ $(GO_CMD) test -v \ -ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \ + $(GO_BUILD_ARGS) \ -c -o $(BIN_DIR)/tests/$$test_filename $$test; \ echo "runTest ./$$test_filename $$test_pkg_full_name" >> $(BIN_DIR)/tests/run_all_tests; \ done; \ @@ -71,7 +74,7 @@ build_release: frontend hash_resource @echo "Building release..." $(GO_CMD) build \ -ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION)" \ - -trimpath \ + $(GO_RELEASE_BUILD_ARGS) \ -o bin/jetkvm_app cmd/main.go release: diff --git a/cloud.go b/cloud.go index fb1998a..cec749e 100644 --- a/cloud.go +++ b/cloud.go @@ -51,34 +51,34 @@ var ( ) metricCloudConnectionEstablishedTimestamp = promauto.NewGauge( prometheus.GaugeOpts{ - Name: "jetkvm_cloud_connection_established_timestamp", + Name: "jetkvm_cloud_connection_established_timestamp_seconds", Help: "The timestamp when the cloud connection was established", }, ) metricConnectionLastPingTimestamp = promauto.NewGaugeVec( prometheus.GaugeOpts{ - Name: "jetkvm_connection_last_ping_timestamp", + Name: "jetkvm_connection_last_ping_timestamp_seconds", Help: "The timestamp when the last ping response was received", }, []string{"type", "source"}, ) metricConnectionLastPingReceivedTimestamp = promauto.NewGaugeVec( prometheus.GaugeOpts{ - Name: "jetkvm_connection_last_ping_received_timestamp", + Name: "jetkvm_connection_last_ping_received_timestamp_seconds", Help: "The timestamp when the last ping request was received", }, []string{"type", "source"}, ) metricConnectionLastPingDuration = promauto.NewGaugeVec( prometheus.GaugeOpts{ - Name: "jetkvm_connection_last_ping_duration", + Name: "jetkvm_connection_last_ping_duration_seconds", Help: "The duration of the last ping response", }, []string{"type", "source"}, ) metricConnectionPingDuration = promauto.NewHistogramVec( prometheus.HistogramOpts{ - Name: "jetkvm_connection_ping_duration", + Name: "jetkvm_connection_ping_duration_seconds", Help: "The duration of the ping response", Buckets: []float64{ 0.1, 0.5, 1, 10, @@ -88,28 +88,28 @@ var ( ) metricConnectionTotalPingSentCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_connection_total_ping_sent", + Name: "jetkvm_connection_ping_sent_total", Help: "The total number of pings sent to the connection", }, []string{"type", "source"}, ) metricConnectionTotalPingReceivedCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_connection_total_ping_received", + Name: "jetkvm_connection_ping_received_total", Help: "The total number of pings received from the connection", }, []string{"type", "source"}, ) metricConnectionSessionRequestCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_connection_session_total_requests", + Name: "jetkvm_connection_session_requests_total", Help: "The total number of session requests received", }, []string{"type", "source"}, ) metricConnectionSessionRequestDuration = promauto.NewHistogramVec( prometheus.HistogramOpts{ - Name: "jetkvm_connection_session_request_duration", + Name: "jetkvm_connection_session_request_duration_seconds", Help: "The duration of session requests", Buckets: []float64{ 0.1, 0.5, 1, 10, @@ -119,7 +119,7 @@ var ( ) metricConnectionLastSessionRequestTimestamp = promauto.NewGaugeVec( prometheus.GaugeOpts{ - Name: "jetkvm_connection_last_session_request_timestamp", + Name: "jetkvm_connection_last_session_request_timestamp_seconds", Help: "The timestamp of the last session request", }, []string{"type", "source"}, @@ -133,7 +133,7 @@ var ( ) metricCloudConnectionFailureCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_cloud_connection_failure_count", + Name: "jetkvm_cloud_connection_failure_total", Help: "The number of times the cloud connection has failed", }, ) diff --git a/cmd/main.go b/cmd/main.go index ab44ac9..2292bd9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,9 +1,27 @@ package main import ( + "flag" + "fmt" + "os" + "github.com/jetkvm/kvm" ) func main() { + versionPtr := flag.Bool("version", false, "print version and exit") + versionJsonPtr := flag.Bool("version-json", false, "print version as json and exit") + flag.Parse() + + if *versionPtr || *versionJsonPtr { + versionData, err := kvm.GetVersionData(*versionJsonPtr) + if err != nil { + fmt.Printf("failed to get version data: %v\n", err) + os.Exit(1) + } + fmt.Println(string(versionData)) + return + } + kvm.Main() } diff --git a/config.go b/config.go index 04f2a4e..3e88457 100644 --- a/config.go +++ b/config.go @@ -111,7 +111,7 @@ var defaultConfig = &Config{ ActiveExtension: "", KeyboardMacros: []KeyboardMacro{}, DisplayRotation: "270", - KeyboardLayout: "en-US", + KeyboardLayout: "en_US", DisplayMaxBrightness: 64, DisplayDimAfterSec: 120, // 2 minutes DisplayOffAfterSec: 1800, // 30 minutes diff --git a/dc_metrics.go b/dc_metrics.go new file mode 100644 index 0000000..692a7b5 --- /dev/null +++ b/dc_metrics.go @@ -0,0 +1,53 @@ +package kvm + +import ( + "sync" + + "github.com/prometheus/client_golang/prometheus" +) + +var ( + dcCurrentGauge = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "jetkvm_dc_current_amperes", + Help: "Current DC power consumption in amperes", + }) + + dcPowerGauge = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "jetkvm_dc_power_watts", + Help: "DC power consumption in watts", + }) + + dcVoltageGauge = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "jetkvm_dc_voltage_volts", + Help: "DC voltage in volts", + }) + + dcStateGauge = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "jetkvm_dc_power_state", + Help: "DC power state (1 = on, 0 = off)", + }) + + dcMetricsRegistered sync.Once +) + +// registerDCMetrics registers the DC power metrics with Prometheus (called once when DC control is mounted) +func registerDCMetrics() { + dcMetricsRegistered.Do(func() { + prometheus.MustRegister(dcCurrentGauge) + prometheus.MustRegister(dcPowerGauge) + prometheus.MustRegister(dcVoltageGauge) + prometheus.MustRegister(dcStateGauge) + }) +} + +// updateDCMetrics updates the Prometheus metrics with current DC power state values +func updateDCMetrics(state DCPowerState) { + dcCurrentGauge.Set(state.Current) + dcPowerGauge.Set(state.Power) + dcVoltageGauge.Set(state.Voltage) + if state.IsOn { + dcStateGauge.Set(1) + } else { + dcStateGauge.Set(0) + } +} diff --git a/dev_deploy.sh b/dev_deploy.sh index a2d32ed..90ced64 100755 --- a/dev_deploy.sh +++ b/dev_deploy.sh @@ -174,7 +174,7 @@ cd "${REMOTE_PATH}" chmod +x jetkvm_app_debug # Run the application in the background -PION_LOG_TRACE=${LOG_TRACE_SCOPES} ./jetkvm_app_debug +PION_LOG_TRACE=${LOG_TRACE_SCOPES} ./jetkvm_app_debug | tee -a /tmp/jetkvm_app_debug.log EOF echo "Deployment complete." \ No newline at end of file diff --git a/display.go b/display.go index 2a22351..274bb8b 100644 --- a/display.go +++ b/display.go @@ -9,9 +9,14 @@ import ( "time" ) -var currentScreen = "ui_Boot_Screen" var backlightState = 0 // 0 - NORMAL, 1 - DIMMED, 2 - OFF +var ( + currentScreen = "ui_Boot_Screen" + displayedTexts = make(map[string]string) + screenStateLock = sync.Mutex{} +) + var ( dimTicker *time.Ticker offTicker *time.Ticker @@ -22,6 +27,8 @@ const ( backlightControlClass string = "/sys/class/backlight/backlight/brightness" ) +// do not call this function directly, use switchToScreenIfDifferent instead +// this function is not thread safe func switchToScreen(screen string) { _, err := CallCtrlAction("lv_scr_load", map[string]interface{}{"obj": screen}) if err != nil { @@ -31,8 +38,6 @@ func switchToScreen(screen string) { currentScreen = screen } -var displayedTexts = make(map[string]string) - func lvObjSetState(objName string, state string) (*CtrlResponse, error) { return CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": objName, "state": state}) } @@ -78,6 +83,9 @@ func lvDispSetRotation(rotation string) (*CtrlResponse, error) { } func updateLabelIfChanged(objName string, newText string) { + screenStateLock.Lock() + defer screenStateLock.Unlock() + if newText != "" && newText != displayedTexts[objName] { _, _ = lvLabelSetText(objName, newText) displayedTexts[objName] = newText @@ -85,12 +93,23 @@ func updateLabelIfChanged(objName string, newText string) { } func switchToScreenIfDifferent(screenName string) { + screenStateLock.Lock() + defer screenStateLock.Unlock() + if currentScreen != screenName { displayLogger.Info().Str("from", currentScreen).Str("to", screenName).Msg("switching screen") switchToScreen(screenName) } } +func clearDisplayState() { + screenStateLock.Lock() + defer screenStateLock.Unlock() + + displayedTexts = make(map[string]string) + currentScreen = "ui_Boot_Screen" +} + var ( cloudBlinkLock sync.Mutex = sync.Mutex{} cloudBlinkStopped bool @@ -339,10 +358,18 @@ func startBacklightTickers() { return } - if dimTicker == nil && config.DisplayDimAfterSec != 0 { + // Stop existing tickers to prevent multiple active instances on repeated calls + if dimTicker != nil { + dimTicker.Stop() + } + + if offTicker != nil { + offTicker.Stop() + } + + if config.DisplayDimAfterSec != 0 { displayLogger.Info().Msg("dim_ticker has started") dimTicker = time.NewTicker(time.Duration(config.DisplayDimAfterSec) * time.Second) - defer dimTicker.Stop() go func() { for { //nolint:staticcheck @@ -354,10 +381,9 @@ func startBacklightTickers() { }() } - if offTicker == nil && config.DisplayOffAfterSec != 0 { + if config.DisplayOffAfterSec != 0 { displayLogger.Info().Msg("off_ticker has started") offTicker = time.NewTicker(time.Duration(config.DisplayOffAfterSec) * time.Second) - defer offTicker.Stop() go func() { for { //nolint:staticcheck diff --git a/go.mod b/go.mod index 4abd752..426f656 100644 --- a/go.mod +++ b/go.mod @@ -1,37 +1,35 @@ module github.com/jetkvm/kvm -go 1.23.4 - -toolchain go1.24.3 +go 1.24.4 require ( - github.com/Masterminds/semver/v3 v3.3.0 - github.com/beevik/ntp v1.3.1 + github.com/Masterminds/semver/v3 v3.4.0 + github.com/beevik/ntp v1.4.3 github.com/coder/websocket v1.8.13 - github.com/coreos/go-oidc/v3 v3.11.0 - github.com/creack/pty v1.1.23 + github.com/coreos/go-oidc/v3 v3.14.1 + github.com/creack/pty v1.1.24 github.com/fsnotify/fsnotify v1.9.0 - github.com/gin-contrib/logger v1.2.5 - github.com/gin-gonic/gin v1.10.0 + github.com/gin-contrib/logger v1.2.6 + github.com/gin-gonic/gin v1.10.1 github.com/google/uuid v1.6.0 github.com/guregu/null/v6 v6.0.0 - github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf - github.com/hanwen/go-fuse/v2 v2.5.1 - github.com/pion/logging v0.2.2 + github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341 + github.com/hanwen/go-fuse/v2 v2.8.0 + github.com/pion/logging v0.2.4 github.com/pion/mdns/v2 v2.0.7 - github.com/pion/webrtc/v4 v4.0.0 + github.com/pion/webrtc/v4 v4.1.3 github.com/pojntfx/go-nbd v0.3.2 - github.com/prometheus/client_golang v1.21.0 - github.com/prometheus/common v0.62.0 - github.com/prometheus/procfs v0.15.1 + github.com/prometheus/client_golang v1.22.0 + github.com/prometheus/common v0.65.0 + github.com/prometheus/procfs v0.16.1 github.com/psanford/httpreadat v0.1.0 github.com/rs/zerolog v1.34.0 github.com/sourcegraph/tf-dag v0.2.2-0.20250131204052-3e8ff1477b4f github.com/stretchr/testify v1.10.0 - github.com/vishvananda/netlink v1.3.0 - go.bug.st/serial v1.6.2 - golang.org/x/crypto v0.38.0 - golang.org/x/net v0.40.0 + github.com/vishvananda/netlink v1.3.1 + go.bug.st/serial v1.6.4 + golang.org/x/crypto v0.39.0 + golang.org/x/net v0.41.0 golang.org/x/sys v0.33.0 ) @@ -39,22 +37,20 @@ replace github.com/pojntfx/go-nbd v0.3.2 => github.com/chemhack/go-nbd v0.0.0-20 require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic v1.13.3 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.5 // indirect - github.com/creack/goselect v0.1.2 // indirect + github.com/creack/goselect v0.1.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/gin-contrib/sse v1.0.0 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/gabriel-vasile/mimetype v1.4.9 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.26.0 // indirect github.com/goccy/go-json v0.10.5 // indirect - github.com/google/go-cmp v0.7.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect @@ -62,31 +58,31 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect - github.com/pilebones/go-udev v0.9.0 // 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/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pilebones/go-udev v0.9.1 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v3 v3.0.6 // indirect + github.com/pion/ice/v4 v4.0.10 // indirect + github.com/pion/interceptor v0.1.40 // 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/sctp v1.8.33 // indirect - github.com/pion/sdp/v3 v3.0.9 // indirect - github.com/pion/srtp/v3 v3.0.4 // indirect + github.com/pion/rtcp v1.2.15 // indirect + github.com/pion/rtp v1.8.20 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/sdp/v3 v3.0.14 // indirect + github.com/pion/srtp/v3 v3.0.6 // indirect github.com/pion/stun/v3 v3.0.0 // indirect github.com/pion/transport/v3 v3.0.7 // indirect - github.com/pion/turn/v4 v4.0.0 // indirect + github.com/pion/turn/v4 v4.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - github.com/vishvananda/netns v0.0.4 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/vishvananda/netns v0.0.5 // indirect github.com/wlynxg/anet v0.0.5 // indirect - golang.org/x/arch v0.15.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/arch v0.18.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/text v0.26.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 63ebc96..a9f9b77 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/beevik/ntp v1.3.1 h1:Y/srlT8L1yQr58kyPWFPZIxRL8ttx2SRIpVYJqZIlAM= -github.com/beevik/ntp v1.3.1/go.mod h1:fT6PylBq86Tsq23ZMEe47b7QQrZfYBFPnpzt0a9kJxw= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho= +github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= -github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0= +github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= @@ -18,28 +18,28 @@ github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE= github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= -github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= -github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= +github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk= +github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= -github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= -github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= -github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/creack/goselect v0.1.3 h1:MaGNMclRo7P2Jl21hBpR1Cn33ITSbKP6E49RtfblLKc= +github.com/creack/goselect v0.1.3/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= -github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/gin-contrib/logger v1.2.5 h1:qVQI4omayQecuN4zX9ZZnsOq7w9J/ZLds3J/FMn8ypM= -github.com/gin-contrib/logger v1.2.5/go.mod h1:/bj+vNMuA2xOEQ1aRHoJ1m9+uyaaXIAxQTvM2llsc6I= -github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= -github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= -github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= -github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= +github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= +github.com/gin-contrib/logger v1.2.6 h1:EPolruKUTzNXMVBD9LuAFQmRjTs7AH7yKGuXgYqrKWc= +github.com/gin-contrib/logger v1.2.6/go.mod h1:7niPrd7F0Nscw/zvgz8RiGJxSdbKM2yfQNy8xCHcm64= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= +github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= +github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -58,14 +58,14 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ= github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ= -github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf h1:JO6ISZIvEUitto5zjQ3/VEnDM5rPbqIFuOhS0U0ByeA= -github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf/go.mod h1:5Kt9XkWvkGi2OHOq0QsGxebHmhCcqJ8KCbNg/a6+n+g= -github.com/hanwen/go-fuse/v2 v2.5.1 h1:OQBE8zVemSocRxA4OaFJbjJ5hlpCmIWbGr7r0M4uoQQ= -github.com/hanwen/go-fuse/v2 v2.5.1/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs= +github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341 h1:zPrkLSKi7kKJoNJH4uUmsQ86+0/QqpwEns0NyNLwKv0= +github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341/go.mod h1:5Kt9XkWvkGi2OHOq0QsGxebHmhCcqJ8KCbNg/a6+n+g= +github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs= +github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -77,7 +77,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -89,8 +88,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -98,57 +97,57 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q= -github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI= -github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA= -github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE= -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/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pilebones/go-udev v0.9.1 h1:uN72M1C1fgzhsVmBGEM8w9RD1JY4iVsPZpr+Z6rb3O8= +github.com/pilebones/go-udev v0.9.1/go.mod h1:Bgcl07crebF3JSeS4+nuaRvhWFdCeFoBhXXeAp93XNo= +github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= +github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E= +github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= +github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= +github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8= +github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so= 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/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= -github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= -github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M= -github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ= +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.20 h1:8zcyqohadZE8FCBeGdyEvHiclPIezcwRQH9zfapFyYI= +github.com/pion/rtp v1.8.20/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.14 h1:1h7gBr9FhOWH5GjWWY5lcw/U85MtdcibTyt/o6RxRUI= +github.com/pion/sdp/v3 v3.0.14/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4= +github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= -github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM= -github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA= -github.com/pion/webrtc/v4 v4.0.0 h1:x8ec7uJQPP3D1iI8ojPAiTOylPI7Fa7QgqZrhpLyqZ8= -github.com/pion/webrtc/v4 v4.0.0/go.mod h1:SfNn8CcFxR6OUVjLXVslAQ3a3994JhyE3Hw1jAuqEto= +github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= +github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= +github.com/pion/webrtc/v4 v4.1.3 h1:YZ67Boj9X/hk190jJZ8+HFGQ6DqSZ/fYP3sLAZv7c3c= +github.com/pion/webrtc/v4 v4.1.3/go.mod h1:rsq+zQ82ryfR9vbb0L1umPJ6Ogq7zm8mcn9fcGnxomM= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= -github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIwZLUE= github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= @@ -157,38 +156,33 @@ github.com/sourcegraph/tf-dag v0.2.2-0.20250131204052-3e8ff1477b4f/go.mod h1:pzr github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/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/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= -github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= -github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= -github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= -go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= -go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= -golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= -golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A= +go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI= +golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc= +golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -196,8 +190,8 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/confparser/confparser_test.go b/internal/confparser/confparser_test.go index 07d057e..e14a1ea 100644 --- a/internal/confparser/confparser_test.go +++ b/internal/confparser/confparser_test.go @@ -43,9 +43,11 @@ type testNetworkConfig struct { LLDPTxTLVs []string `json:"lldp_tx_tlvs,omitempty" one_of:"chassis,port,system,vlan" default:"chassis,port,system,vlan"` MDNSMode null.String `json:"mdns_mode,omitempty" one_of:"disabled,auto,ipv4_only,ipv6_only" default:"auto"` TimeSyncMode null.String `json:"time_sync_mode,omitempty" one_of:"ntp_only,ntp_and_http,http_only,custom" default:"ntp_and_http"` - TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,ntp_fallback" default:"ntp,http"` + TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,http_user_provided" default:"ntp,http"` TimeSyncDisableFallback null.Bool `json:"time_sync_disable_fallback,omitempty" default:"false"` TimeSyncParallel null.Int `json:"time_sync_parallel,omitempty" default:"4"` + TimeSyncNTPServers []string `json:"time_sync_ntp_servers,omitempty" validate_type:"ipv4_or_ipv6" required_if:"TimeSyncOrdering=ntp_user_provided"` + TimeSyncHTTPUrls []string `json:"time_sync_http_urls,omitempty" validate_type:"url" required_if:"TimeSyncOrdering=http_user_provided"` } func TestValidateConfig(t *testing.T) { diff --git a/internal/network/config.go b/internal/network/config.go index 74ddf19..c8fe582 100644 --- a/internal/network/config.go +++ b/internal/network/config.go @@ -45,9 +45,11 @@ type NetworkConfig struct { LLDPTxTLVs []string `json:"lldp_tx_tlvs,omitempty" one_of:"chassis,port,system,vlan" default:"chassis,port,system,vlan"` MDNSMode null.String `json:"mdns_mode,omitempty" one_of:"disabled,auto,ipv4_only,ipv6_only" default:"auto"` TimeSyncMode null.String `json:"time_sync_mode,omitempty" one_of:"ntp_only,ntp_and_http,http_only,custom" default:"ntp_and_http"` - TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,ntp_fallback" default:"ntp,http"` + TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,http_user_provided" default:"ntp,http"` TimeSyncDisableFallback null.Bool `json:"time_sync_disable_fallback,omitempty" default:"false"` TimeSyncParallel null.Int `json:"time_sync_parallel,omitempty" default:"4"` + TimeSyncNTPServers []string `json:"time_sync_ntp_servers,omitempty" validate_type:"ipv4_or_ipv6" required_if:"TimeSyncOrdering=ntp_user_provided"` + TimeSyncHTTPUrls []string `json:"time_sync_http_urls,omitempty" validate_type:"url" required_if:"TimeSyncOrdering=http_user_provided"` } func (c *NetworkConfig) GetMDNSMode() *mdns.MDNSListenOptions { diff --git a/internal/network/netif.go b/internal/network/netif.go index c5db806..5a8dab6 100644 --- a/internal/network/netif.go +++ b/internal/network/netif.go @@ -21,6 +21,7 @@ type NetworkInterfaceState struct { ipv6Addr *net.IP ipv6Addresses []IPv6Address ipv6LinkLocal *net.IP + ntpAddresses []*net.IP macAddr *net.HardwareAddr l *zerolog.Logger @@ -76,6 +77,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS onInitialCheck: opts.OnInitialCheck, cbConfigChange: opts.OnConfigChange, config: opts.NetworkConfig, + ntpAddresses: make([]*net.IP, 0), } // create the dhcp client @@ -89,7 +91,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS opts.Logger.Error().Err(err).Msg("failed to update network state") return } - + _ = s.updateNtpServersFromLease(lease) _ = s.setHostnameIfNotSame() opts.OnDhcpLeaseChange(lease) @@ -135,6 +137,27 @@ func (s *NetworkInterfaceState) IPv6String() string { return s.ipv6Addr.String() } +func (s *NetworkInterfaceState) NtpAddresses() []*net.IP { + return s.ntpAddresses +} + +func (s *NetworkInterfaceState) NtpAddressesString() []string { + ntpServers := []string{} + + if s != nil { + s.l.Debug().Any("s", s).Msg("getting NTP address strings") + + if len(s.ntpAddresses) > 0 { + for _, server := range s.ntpAddresses { + s.l.Debug().IPAddr("server", *server).Msg("converting NTP address") + ntpServers = append(ntpServers, server.String()) + } + } + } + + return ntpServers +} + func (s *NetworkInterfaceState) MAC() *net.HardwareAddr { return s.macAddr } @@ -318,6 +341,25 @@ func (s *NetworkInterfaceState) update() (DhcpTargetState, error) { return dhcpTargetState, nil } +func (s *NetworkInterfaceState) updateNtpServersFromLease(lease *udhcpc.Lease) error { + if lease != nil && len(lease.NTPServers) > 0 { + s.l.Info().Msg("lease found, updating DHCP NTP addresses") + s.ntpAddresses = make([]*net.IP, 0, len(lease.NTPServers)) + + for _, ntpServer := range lease.NTPServers { + if ntpServer != nil { + s.l.Info().IPAddr("ntp_server", ntpServer).Msg("NTP server found in lease") + s.ntpAddresses = append(s.ntpAddresses, &ntpServer) + } + } + } else { + s.l.Info().Msg("no NTP servers found in lease") + s.ntpAddresses = make([]*net.IP, 0, len(s.config.TimeSyncNTPServers)) + } + + return nil +} + func (s *NetworkInterfaceState) CheckAndUpdateDhcp() error { dhcpTargetState, err := s.update() if err != nil { diff --git a/internal/timesync/http.go b/internal/timesync/http.go index 3a51463..703308c 100644 --- a/internal/timesync/http.go +++ b/internal/timesync/http.go @@ -19,9 +19,9 @@ var defaultHTTPUrls = []string{ // "http://www.msftconnecttest.com/connecttest.txt", } -func (t *TimeSync) queryAllHttpTime() (now *time.Time) { - chunkSize := 4 - httpUrls := t.httpUrls +func (t *TimeSync) queryAllHttpTime(httpUrls []string) (now *time.Time) { + chunkSize := int(t.networkConfig.TimeSyncParallel.ValueOr(4)) + t.l.Info().Strs("httpUrls", httpUrls).Int("chunkSize", chunkSize).Msg("querying HTTP URLs") // shuffle the http urls to avoid always querying the same servers rand.Shuffle(len(httpUrls), func(i, j int) { httpUrls[i], httpUrls[j] = httpUrls[j], httpUrls[i] }) @@ -95,16 +95,27 @@ func (t *TimeSync) queryMultipleHttp(urls []string, timeout time.Duration) (now } else if errors.Is(err, context.Canceled) { metricHttpCancelCount.WithLabelValues(url).Inc() metricHttpTotalCancelCount.Inc() + results <- nil } else { scopedLogger.Warn(). Str("error", err.Error()). Int("status", status). Msg("failed to query HTTP server") + results <- nil } }(url) } - return <-results + for range urls { + result := <-results + if result == nil { + continue + } + now = result + return + } + + return } func queryHttpTime( diff --git a/internal/timesync/metrics.go b/internal/timesync/metrics.go index 0e28acb..1c27c8b 100644 --- a/internal/timesync/metrics.go +++ b/internal/timesync/metrics.go @@ -14,44 +14,44 @@ var ( ) metricTimeSyncCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_count", + Name: "jetkvm_timesync_total", Help: "The number of times the timesync has been run", }, ) metricTimeSyncSuccessCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_success_count", + Name: "jetkvm_timesync_success_total", Help: "The number of times the timesync has been successful", }, ) metricRTCUpdateCount = promauto.NewCounter( //nolint:unused prometheus.CounterOpts{ - Name: "jetkvm_timesync_rtc_update_count", + Name: "jetkvm_timesync_rtc_update_total", Help: "The number of times the RTC has been updated", }, ) metricNtpTotalSuccessCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_ntp_total_success_count", + Name: "jetkvm_timesync_ntp_total_success_total", Help: "The total number of successful NTP requests", }, ) metricNtpTotalRequestCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_ntp_total_request_count", + Name: "jetkvm_timesync_ntp_total_request_total", Help: "The total number of NTP requests sent", }, ) metricNtpSuccessCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_timesync_ntp_success_count", + Name: "jetkvm_timesync_ntp_success_total", Help: "The number of successful NTP requests", }, []string{"url"}, ) metricNtpRequestCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_timesync_ntp_request_count", + Name: "jetkvm_timesync_ntp_request_total", Help: "The number of NTP requests sent to the server", }, []string{"url"}, @@ -73,6 +73,7 @@ var ( }, []string{"url"}, ) + metricNtpServerInfo = promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: "jetkvm_timesync_ntp_server_info", @@ -83,39 +84,39 @@ var ( metricHttpTotalSuccessCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_total_success_count", + Name: "jetkvm_timesync_http_total_success_total", Help: "The total number of successful HTTP requests", }, ) metricHttpTotalRequestCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_total_request_count", + Name: "jetkvm_timesync_http_total_request_total", Help: "The total number of HTTP requests sent", }, ) metricHttpTotalCancelCount = promauto.NewCounter( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_total_cancel_count", + Name: "jetkvm_timesync_http_total_cancel_total", Help: "The total number of HTTP requests cancelled", }, ) metricHttpSuccessCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_success_count", + Name: "jetkvm_timesync_http_success_total", Help: "The number of successful HTTP requests", }, []string{"url"}, ) metricHttpRequestCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_request_count", + Name: "jetkvm_timesync_http_request_total", Help: "The number of HTTP requests sent to the server", }, []string{"url"}, ) metricHttpCancelCount = promauto.NewCounterVec( prometheus.CounterOpts{ - Name: "jetkvm_timesync_http_cancel_count", + Name: "jetkvm_timesync_http_cancel_total", Help: "The number of HTTP requests cancelled", }, []string{"url"}, diff --git a/internal/timesync/ntp.go b/internal/timesync/ntp.go index d45112c..c32de2a 100644 --- a/internal/timesync/ntp.go +++ b/internal/timesync/ntp.go @@ -1,6 +1,7 @@ package timesync import ( + "context" "math/rand/v2" "strconv" "time" @@ -21,9 +22,9 @@ var defaultNTPServers = []string{ "3.pool.ntp.org", } -func (t *TimeSync) queryNetworkTime() (now *time.Time, offset *time.Duration) { - chunkSize := 4 - ntpServers := t.ntpServers +func (t *TimeSync) queryNetworkTime(ntpServers []string) (now *time.Time, offset *time.Duration) { + chunkSize := int(t.networkConfig.TimeSyncParallel.ValueOr(4)) + t.l.Info().Strs("servers", ntpServers).Int("chunkSize", chunkSize).Msg("querying NTP servers") // shuffle the ntp servers to avoid always querying the same servers rand.Shuffle(len(ntpServers), func(i, j int) { ntpServers[i], ntpServers[j] = ntpServers[j], ntpServers[i] }) @@ -46,6 +47,10 @@ type ntpResult struct { func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (now *time.Time, offset *time.Duration) { results := make(chan *ntpResult, len(servers)) + + _, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + for _, server := range servers { go func(server string) { scopedLogger := t.l.With(). @@ -66,15 +71,25 @@ func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (no return } + if response.IsKissOfDeath() { + scopedLogger.Warn(). + Str("kiss_code", response.KissCode). + Msg("ignoring NTP server kiss of death") + results <- nil + return + } + + rtt := float64(response.RTT.Milliseconds()) + // set the last RTT metricNtpServerLastRTT.WithLabelValues( server, - ).Set(float64(response.RTT.Milliseconds())) + ).Set(rtt) // set the RTT histogram metricNtpServerRttHistogram.WithLabelValues( server, - ).Observe(float64(response.RTT.Milliseconds())) + ).Observe(rtt) // set the server info metricNtpServerInfo.WithLabelValues( @@ -91,10 +106,13 @@ func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (no scopedLogger.Info(). Str("time", now.Format(time.RFC3339)). Str("reference", response.ReferenceString()). - Str("rtt", response.RTT.String()). + Float64("rtt", rtt). Str("clockOffset", response.ClockOffset.String()). Uint8("stratum", response.Stratum). Msg("NTP server returned time") + + cancel() + results <- &ntpResult{ now: now, offset: &response.ClockOffset, diff --git a/internal/timesync/timesync.go b/internal/timesync/timesync.go index e956cf9..db1c96e 100644 --- a/internal/timesync/timesync.go +++ b/internal/timesync/timesync.go @@ -28,9 +28,8 @@ type TimeSync struct { syncLock *sync.Mutex l *zerolog.Logger - ntpServers []string - httpUrls []string - networkConfig *network.NetworkConfig + networkConfig *network.NetworkConfig + dhcpNtpAddresses []string rtcDevicePath string rtcDevice *os.File //nolint:unused @@ -64,14 +63,13 @@ func NewTimeSync(opts *TimeSyncOptions) *TimeSync { } t := &TimeSync{ - syncLock: &sync.Mutex{}, - l: opts.Logger, - rtcDevicePath: rtcDevice, - rtcLock: &sync.Mutex{}, - preCheckFunc: opts.PreCheckFunc, - ntpServers: defaultNTPServers, - httpUrls: defaultHTTPUrls, - networkConfig: opts.NetworkConfig, + syncLock: &sync.Mutex{}, + l: opts.Logger, + dhcpNtpAddresses: []string{}, + rtcDevicePath: rtcDevice, + rtcLock: &sync.Mutex{}, + preCheckFunc: opts.PreCheckFunc, + networkConfig: opts.NetworkConfig, } if t.rtcDevicePath != "" { @@ -82,34 +80,42 @@ func NewTimeSync(opts *TimeSyncOptions) *TimeSync { return t } +func (t *TimeSync) SetDhcpNtpAddresses(addresses []string) { + t.dhcpNtpAddresses = addresses +} + func (t *TimeSync) getSyncMode() SyncMode { syncMode := SyncMode{ + Ntp: true, + Http: true, + Ordering: []string{"ntp_dhcp", "ntp", "http"}, NtpUseFallback: true, HttpUseFallback: true, } - var syncModeString string if t.networkConfig != nil { - syncModeString = t.networkConfig.TimeSyncMode.String + switch t.networkConfig.TimeSyncMode.String { + case "ntp_only": + syncMode.Http = false + case "http_only": + syncMode.Ntp = false + } + if t.networkConfig.TimeSyncDisableFallback.Bool { syncMode.NtpUseFallback = false syncMode.HttpUseFallback = false } + + var syncOrdering = t.networkConfig.TimeSyncOrdering + if len(syncOrdering) > 0 { + syncMode.Ordering = syncOrdering + } } - switch syncModeString { - case "ntp_only": - syncMode.Ntp = true - case "http_only": - syncMode.Http = true - default: - syncMode.Ntp = true - syncMode.Http = true - } + t.l.Debug().Strs("Ordering", syncMode.Ordering).Bool("Ntp", syncMode.Ntp).Bool("Http", syncMode.Http).Bool("NtpUseFallback", syncMode.NtpUseFallback).Bool("HttpUseFallback", syncMode.HttpUseFallback).Msg("sync mode") return syncMode } - func (t *TimeSync) doTimeSync() { metricTimeSyncStatus.Set(0) for { @@ -154,16 +160,61 @@ func (t *TimeSync) Sync() error { offset *time.Duration ) - syncMode := t.getSyncMode() - metricTimeSyncCount.Inc() - if syncMode.Ntp { - now, offset = t.queryNetworkTime() - } + syncMode := t.getSyncMode() - if syncMode.Http && now == nil { - now = t.queryAllHttpTime() +Orders: + for _, mode := range syncMode.Ordering { + switch mode { + case "ntp_user_provided": + if syncMode.Ntp { + t.l.Info().Msg("using NTP custom servers") + now, offset = t.queryNetworkTime(t.networkConfig.TimeSyncNTPServers) + if now != nil { + t.l.Info().Str("source", "NTP").Time("now", *now).Msg("time obtained") + break Orders + } + } + case "ntp_dhcp": + if syncMode.Ntp { + t.l.Info().Msg("using NTP servers from DHCP") + now, offset = t.queryNetworkTime(t.dhcpNtpAddresses) + if now != nil { + t.l.Info().Str("source", "NTP DHCP").Time("now", *now).Msg("time obtained") + break Orders + } + } + case "ntp": + if syncMode.Ntp && syncMode.NtpUseFallback { + t.l.Info().Msg("using NTP fallback") + now, offset = t.queryNetworkTime(defaultNTPServers) + if now != nil { + t.l.Info().Str("source", "NTP fallback").Time("now", *now).Msg("time obtained") + break Orders + } + } + case "http_user_provided": + if syncMode.Http { + t.l.Info().Msg("using HTTP custom URLs") + now = t.queryAllHttpTime(t.networkConfig.TimeSyncHTTPUrls) + if now != nil { + t.l.Info().Str("source", "HTTP").Time("now", *now).Msg("time obtained") + break Orders + } + } + case "http": + if syncMode.Http && syncMode.HttpUseFallback { + t.l.Info().Msg("using HTTP fallback") + now = t.queryAllHttpTime(defaultHTTPUrls) + if now != nil { + t.l.Info().Str("source", "HTTP fallback").Time("now", *now).Msg("time obtained") + break Orders + } + } + default: + t.l.Warn().Str("mode", mode).Msg("unknown time sync mode, skipping") + } } if now == nil { diff --git a/internal/udhcpc/udhcpc.go b/internal/udhcpc/udhcpc.go index 70ac1b8..128ea66 100644 --- a/internal/udhcpc/udhcpc.go +++ b/internal/udhcpc/udhcpc.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "time" "github.com/fsnotify/fsnotify" @@ -149,6 +150,12 @@ func (c *DHCPClient) loadLeaseFile() error { } isFirstLoad := c.lease == nil + + // Skip processing if lease hasn't changed to avoid unnecessary wake-ups. + if reflect.DeepEqual(c.lease, lease) { + return nil + } + c.lease = lease if lease.IPAddress == nil { diff --git a/internal/usbgadget/config.go b/internal/usbgadget/config.go index 1c4f9c3..6d1bd39 100644 --- a/internal/usbgadget/config.go +++ b/internal/usbgadget/config.go @@ -30,8 +30,8 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{ attrs: gadgetAttributes{ "bcdUSB": "0x0200", // USB 2.0 "idVendor": "0x1d6b", // The Linux Foundation - "idProduct": "0104", // Multifunction Composite Gadget - "bcdDevice": "0100", + "idProduct": "0x0104", // Multifunction Composite Gadget + "bcdDevice": "0x0100", // USB2 }, configAttrs: gadgetAttributes{ "MaxPower": "250", // in unit of 2mA diff --git a/internal/usbgadget/hid_keyboard.go b/internal/usbgadget/hid_keyboard.go index df39f9c..a087145 100644 --- a/internal/usbgadget/hid_keyboard.go +++ b/internal/usbgadget/hid_keyboard.go @@ -144,15 +144,21 @@ func (u *UsbGadget) listenKeyboardEvents() { default: l.Trace().Msg("reading from keyboard") if u.keyboardHidFile == nil { - l.Error().Msg("keyboardHidFile is nil") + u.logWithSuppression("keyboardHidFileNil", 100, &l, nil, "keyboardHidFile is nil") + // show the error every 100 times to avoid spamming the logs time.Sleep(time.Second) continue } + // reset the counter + u.resetLogSuppressionCounter("keyboardHidFileNil") + n, err := u.keyboardHidFile.Read(buf) if err != nil { - l.Error().Err(err).Msg("failed to read") + u.logWithSuppression("keyboardHidFileRead", 100, &l, err, "failed to read") continue } + u.resetLogSuppressionCounter("keyboardHidFileRead") + l.Trace().Int("n", n).Bytes("buf", buf).Msg("got data from keyboard") if n != 1 { l.Trace().Int("n", n).Msg("expected 1 byte, got") @@ -196,12 +202,12 @@ func (u *UsbGadget) keyboardWriteHidFile(data []byte) error { _, err := u.keyboardHidFile.Write(data) if err != nil { - u.log.Error().Err(err).Msg("failed to write to hidg0") + u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0") u.keyboardHidFile.Close() u.keyboardHidFile = nil return err } - + u.resetLogSuppressionCounter("keyboardWriteHidFile") return nil } diff --git a/internal/usbgadget/hid_mouse_absolute.go b/internal/usbgadget/hid_mouse_absolute.go index f26a0e1..2718f20 100644 --- a/internal/usbgadget/hid_mouse_absolute.go +++ b/internal/usbgadget/hid_mouse_absolute.go @@ -12,9 +12,9 @@ var absoluteMouseConfig = gadgetConfigItem{ configPath: []string{"hid.usb1"}, attrs: gadgetAttributes{ "protocol": "2", - "subclass": "1", + "subclass": "0", "report_length": "6", - "no_out_endpoint": "1", + "no_out_endpoint": "1", }, reportDesc: absoluteMouseCombinedReportDesc, } @@ -76,11 +76,12 @@ func (u *UsbGadget) absMouseWriteHidFile(data []byte) error { _, err := u.absMouseHidFile.Write(data) if err != nil { - u.log.Error().Err(err).Msg("failed to write to hidg1") + u.logWithSuppression("absMouseWriteHidFile", 100, u.log, err, "failed to write to hidg1") u.absMouseHidFile.Close() u.absMouseHidFile = nil return err } + u.resetLogSuppressionCounter("absMouseWriteHidFile") return nil } diff --git a/internal/usbgadget/hid_mouse_relative.go b/internal/usbgadget/hid_mouse_relative.go index c8735c5..786f265 100644 --- a/internal/usbgadget/hid_mouse_relative.go +++ b/internal/usbgadget/hid_mouse_relative.go @@ -66,11 +66,12 @@ func (u *UsbGadget) relMouseWriteHidFile(data []byte) error { _, err := u.relMouseHidFile.Write(data) if err != nil { - u.log.Error().Err(err).Msg("failed to write to hidg2") + u.logWithSuppression("relMouseWriteHidFile", 100, u.log, err, "failed to write to hidg2") u.relMouseHidFile.Close() u.relMouseHidFile = nil return err } + u.resetLogSuppressionCounter("relMouseWriteHidFile") return nil } diff --git a/internal/usbgadget/usbgadget.go b/internal/usbgadget/usbgadget.go index 2eab822..cb70655 100644 --- a/internal/usbgadget/usbgadget.go +++ b/internal/usbgadget/usbgadget.go @@ -79,6 +79,9 @@ type UsbGadget struct { onKeyboardStateChange *func(state KeyboardState) log *zerolog.Logger + + logSuppressionCounter map[string]int + logSuppressionLock sync.Mutex } const configFSPath = "/sys/kernel/config" @@ -126,6 +129,8 @@ func newUsbGadget(name string, configMap map[string]gadgetConfigItem, enabledDev strictMode: config.strictMode, + logSuppressionCounter: make(map[string]int), + absMouseAccumulatedWheelY: 0, } if err := g.Init(); err != nil { diff --git a/internal/usbgadget/utils.go b/internal/usbgadget/utils.go index 7a6d1db..8654924 100644 --- a/internal/usbgadget/utils.go +++ b/internal/usbgadget/utils.go @@ -6,6 +6,8 @@ import ( "path/filepath" "strconv" "strings" + + "github.com/rs/zerolog" ) func joinPath(basePath string, paths []string) string { @@ -78,3 +80,33 @@ func compareFileContent(oldContent []byte, newContent []byte, looserMatch bool) return false } + +func (u *UsbGadget) logWithSuppression(counterName string, every int, logger *zerolog.Logger, err error, msg string, args ...interface{}) { + u.logSuppressionLock.Lock() + defer u.logSuppressionLock.Unlock() + + if _, ok := u.logSuppressionCounter[counterName]; !ok { + u.logSuppressionCounter[counterName] = 0 + } else { + u.logSuppressionCounter[counterName]++ + } + + l := logger.With().Int("counter", u.logSuppressionCounter[counterName]).Logger() + + if u.logSuppressionCounter[counterName]%every == 0 { + if err != nil { + l.Error().Err(err).Msgf(msg, args...) + } else { + l.Error().Msgf(msg, args...) + } + } +} + +func (u *UsbGadget) resetLogSuppressionCounter(counterName string) { + u.logSuppressionLock.Lock() + defer u.logSuppressionLock.Unlock() + + if _, ok := u.logSuppressionCounter[counterName]; !ok { + u.logSuppressionCounter[counterName] = 0 + } +} diff --git a/jsonrpc.go b/jsonrpc.go index 258828a..e930f49 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -681,10 +681,11 @@ func rpcResetConfig() error { } type DCPowerState struct { - IsOn bool `json:"isOn"` - Voltage float64 `json:"voltage"` - Current float64 `json:"current"` - Power float64 `json:"power"` + IsOn bool `json:"isOn"` + Voltage float64 `json:"voltage"` + Current float64 `json:"current"` + Power float64 `json:"power"` + RestoreState int `json:"restoreState"` } func rpcGetDCPowerState() (DCPowerState, error) { @@ -700,6 +701,15 @@ func rpcSetDCPowerState(enabled bool) error { return nil } +func rpcSetDCRestoreState(state int) error { + logger.Info().Int("state", state).Msg("Setting DC restore state") + err := setDCRestoreState(state) + if err != nil { + return fmt.Errorf("failed to set DC restore state: %w", err) + } + return nil +} + func rpcGetActiveExtension() (string, error) { return config.ActiveExtension, nil } @@ -1088,6 +1098,7 @@ var rpcHandlers = map[string]RPCHandler{ "getBacklightSettings": {Func: rpcGetBacklightSettings}, "getDCPowerState": {Func: rpcGetDCPowerState}, "setDCPowerState": {Func: rpcSetDCPowerState, Params: []string{"enabled"}}, + "setDCRestoreState": {Func: rpcSetDCRestoreState, Params: []string{"state"}}, "getActiveExtension": {Func: rpcGetActiveExtension}, "setActiveExtension": {Func: rpcSetActiveExtension, Params: []string{"extensionId"}}, "getATXState": {Func: rpcGetATXState}, diff --git a/native.go b/native.go index 496f580..9807206 100644 --- a/native.go +++ b/native.go @@ -8,6 +8,8 @@ import ( "io" "net" "os" + "os/exec" + "strings" "sync" "time" @@ -41,6 +43,11 @@ var ongoingRequests = make(map[int32]chan *CtrlResponse) var lock = &sync.Mutex{} +var ( + nativeCmd *exec.Cmd + nativeCmdLock = &sync.Mutex{} +) + func CallCtrlAction(action string, params map[string]interface{}) (*CtrlResponse, error) { lock.Lock() defer lock.Unlock() @@ -129,16 +136,26 @@ func StartNativeSocketServer(socketPath string, handleClient func(net.Conn), isC scopedLogger.Info().Msg("server listening") go func() { - conn, err := listener.Accept() - listener.Close() - if err != nil { - scopedLogger.Warn().Err(err).Msg("failed to accept socket") + for { + conn, err := listener.Accept() + + if err != nil { + scopedLogger.Warn().Err(err).Msg("failed to accept socket") + continue + } + if isCtrl { + // check if the channel is closed + select { + case <-ctrlClientConnected: + scopedLogger.Debug().Msg("ctrl client reconnected") + default: + close(ctrlClientConnected) + scopedLogger.Debug().Msg("first native ctrl socket client connected") + } + } + + go handleClient(conn) } - if isCtrl { - close(ctrlClientConnected) - scopedLogger.Debug().Msg("first native ctrl socket client connected") - } - handleClient(conn) }() return listener @@ -235,6 +252,58 @@ func handleVideoClient(conn net.Conn) { } } +func startNativeBinaryWithLock(binaryPath string) (*exec.Cmd, error) { + nativeCmdLock.Lock() + defer nativeCmdLock.Unlock() + + cmd, err := startNativeBinary(binaryPath) + if err != nil { + return nil, err + } + nativeCmd = cmd + return cmd, nil +} + +func restartNativeBinary(binaryPath string) error { + time.Sleep(10 * time.Second) + // restart the binary + nativeLogger.Info().Msg("restarting jetkvm_native binary") + cmd, err := startNativeBinary(binaryPath) + if err != nil { + nativeLogger.Warn().Err(err).Msg("failed to restart binary") + } + nativeCmd = cmd + + // reset the display state + time.Sleep(1 * time.Second) + clearDisplayState() + updateStaticContents() + requestDisplayUpdate(true) + + return err +} + +func superviseNativeBinary(binaryPath string) error { + nativeCmdLock.Lock() + defer nativeCmdLock.Unlock() + + if nativeCmd == nil || nativeCmd.Process == nil { + return restartNativeBinary(binaryPath) + } + + err := nativeCmd.Wait() + + if err == nil { + nativeLogger.Info().Err(err).Msg("jetkvm_native binary exited with no error") + } else if exiterr, ok := err.(*exec.ExitError); ok { + nativeLogger.Warn().Int("exit_code", exiterr.ExitCode()).Msg("jetkvm_native binary exited with error") + } else { + nativeLogger.Warn().Err(err).Msg("jetkvm_native binary exited with unknown error") + } + + return restartNativeBinary(binaryPath) +} + func ExtractAndRunNativeBin() error { binaryPath := "/userdata/jetkvm/bin/jetkvm_native" if err := ensureBinaryUpdated(binaryPath); err != nil { @@ -246,12 +315,28 @@ func ExtractAndRunNativeBin() error { return fmt.Errorf("failed to make binary executable: %w", err) } // Run the binary in the background - cmd, err := startNativeBinary(binaryPath) + cmd, err := startNativeBinaryWithLock(binaryPath) if err != nil { return fmt.Errorf("failed to start binary: %w", err) } - //TODO: add auto restart + // check if the binary is still running every 10 seconds + go func() { + for { + select { + case <-appCtx.Done(): + nativeLogger.Info().Msg("stopping native binary supervisor") + return + default: + err := superviseNativeBinary(binaryPath) + if err != nil { + nativeLogger.Warn().Err(err).Msg("failed to supervise native binary") + time.Sleep(1 * time.Second) // Add a short delay to prevent rapid successive calls + } + } + } + }() + go func() { <-appCtx.Done() nativeLogger.Info().Int("pid", cmd.Process.Pid).Msg("killing process") @@ -282,6 +367,22 @@ func shouldOverwrite(destPath string, srcHash []byte) bool { return !bytes.Equal(srcHash, dstHash) } +func getNativeSha256() ([]byte, error) { + version, err := resource.ResourceFS.ReadFile("jetkvm_native.sha256") + if err != nil { + return nil, err + } + return version, nil +} + +func GetNativeVersion() (string, error) { + version, err := getNativeSha256() + if err != nil { + return "", err + } + return strings.TrimSpace(string(version)), nil +} + func ensureBinaryUpdated(destPath string) error { srcFile, err := resource.ResourceFS.Open("jetkvm_native") if err != nil { @@ -289,7 +390,7 @@ func ensureBinaryUpdated(destPath string) error { } defer srcFile.Close() - srcHash, err := resource.ResourceFS.ReadFile("jetkvm_native.sha256") + srcHash, err := getNativeSha256() if err != nil { nativeLogger.Debug().Msg("error reading embedded jetkvm_native.sha256, proceeding with update") srcHash = nil diff --git a/network.go b/network.go index 8d9261b..d4f46e7 100644 --- a/network.go +++ b/network.go @@ -19,8 +19,19 @@ func networkStateChanged() { // do not block the main thread go waitCtrlAndRequestDisplayUpdate(true) + if timeSync != nil { + if networkState != nil { + timeSync.SetDhcpNtpAddresses(networkState.NtpAddressesString()) + } + + if err := timeSync.Sync(); err != nil { + networkLogger.Error().Err(err).Msg("failed to sync time after network state change") + } + } + // always restart mDNS when the network state changes if mDNS != nil { + _ = mDNS.SetListenOptions(config.NetworkConfig.GetMDNSMode()) _ = mDNS.SetLocalNames([]string{ networkState.GetHostname(), networkState.GetFQDN(), @@ -54,14 +65,6 @@ func initNetwork() error { OnConfigChange: func(networkConfig *network.NetworkConfig) { config.NetworkConfig = networkConfig networkStateChanged() - - if mDNS != nil { - _ = mDNS.SetListenOptions(networkConfig.GetMDNSMode()) - _ = mDNS.SetLocalNames([]string{ - networkState.GetHostname(), - networkState.GetFQDN(), - }, true) - } }, }) diff --git a/ota.go b/ota.go index cf97cc0..45603f0 100644 --- a/ota.go +++ b/ota.go @@ -50,6 +50,10 @@ const UpdateMetadataUrl = "https://api.jetkvm.com/releases" var builtAppVersion = "0.1.0+dev" +func GetBuiltAppVersion() string { + return builtAppVersion +} + func GetLocalVersion() (systemVersion *semver.Version, appVersion *semver.Version, err error) { appVersion, err = semver.NewVersion(builtAppVersion) if err != nil { diff --git a/serial.go b/serial.go index f4dd5b5..5439d13 100644 --- a/serial.go +++ b/serial.go @@ -128,6 +128,7 @@ func pressATXResetButton(duration time.Duration) error { func mountDCControl() error { _ = port.SetMode(defaultMode) + registerDCMetrics() go runDCControl() return nil } @@ -142,6 +143,7 @@ var dcState DCPowerState func runDCControl() { scopedLogger := serialLogger.With().Str("service", "dc_control").Logger() reader := bufio.NewReader(port) + hasRestoreFeature := false for { line, err := reader.ReadString('\n') if err != nil { @@ -151,7 +153,13 @@ func runDCControl() { // Split the line by semicolon parts := strings.Split(strings.TrimSpace(line), ";") - if len(parts) != 4 { + if len(parts) == 5 { + scopedLogger.Debug().Str("line", line).Msg("Detected DC extension with restore feature") + hasRestoreFeature = true + } else if len(parts) == 4 { + scopedLogger.Debug().Str("line", line).Msg("Detected DC extension without restore feature") + hasRestoreFeature = false + } else { scopedLogger.Warn().Str("line", line).Msg("Invalid line") continue } @@ -163,6 +171,17 @@ func runDCControl() { continue } dcState.IsOn = powerState == 1 + if hasRestoreFeature { + restoreState, err := strconv.Atoi(parts[4]) + if err != nil { + scopedLogger.Warn().Err(err).Msg("Invalid restore state") + continue + } + dcState.RestoreState = restoreState + } else { + // -1 means not supported + dcState.RestoreState = -1 + } milliVolts, err := strconv.ParseFloat(parts[1], 64) if err != nil { scopedLogger.Warn().Err(err).Msg("Invalid voltage") @@ -188,6 +207,9 @@ func runDCControl() { dcState.Current = amps dcState.Power = watts + // Update Prometheus metrics + updateDCMetrics(dcState) + if currentSession != nil { writeJSONRPCEvent("dcState", dcState, currentSession) } @@ -210,6 +232,25 @@ func setDCPowerState(on bool) error { return nil } +func setDCRestoreState(state int) error { + _, err := port.Write([]byte("\n")) + if err != nil { + return err + } + command := "RESTORE_MODE_OFF\n" + switch state { + case 1: + command = "RESTORE_MODE_ON\n" + case 2: + command = "RESTORE_MODE_LAST_STATE\n" + } + _, err = port.Write([]byte(command)) + if err != nil { + return err + } + return nil +} + var defaultMode = &serial.Mode{ BaudRate: 115200, DataBits: 8, diff --git a/terminal.go b/terminal.go index e98b4de..e06e5cd 100644 --- a/terminal.go +++ b/terminal.go @@ -1,6 +1,7 @@ package kvm import ( + "bytes" "encoding/json" "io" "os" @@ -55,18 +56,23 @@ func handleTerminalChannel(d *webrtc.DataChannel) { return } if msg.IsString { - var size TerminalSize - err := json.Unmarshal([]byte(msg.Data), &size) - if err == nil { - err = pty.Setsize(ptmx, &pty.Winsize{ - Rows: uint16(size.Rows), - Cols: uint16(size.Cols), - }) + maybeJson := bytes.TrimSpace(msg.Data) + // Cheap check to see if this resembles JSON + if len(maybeJson) > 1 && maybeJson[0] == '{' && maybeJson[len(maybeJson)-1] == '}' { + var size TerminalSize + err := json.Unmarshal(maybeJson, &size) if err == nil { - return + err = pty.Setsize(ptmx, &pty.Winsize{ + Rows: uint16(size.Rows), + Cols: uint16(size.Cols), + }) + if err == nil { + scopedLogger.Info().Int("rows", size.Rows).Int("cols", size.Cols).Msg("Set terminal size") + return + } } + scopedLogger.Warn().Err(err).Msg("Failed to parse terminal size") } - scopedLogger.Warn().Err(err).Msg("Failed to parse terminal size") } _, err := ptmx.Write(msg.Data) if err != nil { diff --git a/ui/package-lock.json b/ui/package-lock.json index 8ac57a1..6380015 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -8,21 +8,21 @@ "name": "kvm-ui", "version": "0.0.0", "dependencies": { - "@headlessui/react": "^2.2.3", + "@headlessui/react": "^2.2.4", "@headlessui/tailwindcss": "^0.2.2", "@heroicons/react": "^2.2.0", - "@vitejs/plugin-basic-ssl": "^2.0.0", + "@vitejs/plugin-basic-ssl": "^2.1.0", "@xterm/addon-clipboard": "^0.1.0", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-unicode11": "^0.8.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/addon-webgl": "^0.18.0", "@xterm/xterm": "^5.5.0", - "cva": "^1.0.0-beta.3", + "cva": "^1.0.0-beta.4", "dayjs": "^1.11.13", "eslint-import-resolver-alias": "^1.1.2", - "focus-trap-react": "^11.0.3", - "framer-motion": "^12.11.4", + "focus-trap-react": "^11.0.4", + "framer-motion": "^12.23.0", "lodash.throttle": "^4.1.1", "mini-svg-data-uri": "^1.4.4", "react": "^19.1.0", @@ -31,42 +31,42 @@ "react-hot-toast": "^2.5.2", "react-icons": "^5.5.0", "react-router-dom": "^6.22.3", - "react-simple-keyboard": "^3.8.72", + "react-simple-keyboard": "^3.8.89", "react-use-websocket": "^4.13.0", "react-xtermjs": "^1.0.10", "recharts": "^2.15.3", - "tailwind-merge": "^3.3.0", + "tailwind-merge": "^3.3.1", "usehooks-ts": "^3.1.1", - "validator": "^13.15.0", + "validator": "^13.15.15", "zustand": "^4.5.2" }, "devDependencies": { - "@eslint/compat": "^1.2.9", + "@eslint/compat": "^1.3.1", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "^9.26.0", + "@eslint/js": "^9.30.1", "@tailwindcss/forms": "^0.5.10", - "@tailwindcss/postcss": "^4.1.7", + "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/typography": "^0.5.16", - "@tailwindcss/vite": "^4.1.7", - "@types/react": "^19.1.4", - "@types/react-dom": "^19.1.5", + "@tailwindcss/vite": "^4.1.11", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", "@types/semver": "^7.7.0", - "@types/validator": "^13.15.0", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "@vitejs/plugin-react-swc": "^3.9.0", + "@types/validator": "^13.15.2", + "@typescript-eslint/eslint-plugin": "^8.35.1", + "@typescript-eslint/parser": "^8.35.1", + "@vitejs/plugin-react-swc": "^3.10.2", "autoprefixer": "^10.4.21", - "eslint": "^9.26.0", + "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.1.0", - "postcss": "^8.5.3", - "prettier": "^3.5.3", - "prettier-plugin-tailwindcss": "^0.6.11", - "tailwindcss": "^4.1.7", + "globals": "^16.3.0", + "postcss": "^8.5.6", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.13", + "tailwindcss": "^4.1.11", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-tsconfig-paths": "^5.1.4" @@ -103,18 +103,18 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "cpu": [ "ppc64" ], @@ -128,9 +128,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "cpu": [ "arm" ], @@ -144,9 +144,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "cpu": [ "arm64" ], @@ -160,9 +160,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "cpu": [ "x64" ], @@ -176,9 +176,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "cpu": [ "arm64" ], @@ -192,9 +192,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "cpu": [ "x64" ], @@ -208,9 +208,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "cpu": [ "arm64" ], @@ -224,9 +224,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "cpu": [ "x64" ], @@ -240,9 +240,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "cpu": [ "arm" ], @@ -256,9 +256,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "cpu": [ "arm64" ], @@ -272,9 +272,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "cpu": [ "ia32" ], @@ -288,9 +288,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "cpu": [ "loong64" ], @@ -304,9 +304,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "cpu": [ "mips64el" ], @@ -320,9 +320,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "cpu": [ "ppc64" ], @@ -336,9 +336,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "cpu": [ "riscv64" ], @@ -352,9 +352,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "cpu": [ "s390x" ], @@ -368,9 +368,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "cpu": [ "x64" ], @@ -384,9 +384,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", "cpu": [ "arm64" ], @@ -400,9 +400,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "cpu": [ "x64" ], @@ -416,9 +416,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", "cpu": [ "arm64" ], @@ -432,9 +432,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "cpu": [ "x64" ], @@ -448,9 +448,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "cpu": [ "x64" ], @@ -464,9 +464,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "cpu": [ "arm64" ], @@ -480,9 +480,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "cpu": [ "ia32" ], @@ -496,9 +496,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "cpu": [ "x64" ], @@ -539,16 +539,16 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", - "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.1.tgz", + "integrity": "sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": "^9.10.0" + "eslint": "^8.40 || 9" }, "peerDependenciesMeta": { "eslint": { @@ -557,9 +557,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.6", @@ -571,9 +571,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -627,9 +627,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", - "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", + "version": "9.30.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.1.tgz", + "integrity": "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -648,35 +648,47 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@floating-ui/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", - "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", + "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", - "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", + "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.0", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.7.2", + "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react": { @@ -695,12 +707,12 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz", + "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@floating-ui/dom": "^1.7.2" }, "peerDependencies": { "react": ">=16.8.0", @@ -708,21 +720,21 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, "node_modules/@headlessui/react": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.3.tgz", - "integrity": "sha512-hgOJGXPifPlOczIeSwX8OjLWRJ5XdYApZFf7DeCbCrO1PXHkPhNTRrA9ZwJsgAG7SON1i2JcvIreF/kbgtJeaQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz", + "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.16", "@react-aria/focus": "^3.20.2", "@react-aria/interactions": "^3.25.0", - "@tanstack/react-virtual": "^3.13.6", + "@tanstack/react-virtual": "^3.13.9", "use-sync-external-store": "^1.5.0" }, "engines": { @@ -829,18 +841,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -853,27 +861,17 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -920,14 +918,14 @@ } }, "node_modules/@react-aria/focus": { - "version": "3.20.3", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.3.tgz", - "integrity": "sha512-rR5uZUMSY4xLHmpK/I8bP1V6vUNHFo33gTvrvNUsAKKqvMfa7R2nu5A6v97dr5g6tVH6xzpdkPsOJCWh90H2cw==", + "version": "3.20.5", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.5.tgz", + "integrity": "sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.25.1", - "@react-aria/utils": "^3.29.0", - "@react-types/shared": "^3.29.1", + "@react-aria/interactions": "^3.25.3", + "@react-aria/utils": "^3.29.1", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -937,15 +935,15 @@ } }, "node_modules/@react-aria/interactions": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.1.tgz", - "integrity": "sha512-ntLrlgqkmZupbbjekz3fE/n3eQH2vhncx8gUp0+N+GttKWevx7jos11JUBjnJwb1RSOPgRUFcrluOqBp0VgcfQ==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.3.tgz", + "integrity": "sha512-J1bhlrNtjPS/fe5uJQ+0c7/jiXniwa4RQlP+Emjfc/iuqpW2RhbF9ou5vROcLzWIyaW8tVMZ468J68rAs/aZ5A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.8", - "@react-aria/utils": "^3.29.0", - "@react-stately/flags": "^3.1.1", - "@react-types/shared": "^3.29.1", + "@react-aria/ssr": "^3.9.9", + "@react-aria/utils": "^3.29.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -954,9 +952,9 @@ } }, "node_modules/@react-aria/ssr": { - "version": "3.9.8", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.8.tgz", - "integrity": "sha512-lQDE/c9uTfBSDOjaZUJS8xP2jCKVk4zjQeIlCH90xaLhHDgbpCdns3xvFpJJujfj3nI4Ll9K7A+ONUBDCASOuw==", + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.9.tgz", + "integrity": "sha512-2P5thfjfPy/np18e5wD4WPt8ydNXhij1jwA8oehxZTFqlgVMGXzcWKxTb4RtJrLFsqPO7RUQTiY8QJk0M4Vy2g==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -969,15 +967,15 @@ } }, "node_modules/@react-aria/utils": { - "version": "3.29.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.0.tgz", - "integrity": "sha512-jSOrZimCuT1iKNVlhjIxDkAhgF7HSp3pqyT6qjg/ZoA0wfqCi/okmrMPiWSAKBnkgX93N8GYTLT3CIEO6WZe9Q==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.1.tgz", + "integrity": "sha512-yXMFVJ73rbQ/yYE/49n5Uidjw7kh192WNN9PNQGV0Xoc7EJUlSOxqhnpHmYTyO0EotJ8fdM1fMH8durHjUSI8g==", "license": "Apache-2.0", "dependencies": { - "@react-aria/ssr": "^3.9.8", - "@react-stately/flags": "^3.1.1", - "@react-stately/utils": "^3.10.6", - "@react-types/shared": "^3.29.1", + "@react-aria/ssr": "^3.9.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.7", + "@react-types/shared": "^3.30.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -987,18 +985,18 @@ } }, "node_modules/@react-stately/flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.1.tgz", - "integrity": "sha512-XPR5gi5LfrPdhxZzdIlJDz/B5cBf63l4q6/AzNqVWFKgd0QqY5LvWJftXkklaIUpKSJkIKQb8dphuZXDtkWNqg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@react-stately/utils": { - "version": "3.10.6", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.6.tgz", - "integrity": "sha512-O76ip4InfTTzAJrg8OaZxKU4vvjMDOpfA/PGNOytiXwBbkct2ZeZwaimJ8Bt9W1bj5VsZ81/o/tW4BacbdDOMA==", + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.7.tgz", + "integrity": "sha512-cWvjGAocvy4abO9zbr6PW6taHgF24Mwy/LbQ4TC4Aq3tKdKDntxyD+sh7AkSRfJRT2ccMVaHVv2+FfHThd3PKQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -1008,9 +1006,9 @@ } }, "node_modules/@react-types/shared": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.29.1.tgz", - "integrity": "sha512-KtM+cDf2CXoUX439rfEhbnEdAgFZX20UP2A35ypNIawR7/PFFPjQDWyA2EnClCcW/dLWJDEPX2U8+EJff8xqmQ==", + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.30.0.tgz", + "integrity": "sha512-COIazDAx1ncDg046cTJ8SFYsX8aS3lB/08LDnbkH/SkdYrFPWDlXMrO/sUam8j1WWM+PJ+4d1mj7tODIKNiFog==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -1025,10 +1023,17 @@ "node": ">=14.0.0" } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.11", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.11.tgz", + "integrity": "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", - "integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", + "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", "cpu": [ "arm" ], @@ -1039,9 +1044,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz", - "integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", + "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", "cpu": [ "arm64" ], @@ -1052,9 +1057,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz", - "integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", + "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", "cpu": [ "arm64" ], @@ -1065,9 +1070,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz", - "integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", + "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", "cpu": [ "x64" ], @@ -1078,9 +1083,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz", - "integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", + "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", "cpu": [ "arm64" ], @@ -1091,9 +1096,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz", - "integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", + "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", "cpu": [ "x64" ], @@ -1104,9 +1109,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz", - "integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", + "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", "cpu": [ "arm" ], @@ -1117,9 +1122,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz", - "integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", + "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", "cpu": [ "arm" ], @@ -1130,9 +1135,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz", - "integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", + "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", "cpu": [ "arm64" ], @@ -1143,9 +1148,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz", - "integrity": "sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", + "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", "cpu": [ "arm64" ], @@ -1156,9 +1161,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz", - "integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", + "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", "cpu": [ "loong64" ], @@ -1169,9 +1174,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz", - "integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", + "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", "cpu": [ "ppc64" ], @@ -1182,9 +1187,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz", - "integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", + "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", "cpu": [ "riscv64" ], @@ -1195,9 +1200,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz", - "integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", + "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", "cpu": [ "riscv64" ], @@ -1208,9 +1213,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz", - "integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", + "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", "cpu": [ "s390x" ], @@ -1221,9 +1226,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz", - "integrity": "sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", + "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", "cpu": [ "x64" ], @@ -1234,9 +1239,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.0.tgz", - "integrity": "sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", + "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", "cpu": [ "x64" ], @@ -1247,9 +1252,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz", - "integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", + "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", "cpu": [ "arm64" ], @@ -1260,9 +1265,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz", - "integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", + "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", "cpu": [ "ia32" ], @@ -1273,9 +1278,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz", - "integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", + "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", "cpu": [ "x64" ], @@ -1292,15 +1297,15 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz", - "integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.9.tgz", + "integrity": "sha512-O+LfT2JlVMsIMWG9x+rdxg8GzpzeGtCZQfXV7cKc1PjIKUkLFf1QJ7okuseA4f/9vncu37dQ2ZcRrPKy0Ndd5g==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.21" + "@swc/types": "^0.1.23" }, "engines": { "node": ">=10" @@ -1310,16 +1315,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.11.24", - "@swc/core-darwin-x64": "1.11.24", - "@swc/core-linux-arm-gnueabihf": "1.11.24", - "@swc/core-linux-arm64-gnu": "1.11.24", - "@swc/core-linux-arm64-musl": "1.11.24", - "@swc/core-linux-x64-gnu": "1.11.24", - "@swc/core-linux-x64-musl": "1.11.24", - "@swc/core-win32-arm64-msvc": "1.11.24", - "@swc/core-win32-ia32-msvc": "1.11.24", - "@swc/core-win32-x64-msvc": "1.11.24" + "@swc/core-darwin-arm64": "1.12.9", + "@swc/core-darwin-x64": "1.12.9", + "@swc/core-linux-arm-gnueabihf": "1.12.9", + "@swc/core-linux-arm64-gnu": "1.12.9", + "@swc/core-linux-arm64-musl": "1.12.9", + "@swc/core-linux-x64-gnu": "1.12.9", + "@swc/core-linux-x64-musl": "1.12.9", + "@swc/core-win32-arm64-msvc": "1.12.9", + "@swc/core-win32-ia32-msvc": "1.12.9", + "@swc/core-win32-x64-msvc": "1.12.9" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -1331,9 +1336,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz", - "integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.9.tgz", + "integrity": "sha512-GACFEp4nD6V+TZNR2JwbMZRHB+Yyvp14FrcmB6UCUYmhuNWjkxi+CLnEvdbuiKyQYv0zA+TRpCHZ+whEs6gwfA==", "cpu": [ "arm64" ], @@ -1348,9 +1353,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz", - "integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.12.9.tgz", + "integrity": "sha512-hv2kls7Ilkm2EpeJz+I9MCil7pGS3z55ZAgZfxklEuYsxpICycxeH+RNRv4EraggN44ms+FWCjtZFu0LGg2V3g==", "cpu": [ "x64" ], @@ -1365,9 +1370,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz", - "integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.12.9.tgz", + "integrity": "sha512-od9tDPiG+wMU9wKtd6y3nYJdNqgDOyLdgRRcrj1/hrbHoUPOM8wZQZdwQYGarw63iLXGgsw7t5HAF9Yc51ilFA==", "cpu": [ "arm" ], @@ -1382,9 +1387,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz", - "integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.9.tgz", + "integrity": "sha512-6qx1ka9LHcLzxIgn2Mros+CZLkHK2TawlXzi/h7DJeNnzi8F1Hw0Yzjp8WimxNCg6s2n+o3jnmin1oXB7gg8rw==", "cpu": [ "arm64" ], @@ -1399,9 +1404,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz", - "integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.12.9.tgz", + "integrity": "sha512-yghFZWKPVVGbUdqiD7ft23G0JX6YFGDJPz9YbLLAwGuKZ9th3/jlWoQDAw1Naci31LQhVC+oIji6ozihSuwB2A==", "cpu": [ "arm64" ], @@ -1416,9 +1421,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz", - "integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.9.tgz", + "integrity": "sha512-SFUxyhWLZRNL8QmgGNqdi2Q43PNyFVkRZ2zIif30SOGFSxnxcf2JNeSeBgKIGVgaLSuk6xFVVCtJ3KIeaStgRg==", "cpu": [ "x64" ], @@ -1433,9 +1438,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz", - "integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.12.9.tgz", + "integrity": "sha512-9FB0wM+6idCGTI20YsBNBg9xSWtkDBymnpaTCsZM3qDc0l4uOpJMqbfWhQvp17x7r/ulZfb2QY8RDvQmCL6AcQ==", "cpu": [ "x64" ], @@ -1450,9 +1455,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz", - "integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.12.9.tgz", + "integrity": "sha512-zHOusMVbOH9ik5RtRrMiGzLpKwxrPXgXkBm3SbUCa65HAdjV33NZ0/R9Rv1uPESALtEl2tzMYLUxYA5ECFDFhA==", "cpu": [ "arm64" ], @@ -1467,9 +1472,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz", - "integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.12.9.tgz", + "integrity": "sha512-aWZf0PqE0ot7tCuhAjRkDFf41AzzSQO0x2xRfTbnhpROp57BRJ/N5eee1VULO/UA2PIJRG7GKQky5bSGBYlFug==", "cpu": [ "ia32" ], @@ -1484,9 +1489,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz", - "integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==", + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.12.9.tgz", + "integrity": "sha512-C25fYftXOras3P3anSUeXXIpxmEkdAcsIL9yrr0j1xepTZ/yKwpnQ6g3coj8UXdeJy4GTVlR6+Ow/QiBgZQNOg==", "cpu": [ "x64" ], @@ -1517,9 +1522,9 @@ } }, "node_modules/@swc/types": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", - "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", + "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1540,9 +1545,9 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz", - "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1552,13 +1557,13 @@ "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.7" + "tailwindcss": "4.1.11" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz", - "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1570,24 +1575,24 @@ "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.7", - "@tailwindcss/oxide-darwin-arm64": "4.1.7", - "@tailwindcss/oxide-darwin-x64": "4.1.7", - "@tailwindcss/oxide-freebsd-x64": "4.1.7", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.7", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.7", - "@tailwindcss/oxide-linux-x64-musl": "4.1.7", - "@tailwindcss/oxide-wasm32-wasi": "4.1.7", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.7" + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz", - "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", "cpu": [ "arm64" ], @@ -1602,9 +1607,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz", - "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", "cpu": [ "arm64" ], @@ -1619,9 +1624,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz", - "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", "cpu": [ "x64" ], @@ -1636,9 +1641,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz", - "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", "cpu": [ "x64" ], @@ -1653,9 +1658,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz", - "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", "cpu": [ "arm" ], @@ -1670,9 +1675,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz", - "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", "cpu": [ "arm64" ], @@ -1687,9 +1692,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz", - "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", "cpu": [ "arm64" ], @@ -1704,9 +1709,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz", - "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", "cpu": [ "x64" ], @@ -1721,9 +1726,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz", - "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", "cpu": [ "x64" ], @@ -1738,9 +1743,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz", - "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1759,7 +1764,7 @@ "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.9", + "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, @@ -1768,9 +1773,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz", - "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", "cpu": [ "arm64" ], @@ -1785,9 +1790,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz", - "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", "cpu": [ "x64" ], @@ -1802,17 +1807,17 @@ } }, "node_modules/@tailwindcss/postcss": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.7.tgz", - "integrity": "sha512-88g3qmNZn7jDgrrcp3ZXEQfp9CVox7xjP1HN2TFKI03CltPVd/c61ydn5qJJL8FYunn0OqBaW5HNUga0kmPVvw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.11.tgz", + "integrity": "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.7", - "@tailwindcss/oxide": "4.1.7", + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", "postcss": "^8.4.41", - "tailwindcss": "4.1.7" + "tailwindcss": "4.1.11" } }, "node_modules/@tailwindcss/typography": { @@ -1832,27 +1837,27 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz", - "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", + "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.7", - "@tailwindcss/oxide": "4.1.7", - "tailwindcss": "4.1.7" + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "tailwindcss": "4.1.11" }, "peerDependencies": { - "vite": "^5.2.0 || ^6" + "vite": "^5.2.0 || ^6 || ^7" } }, "node_modules/@tanstack/react-virtual": { - "version": "3.13.8", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.8.tgz", - "integrity": "sha512-meS2AanUg50f3FBSNoAdBSRAh8uS0ue01qm7zrw65KGJtiXB9QXfybqZwkh4uFpRv2iX/eu5tjcH5wqUpwYLPg==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", + "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.13.8" + "@tanstack/virtual-core": "3.13.12" }, "funding": { "type": "github", @@ -1864,9 +1869,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.13.8", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.8.tgz", - "integrity": "sha512-BT6w89Hqy7YKaWewYzmecXQzcJh6HTBbKYJIIkMaNU49DZ06LoTV3z32DWWEdUsgW6n1xTmwTLs4GtWrZC261w==", + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", + "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", "license": "MIT", "funding": { "type": "github", @@ -1937,9 +1942,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/json-schema": { @@ -1955,18 +1960,18 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz", - "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "license": "MIT", "dependencies": { "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "19.1.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz", - "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "license": "MIT", "peerDependencies": { "@types/react": "^19.0.0" @@ -1980,24 +1985,24 @@ "license": "MIT" }, "node_modules/@types/validator": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.0.tgz", - "integrity": "sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA==", + "version": "13.15.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", + "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", - "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.1.tgz", + "integrity": "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/type-utils": "8.32.1", - "@typescript-eslint/utils": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/scope-manager": "8.35.1", + "@typescript-eslint/type-utils": "8.35.1", + "@typescript-eslint/utils": "8.35.1", + "@typescript-eslint/visitor-keys": "8.35.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2011,15 +2016,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.35.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -2027,16 +2032,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", - "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.1.tgz", + "integrity": "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/typescript-estree": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/scope-manager": "8.35.1", + "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/typescript-estree": "8.35.1", + "@typescript-eslint/visitor-keys": "8.35.1", "debug": "^4.3.4" }, "engines": { @@ -2051,15 +2056,37 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", - "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.1.tgz", + "integrity": "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1" + "@typescript-eslint/tsconfig-utils": "^8.35.1", + "@typescript-eslint/types": "^8.35.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.1.tgz", + "integrity": "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/visitor-keys": "8.35.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2069,15 +2096,32 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.1.tgz", + "integrity": "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", - "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.1.tgz", + "integrity": "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.1", - "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/typescript-estree": "8.35.1", + "@typescript-eslint/utils": "8.35.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2094,9 +2138,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", - "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.1.tgz", + "integrity": "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==", "dev": true, "license": "MIT", "engines": { @@ -2108,14 +2152,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", - "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.1.tgz", + "integrity": "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/project-service": "8.35.1", + "@typescript-eslint/tsconfig-utils": "8.35.1", + "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/visitor-keys": "8.35.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2135,9 +2181,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2161,16 +2207,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", - "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.1.tgz", + "integrity": "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/typescript-estree": "8.32.1" + "@typescript-eslint/scope-manager": "8.35.1", + "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/typescript-estree": "8.35.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2185,14 +2231,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", - "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "version": "8.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.1.tgz", + "integrity": "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.35.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2203,9 +2249,9 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2216,28 +2262,29 @@ } }, "node_modules/@vitejs/plugin-basic-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.0.0.tgz", - "integrity": "sha512-gc9Tjg8bUxBVSTzeWT3Njc0Cl3PakHFKdNfABnZWiUgbxqmHDEn7uECv3fHVylxoYgNzAcmU7ZrILz+BwSo3sA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz", + "integrity": "sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==", "license": "MIT", "engines": { "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "peerDependencies": { - "vite": "^6.0.0" + "vite": "^6.0.0 || ^7.0.0" } }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.9.0.tgz", - "integrity": "sha512-jYFUSXhwMCYsh/aQTgSGLIN3Foz5wMbH9ahb0Zva//UzwZYbMiZd7oT3AU9jHT9DLswYDswsRwPU9jVF3yA48Q==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.10.2.tgz", + "integrity": "sha512-xD3Rdvrt5LgANug7WekBn1KhcvLn1H3jNBfJRL3reeOIua/WnZOEV5qi5qIBq5T8R0jUDmRtxuvk4bPhzGHDWw==", "dev": true, "license": "MIT", "dependencies": { - "@swc/core": "^1.11.21" + "@rolldown/pluginutils": "1.0.0-beta.11", + "@swc/core": "^1.11.31" }, "peerDependencies": { - "vite": "^4 || ^5 || ^6" + "vite": "^4 || ^5 || ^6 || ^7.0.0-beta.0" } }, "node_modules/@xterm/addon-clipboard": { @@ -2295,9 +2342,9 @@ "license": "MIT" }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2369,17 +2416,19 @@ } }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2573,9 +2622,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2596,9 +2645,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -2616,8 +2665,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -2685,9 +2734,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "dev": true, "funding": [ { @@ -2798,9 +2847,9 @@ "license": "MIT" }, "node_modules/cva": { - "version": "1.0.0-beta.3", - "resolved": "https://registry.npmjs.org/cva/-/cva-1.0.0-beta.3.tgz", - "integrity": "sha512-CZa8pTkpEygxJRLH9aod/wfnSgK5z/0GJqG/NNehlwam+S8llqCWUXS3eCenvAiW5sTUpwTWE6bJaeeZ/b4pzA==", + "version": "1.0.0-beta.4", + "resolved": "https://registry.npmjs.org/cva/-/cva-1.0.0-beta.4.tgz", + "integrity": "sha512-F/JS9hScapq4DBVQXcK85l9U91M6ePeXoBMSp7vypzShoefUBxjQTo3g3935PUHgQd+IW77DjbPRIxugy4/GCQ==", "license": "Apache-2.0", "dependencies": { "clsx": "^2.1.1" @@ -3105,16 +3154,16 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.155", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", - "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", + "version": "1.5.179", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", + "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", "dev": true, "license": "ISC" }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3126,27 +3175,27 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -3158,21 +3207,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -3181,7 +3233,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -3293,9 +3345,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -3305,31 +3357,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, "node_modules/escalade": { @@ -3355,18 +3407,18 @@ } }, "node_modules/eslint": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", - "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", + "version": "9.30.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.1.tgz", + "integrity": "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.27.0", + "@eslint/js": "9.30.1", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3378,9 +3430,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.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.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3463,9 +3515,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "license": "MIT", "dependencies": { "debug": "^3.2.7" @@ -3489,29 +3541,29 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -3624,9 +3676,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -3652,9 +3704,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3664,14 +3716,14 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3681,9 +3733,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3868,21 +3920,21 @@ "license": "ISC" }, "node_modules/focus-trap": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.4.tgz", - "integrity": "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.5.tgz", + "integrity": "sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==", "license": "MIT", "dependencies": { "tabbable": "^6.2.0" } }, "node_modules/focus-trap-react": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-11.0.3.tgz", - "integrity": "sha512-tS1+enWS/gwCHk2WIF3KpM2oz7Y3HsnRImzHZNRgCBLWXzNG4XQVlJgbqdLr4lBKRXGdDBjQYitSh1bf2xe4Ag==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-11.0.4.tgz", + "integrity": "sha512-tC7jC/yqeAqhe4irNIzdyDf9XCtGSeECHiBSYJBO/vIN0asizbKZCt8TarB6/XqIceu42ajQ/U4lQJ9pZlWjrg==", "license": "MIT", "dependencies": { - "focus-trap": "^7.6.4", + "focus-trap": "^7.6.5", "tabbable": "^6.2.0" }, "peerDependencies": { @@ -3922,13 +3974,13 @@ } }, "node_modules/framer-motion": { - "version": "12.12.1", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.12.1.tgz", - "integrity": "sha512-PFw4/GCREHI2suK/NlPSUxd+x6Rkp80uQsfCRFSOQNrm5pZif7eGtmG1VaD/UF1fW9tRBy5AaS77StatB3OJDg==", + "version": "12.23.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.0.tgz", + "integrity": "sha512-xf6NxTGAyf7zR4r2KlnhFmsRfKIbjqeBupEDBAaEtVIBJX96sAon00kMlsKButSIRwPSHjbRrAPnYdJJ9kyhbA==", "license": "MIT", "dependencies": { - "motion-dom": "^12.12.1", - "motion-utils": "^12.12.1", + "motion-dom": "^12.22.0", + "motion-utils": "^12.19.0", "tslib": "^2.4.0" }, "peerDependencies": { @@ -4067,9 +4119,9 @@ } }, "node_modules/globals": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", - "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", "engines": { @@ -4474,6 +4526,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5175,18 +5239,18 @@ } }, "node_modules/motion-dom": { - "version": "12.12.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.12.1.tgz", - "integrity": "sha512-GXq/uUbZBEiFFE+K1Z/sxdPdadMdfJ/jmBALDfIuHGi0NmtealLOfH9FqT+6aNPgVx8ilq0DtYmyQlo6Uj9LKQ==", + "version": "12.22.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.22.0.tgz", + "integrity": "sha512-ooH7+/BPw9gOsL9VtPhEJHE2m4ltnhMlcGMhEqA0YGNhKof7jdaszvsyThXI6LVIKshJUZ9/CP6HNqQhJfV7kw==", "license": "MIT", "dependencies": { - "motion-utils": "^12.12.1" + "motion-utils": "^12.19.0" } }, "node_modules/motion-utils": { - "version": "12.12.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.12.1.tgz", - "integrity": "sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w==", + "version": "12.19.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.19.0.tgz", + "integrity": "sha512-BuFTHINYmV07pdWs6lj6aI63vr2N4dg0vR+td0rtrdpWOhBzIkEklZyLcvKBoEtwSqx8Jg06vUB5RS0xDiUybw==", "license": "MIT" }, "node_modules/ms": { @@ -5481,9 +5545,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -5500,7 +5564,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5539,9 +5603,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -5555,9 +5619,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", - "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.13.tgz", + "integrity": "sha512-uQ0asli1+ic8xrrSmIOaElDu0FacR4x69GynTh2oZjFY10JUt6EEumTQl5tB4fMeD6I1naKd+4rXQQ7esT2i1g==", "dev": true, "license": "MIT", "engines": { @@ -5741,9 +5805,9 @@ "license": "MIT" }, "node_modules/react-router": { - "version": "6.30.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz", - "integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==", + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", + "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", "license": "MIT", "dependencies": { "@remix-run/router": "1.23.0" @@ -5756,13 +5820,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.30.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz", - "integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==", + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", + "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", "license": "MIT", "dependencies": { "@remix-run/router": "1.23.0", - "react-router": "6.30.0" + "react-router": "6.30.1" }, "engines": { "node": ">=14.0.0" @@ -5773,9 +5837,9 @@ } }, "node_modules/react-simple-keyboard": { - "version": "3.8.72", - "resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.8.72.tgz", - "integrity": "sha512-C34MVOykLrlONImOdJrSaXrNloTxOtUStipQaINR5Bem5JLFHEszNedVBEmxnt7Fqb7CTIIZ7fSgR8FasRIbzw==", + "version": "3.8.89", + "resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.8.89.tgz", + "integrity": "sha512-F3a29Uvp7Zf92YM84DidqBTGQjk78Yzqm7xZBjsW7rGXis5Yhakw+7CWeBQjHAbwNMdYAMoBq34AjGYemlXGSQ==", "license": "MIT", "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", @@ -5829,9 +5893,9 @@ } }, "node_modules/recharts": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz", - "integrity": "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", "license": "MIT", "dependencies": { "clsx": "^2.0.0", @@ -5949,12 +6013,12 @@ } }, "node_modules/rollup": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.0.tgz", - "integrity": "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", + "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -5964,26 +6028,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.41.0", - "@rollup/rollup-android-arm64": "4.41.0", - "@rollup/rollup-darwin-arm64": "4.41.0", - "@rollup/rollup-darwin-x64": "4.41.0", - "@rollup/rollup-freebsd-arm64": "4.41.0", - "@rollup/rollup-freebsd-x64": "4.41.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.41.0", - "@rollup/rollup-linux-arm-musleabihf": "4.41.0", - "@rollup/rollup-linux-arm64-gnu": "4.41.0", - "@rollup/rollup-linux-arm64-musl": "4.41.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.41.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-musl": "4.41.0", - "@rollup/rollup-linux-s390x-gnu": "4.41.0", - "@rollup/rollup-linux-x64-gnu": "4.41.0", - "@rollup/rollup-linux-x64-musl": "4.41.0", - "@rollup/rollup-win32-arm64-msvc": "4.41.0", - "@rollup/rollup-win32-ia32-msvc": "4.41.0", - "@rollup/rollup-win32-x64-msvc": "4.41.0", + "@rollup/rollup-android-arm-eabi": "4.44.1", + "@rollup/rollup-android-arm64": "4.44.1", + "@rollup/rollup-darwin-arm64": "4.44.1", + "@rollup/rollup-darwin-x64": "4.44.1", + "@rollup/rollup-freebsd-arm64": "4.44.1", + "@rollup/rollup-freebsd-x64": "4.44.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", + "@rollup/rollup-linux-arm-musleabihf": "4.44.1", + "@rollup/rollup-linux-arm64-gnu": "4.44.1", + "@rollup/rollup-linux-arm64-musl": "4.44.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-musl": "4.44.1", + "@rollup/rollup-linux-s390x-gnu": "4.44.1", + "@rollup/rollup-linux-x64-gnu": "4.44.1", + "@rollup/rollup-linux-x64-musl": "4.44.1", + "@rollup/rollup-win32-arm64-msvc": "4.44.1", + "@rollup/rollup-win32-ia32-msvc": "4.44.1", + "@rollup/rollup-win32-x64-msvc": "4.44.1", "fsevents": "~2.3.2" } }, @@ -6230,6 +6294,19 @@ "node": ">=0.10.0" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -6377,9 +6454,9 @@ "license": "MIT" }, "node_modules/tailwind-merge": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.0.tgz", - "integrity": "sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", "license": "MIT", "funding": { "type": "github", @@ -6387,15 +6464,15 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz", - "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", "license": "MIT" }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", "engines": { @@ -6427,9 +6504,9 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -6443,9 +6520,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -6495,9 +6572,9 @@ } }, "node_modules/tsconfck": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.5.tgz", - "integrity": "sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", "dev": true, "license": "MIT", "bin": { @@ -6723,9 +6800,9 @@ "license": "MIT" }, "node_modules/validator": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz", - "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==", + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -6848,9 +6925,9 @@ } }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" diff --git a/ui/package.json b/ui/package.json index eb9a9a3..8723767 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,21 +19,21 @@ "preview": "vite preview" }, "dependencies": { - "@headlessui/react": "^2.2.3", + "@headlessui/react": "^2.2.4", "@headlessui/tailwindcss": "^0.2.2", "@heroicons/react": "^2.2.0", - "@vitejs/plugin-basic-ssl": "^2.0.0", + "@vitejs/plugin-basic-ssl": "^2.1.0", "@xterm/addon-clipboard": "^0.1.0", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-unicode11": "^0.8.0", "@xterm/addon-web-links": "^0.11.0", "@xterm/addon-webgl": "^0.18.0", "@xterm/xterm": "^5.5.0", - "cva": "^1.0.0-beta.3", + "cva": "^1.0.0-beta.4", "dayjs": "^1.11.13", "eslint-import-resolver-alias": "^1.1.2", - "focus-trap-react": "^11.0.3", - "framer-motion": "^12.11.4", + "focus-trap-react": "^11.0.4", + "framer-motion": "^12.23.0", "lodash.throttle": "^4.1.1", "mini-svg-data-uri": "^1.4.4", "react": "^19.1.0", @@ -42,42 +42,42 @@ "react-hot-toast": "^2.5.2", "react-icons": "^5.5.0", "react-router-dom": "^6.22.3", - "react-simple-keyboard": "^3.8.72", + "react-simple-keyboard": "^3.8.89", "react-use-websocket": "^4.13.0", "react-xtermjs": "^1.0.10", "recharts": "^2.15.3", - "tailwind-merge": "^3.3.0", + "tailwind-merge": "^3.3.1", "usehooks-ts": "^3.1.1", - "validator": "^13.15.0", + "validator": "^13.15.15", "zustand": "^4.5.2" }, "devDependencies": { - "@eslint/compat": "^1.2.9", + "@eslint/compat": "^1.3.1", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "^9.26.0", + "@eslint/js": "^9.30.1", "@tailwindcss/forms": "^0.5.10", - "@tailwindcss/postcss": "^4.1.7", + "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/typography": "^0.5.16", - "@tailwindcss/vite": "^4.1.7", - "@types/react": "^19.1.4", - "@types/react-dom": "^19.1.5", + "@tailwindcss/vite": "^4.1.11", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", "@types/semver": "^7.7.0", - "@types/validator": "^13.15.0", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "@vitejs/plugin-react-swc": "^3.9.0", + "@types/validator": "^13.15.2", + "@typescript-eslint/eslint-plugin": "^8.35.1", + "@typescript-eslint/parser": "^8.35.1", + "@vitejs/plugin-react-swc": "^3.10.2", "autoprefixer": "^10.4.21", - "eslint": "^9.26.0", + "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.1.0", - "postcss": "^8.5.3", - "prettier": "^3.5.3", - "prettier-plugin-tailwindcss": "^0.6.11", - "tailwindcss": "^4.1.7", + "globals": "^16.3.0", + "postcss": "^8.5.6", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.13", + "tailwindcss": "^4.1.11", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-tsconfig-paths": "^5.1.4" diff --git a/ui/src/components/ActionBar.tsx b/ui/src/components/ActionBar.tsx index 7de4571..801cc7a 100644 --- a/ui/src/components/ActionBar.tsx +++ b/ui/src/components/ActionBar.tsx @@ -1,6 +1,6 @@ import { MdOutlineContentPasteGo } from "react-icons/md"; import { LuCable, LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu"; -import { FaKeyboard, FaLock} from "react-icons/fa6"; +import { FaKeyboard } from "react-icons/fa6"; import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react"; import { Fragment, useCallback, useRef } from "react"; import { CommandLineIcon } from "@heroicons/react/20/solid"; @@ -19,8 +19,6 @@ import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index"; import MountPopopover from "@/components/popovers/MountPopover"; import ExtensionPopover from "@/components/popovers/ExtensionPopover"; import { useDeviceUiNavigation } from "@/hooks/useAppNavigation"; -import useKeyboard from "@/hooks/useKeyboard"; -import { keys, modifiers } from "@/keyboardMappings"; export default function Actionbar({ requestFullscreen, @@ -58,8 +56,6 @@ export default function Actionbar({ [setDisableFocusTrap], ); - const { sendKeyboardEvent, resetKeyboardState } = useKeyboard(); - return (
- {useSettingsStore().actionBarCtrlAltDel && ( -
-
- )}
+ diff --git a/ui/src/routes/devices.$id.settings.general.reboot.tsx b/ui/src/routes/devices.$id.settings.general.reboot.tsx new file mode 100644 index 0000000..c6889f6 --- /dev/null +++ b/ui/src/routes/devices.$id.settings.general.reboot.tsx @@ -0,0 +1,66 @@ +import { useNavigate } from "react-router-dom"; +import { useCallback } from "react"; + +import { useJsonRpc } from "@/hooks/useJsonRpc"; +import { Button } from "@components/Button"; + +export default function SettingsGeneralRebootRoute() { + const navigate = useNavigate(); + const [send] = useJsonRpc(); + + const onConfirmUpdate = useCallback(() => { + // This is where we send the RPC to the golang binary + send("reboot", {force: true}); + }, [send]); + + { + /* TODO: Migrate to using URLs instead of the global state. To simplify the refactoring, we'll keep the global state for now. */ + } + return navigate("..")} onConfirmUpdate={onConfirmUpdate} />; +} + +export function Dialog({ + onClose, + onConfirmUpdate, +}: { + onClose: () => void; + onConfirmUpdate: () => void; +}) { + + return ( +
+
+ +
+
+ ); +} + +function ConfirmationBox({ + onYes, + onNo, +}: { + onYes: () => void; + onNo: () => void; +}) { + return ( +
+
+

+ Reboot JetKVM +

+

+ Do you want to proceed with rebooting the system? +

+ +
+
+
+
+ ); +} diff --git a/ui/src/routes/devices.$id.settings.hardware.tsx b/ui/src/routes/devices.$id.settings.hardware.tsx index 44a146c..82cc6a1 100644 --- a/ui/src/routes/devices.$id.settings.hardware.tsx +++ b/ui/src/routes/devices.$id.settings.hardware.tsx @@ -1,10 +1,9 @@ -import { useCallback, useEffect, useState } from "react"; +import { useEffect } from "react"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import { SettingsItem } from "@routes/devices.$id.settings"; import { BacklightSettings, useSettingsStore } from "@/hooks/stores"; import { useJsonRpc } from "@/hooks/useJsonRpc"; -import Checkbox from "@components/Checkbox"; import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { UsbDeviceSetting } from "@components/UsbDeviceSetting"; @@ -12,14 +11,6 @@ import notifications from "../notifications"; import { UsbInfoSetting } from "../components/UsbInfoSetting"; import { FeatureFlag } from "../components/FeatureFlag"; -export interface ActionBarConfig { - ctrlAltDel: boolean; -} - -const defaultActionBarConfig: ActionBarConfig = { - ctrlAltDel: false, -}; - export default function SettingsHardwareRoute() { const [send] = useJsonRpc(); const settings = useSettingsStore(); @@ -80,18 +71,6 @@ export default function SettingsHardwareRoute() { }); }, [send, setBacklightSettings]); - const [actionBarConfig, setActionBarConfig] = useState(defaultActionBarConfig); - - const onActionBarItemChange = useCallback( - (key: keyof ActionBarConfig) => (e: React.ChangeEvent) => { - setActionBarConfig(prev => ({ - ...prev, - [key]: e.target.checked, - })); - }, - [], - ); - return (
- - - {settings.backlightSettings.max_brightness != 0 && ( <> state.setShowPressedKeys, ); - // this ensures we always get the original en-US if it hasn't been set yet + // this ensures we always get the original en_US if it hasn't been set yet const safeKeyboardLayout = useMemo(() => { if (keyboardLayout && keyboardLayout.length > 0) return keyboardLayout; - return "en-US"; + return "en_US"; }, [keyboardLayout]); const layoutOptions = Object.entries(layouts).map(([code, language]) => { return { value: code, label: language } }) diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx index 0c710ce..94d6789 100644 --- a/ui/src/routes/devices.$id.settings.mouse.tsx +++ b/ui/src/routes/devices.$id.settings.mouse.tsx @@ -9,6 +9,7 @@ import { useSettingsStore } from "@/hooks/stores"; import { useJsonRpc } from "@/hooks/useJsonRpc"; import notifications from "@/notifications"; import { SettingsPageHeader } from "@components/SettingsPageheader"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { useFeatureFlag } from "../hooks/useFeatureFlag"; import { cx } from "../cva.config"; @@ -26,6 +27,19 @@ export default function SettingsMouseRoute() { const [jiggler, setJiggler] = useState(false); + const scrollThrottling = useSettingsStore(state => state.scrollThrottling); + const setScrollThrottling = useSettingsStore( + state => state.setScrollThrottling, + ); + + const scrollThrottlingOptions = [ + { value: "0", label: "Off" }, + { value: "10", label: "Low" }, + { value: "25", label: "Medium" }, + { value: "50", label: "High" }, + { value: "100", label: "Very High" }, + ]; + const [send] = useJsonRpc(); useEffect(() => { @@ -65,6 +79,21 @@ export default function SettingsMouseRoute() { /> + + setScrollThrottling(parseInt(e.target.value))} + options={scrollThrottlingOptions} + /> + + (null); const [edid, setEdid] = useState(null); + // Video enhancement settings from store + const videoSaturation = useSettingsStore(state => state.videoSaturation); + const setVideoSaturation = useSettingsStore(state => state.setVideoSaturation); + const videoBrightness = useSettingsStore(state => state.videoBrightness); + const setVideoBrightness = useSettingsStore(state => state.setVideoBrightness); + const videoContrast = useSettingsStore(state => state.videoContrast); + const setVideoContrast = useSettingsStore(state => state.setVideoContrast); + useEffect(() => { send("getStreamQualityFactor", {}, resp => { if ("error" in resp) return; @@ -126,6 +135,73 @@ export default function SettingsVideoRoute() { onChange={e => handleStreamQualityChange(e.target.value)} /> + + {/* Video Enhancement Settings */} + + +
+ + setVideoSaturation(parseFloat(e.target.value))} + className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + /> + + + + setVideoBrightness(parseFloat(e.target.value))} + className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + /> + + + + setVideoContrast(parseFloat(e.target.value))} + className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + /> + + +
+
+
+