From 2dbdb4f916c88243efdd924fce38f4b7133014a5 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 15:49:36 +0800 Subject: [PATCH 01/18] feat: go 1.27.1 --- .github/workflows/ci.yml | 2 +- Dockerfile | 2 +- cli/go.mod | 2 +- go.mod | 96 ++++++++++++++++++------------------ go.sum | 103 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce58ac0..56e4234 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.26.4' + go-version: '1.27.1' cache-dependency-path: go.sum - name: Enable Corepack (pnpm) diff --git a/Dockerfile b/Dockerfile index 26d1cac..330667f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ COPY frontend/ ./ RUN pnpm run build # ---------------------build go-------------------- -FROM golang:1.26.4-trixie AS builder_go +FROM golang:1.27.1-trixie AS builder_go WORKDIR /app COPY go.mod go.sum ./ RUN go mod download diff --git a/cli/go.mod b/cli/go.mod index 5a6c8fa..b6fc82e 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,6 +1,6 @@ module shadmin-cli -go 1.26.4 +go 1.27.1 require github.com/spf13/cobra v1.10.2 diff --git a/go.mod b/go.mod index d3a5f92..fa3d2d6 100644 --- a/go.mod +++ b/go.mod @@ -1,40 +1,40 @@ module shadmin -go 1.26.4 +go 1.27.1 require ( entgo.io/ent v0.14.6 - github.com/casbin/casbin/v3 v3.10.0 - github.com/gin-contrib/static v1.1.6 + github.com/casbin/casbin/v3 v3.11.0 + github.com/gin-contrib/static v1.1.7 github.com/gin-gonic/gin v1.12.0 - github.com/go-sql-driver/mysql v1.10.0 + github.com/go-sql-driver/mysql v1.10.1 github.com/golang-jwt/jwt/v5 v5.3.1 github.com/gomodule/redigo v1.9.3 github.com/gorilla/sessions v1.4.0 - github.com/jackc/pgx/v5 v5.10.0 + github.com/jackc/pgx/v5 v5.11.0 github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f github.com/lib/pq v1.12.3 github.com/markbates/goth v1.82.0 - github.com/mattn/go-sqlite3 v1.14.47 - github.com/minio/minio-go/v7 v7.2.1 + github.com/mattn/go-sqlite3 v1.14.52 + github.com/minio/minio-go/v7 v7.3.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 - github.com/redis/go-redis/v9 v9.21.0 + github.com/redis/go-redis/v9 v9.22.0 github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 github.com/rs/xid v1.6.0 - github.com/sirupsen/logrus v1.9.4 + github.com/sirupsen/logrus v1.10.2 github.com/spf13/viper v1.21.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.1 github.com/swaggo/swag v1.16.6 github.com/wenlng/go-captcha-assets v1.0.7 github.com/wenlng/go-captcha/v2 v2.0.5 - golang.org/x/crypto v0.54.0 + golang.org/x/crypto v0.57.0 ) require ( - ariga.io/atlas v1.2.3 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + ariga.io/atlas v1.3.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/agext/levenshtein v1.2.3 // indirect @@ -43,39 +43,39 @@ require ( github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect github.com/bytedance/gopkg v0.1.4 // indirect - github.com/bytedance/sonic v1.15.2 // indirect - github.com/bytedance/sonic/loader v0.5.1 // indirect + github.com/bytedance/sonic v1.15.4 // indirect + github.com/bytedance/sonic/loader v0.5.2 // indirect github.com/casbin/govaluate v1.10.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.7 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/fsnotify/fsnotify v1.10.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.13 // indirect - github.com/gin-contrib/sse v1.1.1 // indirect - github.com/go-chi/chi/v5 v5.2.2 // indirect - github.com/go-openapi/inflect v0.21.6 // indirect - github.com/go-openapi/jsonpointer v1.0.0 // indirect - github.com/go-openapi/jsonreference v1.0.0 // indirect - github.com/go-openapi/spec v0.22.6 // indirect - github.com/go-openapi/swag/conv v0.27.0 // indirect - github.com/go-openapi/swag/jsonname v0.27.0 // indirect - github.com/go-openapi/swag/jsonutils v0.27.0 // indirect - github.com/go-openapi/swag/loading v0.27.0 // indirect - github.com/go-openapi/swag/stringutils v0.27.0 // indirect - github.com/go-openapi/swag/typeutils v0.27.0 // indirect - github.com/go-openapi/swag/yamlutils v0.27.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.15 // indirect + github.com/gin-contrib/sse v1.1.2 // indirect + github.com/go-chi/chi/v5 v5.3.2 // indirect + github.com/go-openapi/inflect v1.0.0 // indirect + github.com/go-openapi/jsonpointer v1.0.1 // indirect + github.com/go-openapi/jsonreference v1.0.2 // indirect + github.com/go-openapi/spec v1.0.1 // indirect + github.com/go-openapi/swag/conv v0.29.2 // indirect + github.com/go-openapi/swag/jsonutils v0.29.2 // indirect + github.com/go-openapi/swag/loading v0.29.2 // indirect + github.com/go-openapi/swag/pools v0.29.2 // indirect + github.com/go-openapi/swag/stringutils v0.29.2 // indirect + github.com/go-openapi/swag/typeutils v0.29.2 // indirect + github.com/go-openapi/swag/yamlutils v0.29.2 // 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.30.3 // indirect + github.com/go-playground/validator/v10 v10.30.4 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/context v1.1.1 // indirect - github.com/gorilla/mux v1.6.2 // indirect + github.com/gorilla/context v1.1.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/hashicorp/hcl/v2 v2.24.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -84,13 +84,13 @@ require ( github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.19.0 // indirect + github.com/klauspost/compress v1.20.0 // indirect github.com/klauspost/cpuid/v2 v2.4.0 // indirect github.com/klauspost/crc32 v1.3.0 // indirect - github.com/leodido/go-urn v1.4.0 // indirect + github.com/leodido/go-urn v1.5.0 // indirect github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect - github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect @@ -99,7 +99,7 @@ require ( github.com/pelletier/go-toml/v2 v2.4.3 // indirect github.com/philhofer/fwd v1.2.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.60.0 // indirect + github.com/quic-go/quic-go v0.62.0 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect @@ -108,23 +108,23 @@ require ( github.com/tebeka/strftime v0.1.5 // indirect github.com/tinylib/msgp v1.6.4 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.1 // indirect + github.com/ugorji/go/codec v1.3.2 // indirect github.com/zclconf/go-cty v1.19.0 // indirect github.com/zclconf/go-cty-yaml v1.2.0 // indirect github.com/zeebo/xxh3 v1.1.0 // indirect - go.mongodb.org/mongo-driver/v2 v2.8.0 // indirect + go.mongodb.org/mongo-driver/v2 v2.9.1 // indirect go.uber.org/atomic v1.11.0 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.29.0 // indirect - golang.org/x/image v0.44.0 // indirect - golang.org/x/mod v0.38.0 // indirect - golang.org/x/net v0.57.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.22.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/text v0.40.0 // indirect - golang.org/x/tools v0.48.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/arch v0.31.0 // indirect + golang.org/x/image v0.46.0 // indirect + golang.org/x/mod v0.41.0 // indirect + golang.org/x/net v0.59.0 // indirect + golang.org/x/oauth2 v0.37.0 // indirect + golang.org/x/sync v0.23.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/text v0.42.0 // indirect + golang.org/x/tools v0.50.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect gopkg.in/ini.v1 v1.67.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 64fc216..b578e2e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ ariga.io/atlas v1.2.3 h1:DLNK5kiz48XGv4Dbv8sJxPHncmmwUm43PoSA7UMZXEU= ariga.io/atlas v1.2.3/go.mod h1:v8ltuOKxFAU8ZF33HNfQs1iRWKuP3hJfu+dU0VE5O0Y= +ariga.io/atlas v1.3.0 h1:/ZQLypoRURfNO0VJmXUNz8k6lGoeJLDPlSOZOhxG/1U= +ariga.io/atlas v1.3.0/go.mod h1:v8ltuOKxFAU8ZF33HNfQs1iRWKuP3hJfu+dU0VE5O0Y= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= entgo.io/ent v0.14.6 h1:/f2696BpwuWAEEG6PVGWflg6+Inrpq4pRWuNlWz/Skk= entgo.io/ent v0.14.6/go.mod h1:z46QBUdGC+BATwsedbDuREfSS0oSCV+csdEYlL4p73s= filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= @@ -29,10 +33,16 @@ github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo= github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA= +github.com/bytedance/sonic v1.15.4 h1:FgtV/4aBHpla9AxuMpuuzVUpa/Cf3izufkxNmnEzdI8= +github.com/bytedance/sonic v1.15.4/go.mod h1:8e51yTPdY8M6t+vvGL1c2Y1xL9i+frEeIAQAEl75NUc= github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/bytedance/sonic/loader v0.5.2 h1:0QtP1gevc1OZ6/H8Lb9BRZiCXd1Ftjd3OKuj1T1lBIo= +github.com/bytedance/sonic/loader v0.5.2/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v3 v3.10.0 h1:039ORla55vCeIZWd0LfzWFt1yiEA5X4W41xBW2bQuHs= github.com/casbin/casbin/v3 v3.10.0/go.mod h1:5rJbQr2e6AuuDDNxnPc5lQlC9nIgg6nS1zYwKXhpHC8= +github.com/casbin/casbin/v3 v3.11.0 h1:xVlnpCGs0c2Hp2WuUF36o8iZgEsXUne9/j1qJjOgJPA= +github.com/casbin/casbin/v3 v3.11.0/go.mod h1:5rJbQr2e6AuuDDNxnPc5lQlC9nIgg6nS1zYwKXhpHC8= github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0= github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= @@ -59,45 +69,80 @@ github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx5 github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= +github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= +github.com/gin-contrib/sse v1.1.2 h1:MU2fgl1RrdYTMcgJLtz2kJF+vPg3xrqaaKfUUU18tCo= +github.com/gin-contrib/sse v1.1.2/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= github.com/gin-contrib/static v1.1.6 h1:4/OIJI9PxO2jsUezNulpVbzI8ORMmdPlJ4P9QGwWgME= github.com/gin-contrib/static v1.1.6/go.mod h1:e9qkj8wAlsxE6mSFGVL/flqGfVibw5amjNEUa4idmHc= +github.com/gin-contrib/static v1.1.7 h1:NO2TB52rpAiYsGNJKoJV0BGcdLDdjHyCmHyRFOGFqgQ= +github.com/gin-contrib/static v1.1.7/go.mod h1:q4wJTVkZkyhlttOg35G79bFJtjsYQ9v6F1VeD+xqn8c= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY= +github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto= github.com/go-openapi/inflect v0.21.6 h1:0Se5BlyDT4hnV9JQQKA63W9TIUU6SC4hPJiY3qJOEzQ= github.com/go-openapi/inflect v0.21.6/go.mod h1:ksYcnLD7j24H79hdqOMmWaLXjFXd0LTkRoBA0UazLW8= +github.com/go-openapi/inflect v1.0.0 h1:IzG7K5YBu97odaCXhjODGGt25WaNtEYLJc9NfUcW4AI= +github.com/go-openapi/inflect v1.0.0/go.mod h1:ksYcnLD7j24H79hdqOMmWaLXjFXd0LTkRoBA0UazLW8= github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +github.com/go-openapi/jsonpointer v1.0.1 h1:2KxywRmNwJkT/FMBa3iRNHEaAxSJvjqoufQZy3au1Mg= +github.com/go-openapi/jsonpointer v1.0.1/go.mod h1:wI7ZYsFmbIi9nBXOZqgDaS/bqOchRGZjqxFli7FBYxY= github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= +github.com/go-openapi/jsonreference v1.0.2 h1:oS4et8FOf3p3UQxEo4Xt0esijmBUM+F259Xl72OSZsc= +github.com/go-openapi/jsonreference v1.0.2/go.mod h1:TbUNSOo+fcorZjFaNoiSDSoaNnnZtqJtLGR1PuvE/Cs= github.com/go-openapi/spec v0.22.6 h1:Tyy1pLaNCM8GBCFLoGYLonjJi6zykqyLCjXLc19ZPic= github.com/go-openapi/spec v0.22.6/go.mod h1:HZvTHat+iH0PALQRWhrqIHtU/PEqxqd89fu0MxGlMeM= +github.com/go-openapi/spec v1.0.1 h1:lj2vdGpNDcVgwRc6qXdw6qt/KQpCtSa9tnUH6vpDPDk= +github.com/go-openapi/spec v1.0.1/go.mod h1:M//GWQGtDUAjnP37gE6fInLgaczB+FatoipV3H1fYw8= github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag/conv v0.27.0 h1:EKOH4feXrvdo8DbSsXSAqRT8fz1epEnS5O2IfXUOzE8= github.com/go-openapi/swag/conv v0.27.0/go.mod h1:pfiv0uKQTbaGApk8Zs/lZV3uSjmSpa2FO1y183YngN8= +github.com/go-openapi/swag/conv v0.29.2 h1:8c9shoB8l0QRSR6ymq1llHdBWDqpIgJfjTGHx3Vuhm0= +github.com/go-openapi/swag/conv v0.29.2/go.mod h1:AZS0YigTNf8qNtD6WqJz/N4RUNmpr76SyjFGkq4+p6Q= github.com/go-openapi/swag/jsonname v0.27.0 h1:4QVB//CKOdE8IOiBg19JNY2wfDS48MhesIquYBy2rUE= github.com/go-openapi/swag/jsonname v0.27.0/go.mod h1:I1YsyvvhBuZsFXSW6I7ODfdyq13p7hDil//1T9/pFFk= +github.com/go-openapi/swag/jsonname v0.29.2 h1:u5e4IQxc7Yxw1APbtOmfY+Lv4lVZSV1KQiMb/Uj35jc= +github.com/go-openapi/swag/jsonname v0.29.2/go.mod h1:EMHY1EUECld0oRKGSkA6Vmzw138nWoSpavlVBep6msk= github.com/go-openapi/swag/jsonutils v0.27.0 h1:VYtd9jEQYeU4j8q5vdn5KWotF4vKywhGdMBrALtAsfE= github.com/go-openapi/swag/jsonutils v0.27.0/go.mod h1:U7pb8AGuwhok3RDicHeHwSG4L3PXSq6PAL98Aon632g= +github.com/go-openapi/swag/jsonutils v0.29.2 h1:uZNSD2/rJDYAfvsLYkykTzXuyxM3QpDKV9jhRHrMu6k= +github.com/go-openapi/swag/jsonutils v0.29.2/go.mod h1:ONTdNvj3Y+IXRzfa17E+Rgt2ns/qiSOYjIo2K7v2yDs= github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0 h1:+d7C7Ur/SsGg/UZ9G0JEovnfRqtMNZCJQGKc2h/ojoE= github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.2 h1:w+Fd6EBOMGlC74GYGHqCLGyb3Bpams8TtNrgM/SG4jo= github.com/go-openapi/swag/loading v0.27.0 h1:s8DA9aPEdFH6OluHUYUn3DnIuoTdyWs9RwffXBUfyeI= github.com/go-openapi/swag/loading v0.27.0/go.mod h1:VOz+Jg6UGGywcmRvYsI4fvtp+bd7NfioseGEPleYdA4= +github.com/go-openapi/swag/loading v0.29.2 h1:QU1ry24e6r6Shoxe380Nx0X5iKkpRO+hJffsyJ2dVlY= +github.com/go-openapi/swag/loading v0.29.2/go.mod h1:DqilDjuiJKETecsS4TRopWG1acUDsfqN39ZmQhPu6uI= +github.com/go-openapi/swag/pools v0.29.2 h1:PlGoDRF8WtSyXkedZZkpW3f9wDhFf3u8KtaBcmgmh8c= +github.com/go-openapi/swag/pools v0.29.2/go.mod h1:V3lhxVT4qDYRqc2MRSSbLsTYIYV/2HlHafhyEkmzLIc= github.com/go-openapi/swag/stringutils v0.27.0 h1:Of7w/HljWsNZvuxsUAnw3n+hCOyI6HLJOxW2kQRAxio= github.com/go-openapi/swag/stringutils v0.27.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= +github.com/go-openapi/swag/stringutils v0.29.2 h1:lcnBxwAaysT3bMUVBfn9V/PkfVqkurpqufKU6rTUMGk= +github.com/go-openapi/swag/stringutils v0.29.2/go.mod h1:i9cdh7sGaa0nm3CqIvH5IM5h2QClk1wns2ktKeILvRI= github.com/go-openapi/swag/typeutils v0.27.0 h1:aCf4MSGo8NLwZP8Q6t32DWLJSvl/WwNqgmEG+xJ6v2o= github.com/go-openapi/swag/typeutils v0.27.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= +github.com/go-openapi/swag/typeutils v0.29.2 h1:O7aVvkTs3pXwikgtrPLenigEMdQFgONKRooQA9pgf2I= +github.com/go-openapi/swag/typeutils v0.29.2/go.mod h1:7+GDG+uz9Ke+eVt4rClZg7wklSDp8hT/mKNh/pC26TE= github.com/go-openapi/swag/yamlutils v0.27.0 h1:bQ6eAMil5X9tdcf7dMn4t15alzG6jddnrKPuKa/zxKM= github.com/go-openapi/swag/yamlutils v0.27.0/go.mod h1:yRfIo7qqVkmJRQjX8exjA3AfcI8rH1KDNPsTparoCv4= +github.com/go-openapi/swag/yamlutils v0.29.2 h1:IFKFFeDnuIwzfsuWRQU+rI8iL3g4XyAYjV/RlnlxPLM= +github.com/go-openapi/swag/yamlutils v0.29.2/go.mod h1:7MGqtcrK73sxQ4ceiyIf8qiXS/s09JLMdR5esK5euYQ= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= +github.com/go-openapi/testify/enable/yaml/v2 v2.7.0 h1:wPW6YRgx3+SID1yUy/Xwa17L8kFEaEKod2VRbJDZNUs= github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-openapi/testify/v2 v2.7.0 h1:bycOreEj6wfBvijg3YFogZ/sFjTCDmQnwSodSzHa3X8= 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= @@ -106,8 +151,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8= github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc= +github.com/go-playground/validator/v10 v10.30.4 h1:9Rcod2ZPO6mOEG6b4GqyoHE/H6//Ze0RuhOo1hT1x0w= +github.com/go-playground/validator/v10 v10.30.4/go.mod h1:numpT+RPLE91R9oYWMY/R9zRgJBewr3IXHko4OISPpk= github.com/go-sql-driver/mysql v1.10.0 h1:Q+1LV8DkHJvSYAdR83XzuhDaTykuDx0l6fkXxoWCWfw= github.com/go-sql-driver/mysql v1.10.0/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk= +github.com/go-sql-driver/mysql v1.10.1 h1:arlSnNLq6a5yxGxV7qg9lF4j0C+KwD6NbQyKr9QL6ME= +github.com/go-sql-driver/mysql v1.10.1/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= @@ -131,12 +180,18 @@ 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/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= +github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -145,6 +200,8 @@ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7Ulw github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.10.0 h1:VhSvgU2jSli8o3AqIEOTJr7rZwAEUVo4E4XhR94Zfr0= github.com/jackc/pgx/v5 v5.10.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= +github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= @@ -155,6 +212,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ= github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA= +github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= @@ -166,6 +225,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= +github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo= github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE= github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgUSP4zdTUZYZgAGGtN5Lxk92rK+JUFOwf+FT99EEI4= @@ -180,16 +241,22 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.47 h1:jOBI62gS7nKeZv+as1oGEy0+1qISgXwH/QBlR6KbfIo= github.com/mattn/go-sqlite3 v1.14.47/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= +github.com/mattn/go-sqlite3 v1.14.52 h1:wVbm2Qnf4OXkqhBTSPuCRZDRnxfbVrrmiCEroVdog8U= +github.com/mattn/go-sqlite3 v1.14.52/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.2.1 h1:PfBfwvKB/MmqyN8Vb1G9voWisaM9OrLv+WwOvMwS9Dw= github.com/minio/minio-go/v7 v7.2.1/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0= +github.com/minio/minio-go/v7 v7.3.0 h1:HM4pFCSQq/TK+j0/zmorSh5ddh81iDgRgU0BG0Vz/YU= +github.com/minio/minio-go/v7 v7.3.0/go.mod h1:KUPWdecEO1LWyUz+sTGXAuf2jZHrPh5fCsRH86QbPfk= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -207,6 +274,7 @@ github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLy github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY= github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= @@ -221,8 +289,12 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.60.0 h1:xcQioE8OM66UQLeUMHltK1CCcOu3JbVB4JAQdDQSB+0= github.com/quic-go/quic-go v0.60.0/go.mod h1:wpKpjmPpftl30sL6pFh7REVpjbcCVy4zt2vDyK1TuJk= +github.com/quic-go/quic-go v0.62.0 h1:ZHDjCk5OacATwGvs8PWE97CTvX7AqZiVoW7++ZOXTf8= +github.com/quic-go/quic-go v0.62.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= github.com/redis/go-redis/v9 v9.21.0 h1:FPBE4hhbAke+TLmcY3WkpbDffJEomdqPn3HYiqAtL9E= github.com/redis/go-redis/v9 v9.21.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= +github.com/redis/go-redis/v9 v9.22.0 h1:laDvpYXTJtZLloinw1fA5Kqd6HAEH2XKxOkG/PDq2F0= +github.com/redis/go-redis/v9 v9.22.0/go.mod h1:y2g0Wj8rQvuK0ELM+oxSudcLtC09JScs98I/X9gRWY4= github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo= github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -233,6 +305,8 @@ github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88ee github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo= +github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= @@ -255,6 +329,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= @@ -271,6 +346,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc= +github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/wenlng/go-captcha-assets v1.0.7 h1:tfF84A4un/i4p+TbRVHDqDPeQeatvddOfB2xbKvLVq8= github.com/wenlng/go-captcha-assets v1.0.7/go.mod h1:zinRACsdYcL/S6pHgI9Iv7FKTU41d00+43pNX+b9+MM= github.com/wenlng/go-captcha/v2 v2.0.5 h1:+1FpVwJZmLCqEHxOt+HvpUArFGo107nRxOeRVHkZhTc= @@ -288,25 +365,37 @@ github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= go.mongodb.org/mongo-driver/v2 v2.8.0 h1:CxWDGQYY8QQwNjAl/aq2sfWakdnWZynnqJ9F4DhHbP8= go.mongodb.org/mongo-driver/v2 v2.8.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +go.mongodb.org/mongo-driver/v2 v2.9.1 h1:jewiFs2m1/VOQp8qhFshX6hWZ+EAXDhZHXExAUMcOgQ= +go.mongodb.org/mongo-driver/v2 v2.9.1/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/arch v0.29.0 h1:8sSET5wB0+exBm0FGmOtdHMqjlRdV2DRD3/IV6OZgho= golang.org/x/arch v0.29.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= +golang.org/x/arch v0.31.0 h1:22MlEb14/O/EPCYHFxsDdv5TuLD5dMjT5e2QeJw4ULk= +golang.org/x/arch v0.31.0/go.mod h1:KcJSod3cqT2dKcjBxqTyGfbumNikqU9p5tHJinPJnuY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs= golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I= golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY= +golang.org/x/image v0.46.0 h1:b1+oYj0Jbp6K5MDT4i4/eZpYlk3V8SJhhDKh6LBHAyQ= +golang.org/x/image v0.46.0/go.mod h1:3B3W05VGVQyuXucLINLjXKrqISASfi4Xj+iCVkLMwew= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= +golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= +golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -314,13 +403,19 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= +golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= +golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -329,6 +424,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -339,15 +436,21 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= +golang.org/x/tools v0.50.0 h1:c2ifzfcuY7L90lZ2aKd8S4K2NpASF08SZx9ZuJkHmSU= +golang.org/x/tools v0.50.0/go.mod h1:7ulVMw3831Mwi5EZD6RomGyffr4VFjuNYXf2BbCEAV0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From fc49137ce9714ab6b8320bf8b38d1bb29317db3a Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 15:55:33 +0800 Subject: [PATCH 02/18] ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56e4234..4866ccf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [ main ] + branches: [ main , oidc ] tags: - 'v*' paths: &trigger_paths From 48bf8c9526bac16f2b2b28b14a815cb5b90debec Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:00:44 +0800 Subject: [PATCH 03/18] fix: format check --- frontend/src/types/profile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/types/profile.ts b/frontend/src/types/profile.ts index ab67b3b..9ad56fe 100644 --- a/frontend/src/types/profile.ts +++ b/frontend/src/types/profile.ts @@ -3,7 +3,7 @@ import { type UserStatus } from './user' export interface Profile { id: string username: string - nickname:string + nickname: string email: string phone?: string bio?: string From d22f5c9c2a727891dfa04c4bc9ef75f830d67af1 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:44:47 +0800 Subject: [PATCH 04/18] fix: rename --- .../src/features/system/users/components/users-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/features/system/users/components/users-provider.tsx b/frontend/src/features/system/users/components/users-provider.tsx index 50bfbc5..53dc6b6 100644 --- a/frontend/src/features/system/users/components/users-provider.tsx +++ b/frontend/src/features/system/users/components/users-provider.tsx @@ -29,7 +29,7 @@ export const useUsersDialog = () => { const usersContext = React.useContext(UsersContext) if (!usersContext) { - throw new Error('useUsers has to be used within ') + throw new Error('useUsersDialog has to be used within ') } return usersContext From d59eb090b2ee96ece2085a4f353498e2b093814c Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:45:29 +0800 Subject: [PATCH 05/18] refactor: clean claude --- .claude/skills/shadmin-dev/SKILL.md | 209 ------------------ .../skills/shadmin-dev/references/backend.md | 114 ---------- .../skills/shadmin-dev/references/frontend.md | 169 -------------- 3 files changed, 492 deletions(-) delete mode 100644 .claude/skills/shadmin-dev/SKILL.md delete mode 100644 .claude/skills/shadmin-dev/references/backend.md delete mode 100644 .claude/skills/shadmin-dev/references/frontend.md diff --git a/.claude/skills/shadmin-dev/SKILL.md b/.claude/skills/shadmin-dev/SKILL.md deleted file mode 100644 index dd098e4..0000000 --- a/.claude/skills/shadmin-dev/SKILL.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -name: shadmin-dev -description: Apply Shadmin feature-development standards (backend Go/Gin/Ent + frontend React/TS). Use when adding/modifying features, CRUD modules, API routes/controllers/usecases/repositories, Ent schemas, frontend pages/routes, React components, TanStack hooks, or any full-stack work in this project. Trigger whenever the user mentions new features, backend changes, frontend changes, database schema changes, permissions, UI pages, tables, forms, or API endpoints — even if they don't explicitly say "feature development." ---- - -# Shadmin Feature Development - -Guide full-stack feature development through Shadmin's clean architecture, producing code that compiles, passes lint/tests, and follows established patterns. Most features require both backend and frontend changes — this skill covers the end-to-end workflow. - -## Architecture Overview - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Frontend (React 19 + TypeScript + Vite) │ -│ Route File → Page Component → TanStack Query Hook → API Service │ -│ ↕ Zustand (auth-store) ↕ Permission checks │ -├─────────────────────────────────────────────────────────────────────┤ -│ HTTP (Axios apiClient ← Bearer Token injection) │ -├─────────────────────────────────────────────────────────────────────┤ -│ Backend (Go + Gin + Ent ORM) │ -│ Route → [JWT MW → Casbin MW] → Controller → Usecase → Repository │ -│ ↕ Domain (contracts, DTOs, errors) ↕ Ent (DB, migrations) │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -**Backend layers** — each has exactly one responsibility: - -| Layer | Directory | Responsibility | -|-------|-----------|---------------| -| Domain | `domain/` | Entity structs, DTOs, Repository/UseCase interfaces, errors, response helpers | -| Schema | `ent/schema/` | DB schema → run `go generate ./ent` after changes | -| Repository | `repository/` | Data access via Ent, domain↔ent conversion, pagination | -| Usecase | `usecase/` | Business logic, validation, `context.WithTimeout` | -| Controller | `api/controller/` | HTTP parsing only, Swagger annotations, status code mapping | -| Route | `api/route/` | Route registration, middleware wiring | -| Factory | `api/route/factory.go` | DI: repo → usecase → controller construction | -| Bootstrap | `bootstarp/` | App init, DB, Casbin, seeds (directory name typo is intentional) | - -**Frontend layers:** - -| Layer | Directory | Responsibility | -|-------|-----------|---------------| -| Types | `frontend/src/types/` | TypeScript interfaces matching backend DTOs | -| Services | `frontend/src/services/` | Axios API wrappers, date parsing | -| Features | `frontend/src/features/` | Page components, tables, dialogs, forms, hooks | -| Routes | `frontend/src/routes/` | TanStack Router file-based routing | -| Stores | `frontend/src/stores/` | Zustand state (auth, permissions) | -| Constants | `frontend/src/constants/` | Permission strings, enums | - -## Full-Stack Development Workflow - -### Step 1: Clarify Scope (before writing code) - -State explicitly: -- What entities/fields are involved -- API endpoints: path, method, request/response shapes -- Whether Casbin permission checks are needed -- Frontend: pages, tables, forms, dialogs -- Permission strings (e.g., `system:project:add`) - -### Step 2: List All Touched Files - -Group by layer — this catches missing pieces early: - -``` -# Backend (implement in this order) -domain/.go -ent/schema/.go -repository/_repository.go -usecase/_usecase.go -api/controller/_controller.go -api/route/_routes.go (or modify system_routes.go) -api/route/factory.go - -# Frontend (implement in this order) -frontend/src/types/.ts -frontend/src/services/Api.ts -frontend/src/features///components/*-provider.tsx -frontend/src/features///hooks/use-.ts -frontend/src/features///components/*-columns.tsx -frontend/src/features///components/*-table.tsx -frontend/src/features///components/*-form-dialog.tsx -frontend/src/features///components/*-dialogs.tsx -frontend/src/features///components/*-primary-buttons.tsx -frontend/src/features///data/schema.ts -frontend/src/features///index.tsx -frontend/src/routes/_authenticated//.tsx -frontend/src/constants/permissions.ts (add new permission keys) -``` - -### Step 3: Implement Backend - -Follow the layer order strictly — each layer depends on the one above. - -**Read `references/backend.md` for complete code templates and patterns.** - -Quick reference for key conventions: -- **IDs**: `xid.New().String()` in Ent schema `DefaultFunc` -- **Partial updates**: pointer fields in `Update*Request` (`*string`) -- **Pagination**: embed `domain.QueryParams`, call `domain.ValidateQueryParams()` -- **Response**: `domain.RespSuccess(data)` (code=0) / `domain.RespError(msg)` (code=1) -- **Usecase**: every method starts with `context.WithTimeout` + `defer cancel()` -- **Errors**: sentinel errors in domain, `%w` wrapping, map to HTTP status in controller -- **Factory**: repo → usecase → controller, dependencies from `f.db`, `f.app`, `f.timeout` -- **Routes**: protected system routes use `casbinMiddleware.CheckAPIPermission()` - -### Step 4: Implement Frontend - -Follow the order: types → service → feature module → route file. - -**Read `references/frontend.md` for complete code templates and patterns.** - -Quick reference for key conventions: -- **API response**: `response.data.data` (outer `.data` = Axios, inner `.data` = `domain.Response.Data`) -- **Date parsing**: API service converts string dates to `Date` objects -- **Query params**: `URLSearchParams` construction, snake_case to match backend -- **Table state**: `useTableUrlState` hook syncs pagination/filters with URL -- **Dialog state**: string-based via context provider (`open === 'add' | 'edit' | 'delete'`) -- **Permissions**: `usePermission()` hook, `PERMISSIONS.SYSTEM.RESOURCE.ACTION` constants -- **Toast**: `sonner` for success/error notifications -- **Forms**: React Hook Form + Zod, single hook handles create/edit -- **Route file**: Zod schema validates URL search params with `.catch()` defaults - -### Step 5: Wire Permissions - -Shadmin uses a **dual-layer permission model**: - -``` -Backend (API access): Casbin checks (userID, path, method) -Frontend (UI visibility): Permission strings like "system:project:add" -``` - -These are linked through the **Role → Menu → API Resources** binding: -1. Backend auto-scans routes into API resources on startup (`bootstrap.InitApiResources`) -2. API resource IDs are deterministic: `METHOD:/api/v1/path` (e.g., `GET:/api/v1/system/project`) -3. Admin assigns menus to roles, each menu binds to API resources -4. Frontend fetches permissions from `/api/v1/resources` and stores in Zustand - -**To add permissions for a new feature:** -1. Backend: routes auto-register as API resources on restart -2. Frontend: add permission constants in `frontend/src/constants/permissions.ts` -3. Admin panel: create menu entries, bind API resources, assign to roles - -### Step 6: Generate & Verify - -```bash -# Backend -go generate ./ent # If schema changed -go fmt ./... && go vet ./... # Format + static analysis -go test ./... # Run tests -swag init -g main.go --output ./docs # If Swagger annotations changed - -# Frontend (from frontend/) -pnpm lint # ESLint -pnpm format:check # Prettier -pnpm build # Recommended if routes/build config changed -``` - -## Key Response Format - -```go -// Success (HTTP 200/201) -type Response struct { - Code int `json:"code"` // 0 = success - Msg string `json:"msg"` // "OK" - Data interface{} `json:"data"` // payload -} - -// Error (HTTP 400/404/500) -// Code = 1, Msg = error description, Data = nil - -// Paginated response (in Data field) -type PagedResult[T any] struct { - List []T `json:"list"` - Total int `json:"total"` - Page int `json:"page"` - PageSize int `json:"page_size"` - TotalPages int `json:"total_pages"` -} -``` - -## Boundaries - -Things to never do: -- **No business logic in controllers** — controllers parse HTTP, call usecase, return response -- **No HTTP/permission logic in repositories** — repositories do data access only -- **No bypassing Casbin** on protected APIs -- **No new globals** — use factory's `f.db`, `f.app`, `f.timeout` -- **No inline API calls in React** — all API access goes through `services/` wrappers -- **No direct localStorage for auth** — use `useAuthStore` -- **No editing `components/ui/`** — shadcn-generated primitives -- **No hardcoded menus** — menus come from backend `/api/v1/resources` -- **No unnecessary dependencies** — frontend or backend -- **Minimal changes** — only touch files relevant to the feature - -## Reference Files - -For detailed code templates and implementation patterns, read these as needed: - -- **`references/backend.md`** — Complete Go/Gin/Ent code templates for domain, schema, repository, usecase, controller, routes, and factory. Read when implementing backend features. -- **`references/frontend.md`** — Complete React/TypeScript code templates for types, API services, feature modules, hooks, tables, forms, dialogs, routes, and permissions. Read when implementing frontend features. - -## Further Documentation - -The `docs/getting-started/` directory contains comprehensive guides: -- `quickstart.zh.md` / `quickstart.en.md` — Quick start guide -- `architecture.zh.md` / `architecture.en.md` — Architecture deep-dive -- `development.zh.md` / `development.en.md` — Full CRUD walkthrough with example -- `deployment.zh.md` / `deployment.en.md` — Production deployment guide diff --git a/.claude/skills/shadmin-dev/references/backend.md b/.claude/skills/shadmin-dev/references/backend.md deleted file mode 100644 index 5ea66ca..0000000 --- a/.claude/skills/shadmin-dev/references/backend.md +++ /dev/null @@ -1,114 +0,0 @@ -# Backend Development Patterns - -Go/Gin/Ent patterns for Shadmin backend. Read this when implementing backend layers. - -## Domain Layer (`domain/.go`) - -Define contracts first — everything else implements these. - -**Entity struct** — JSON tags use `snake_case`, timestamps are `time.Time`. - -**Create request** — required fields use `binding:"required"`. - -**Update request** — all fields are pointers (`*string`, `*int`) to distinguish "not provided" from "set to empty". - -**Query params** — embed `domain.QueryParams` for built-in pagination support. - -**Repository interface** — `Create`, `GetByID`, `Fetch(params QueryParams) (*PagedResult[*T], error)`, `Update`, `Delete`. - -**UseCase interface** — mirrors repository but accepts request DTOs and applies business logic. - -**Sentinel errors** — `ErrResourceNotFound`, `ErrResourceAlreadyExists` — used by controller to map HTTP status. - -**Swagger type alias** — `type ResourcePagedResult = PagedResult[*Resource]` for Swagger annotations. - -### Built-in domain helpers - -`domain.QueryParams` embeds into resource query params; `domain.ValidateQueryParams()` sets defaults (Page=1, PageSize=10, Max=10000). - -`domain.NewPagedResult(items, total, page, pageSize)` builds paginated response. - -`domain.RespSuccess(data)` → `{code:0, msg:"OK", data:...}` / `domain.RespError(msg)` → `{code:1, msg:...}`. - -## Ent Schema (`ent/schema/.go`) - -- ID: `field.String("id").DefaultFunc(func() string { return xid.New().String() })` -- Timestamps: `field.Time("created_at").Default(time.Now)` / `.UpdateDefault(time.Now)` for updated_at -- Unique fields: `.Unique()` — Ent enforces at DB level -- Optional fields: `.Optional().Default("")` -- Add relevant indexes for frequently filtered fields - -Run `go generate ./ent` after any schema change. - -## Repository (`repository/_repository.go`) - -- Struct holds `*ent.Client`; constructor returns `domain.ResourceRepository` -- `convertToDomain()` private method converts Ent entity to domain entity -- **GetByID**: wrap `ent.IsNotFound(err)` → return domain sentinel error -- **Fetch**: call `domain.ValidateQueryParams` first; clone query for count before applying offset/limit; default sort by `created_at` DESC -- **Update**: check each pointer field before calling `Set*()`; wrap `ent.IsNotFound` → sentinel error -- All errors wrapped with `fmt.Errorf("...: %w", err)` - -## Usecase (`usecase/_usecase.go`) - -- Constructor: `func NewUsecase(client *ent.Client, repo domain.ResourceRepository, timeout time.Duration) domain.ResourceUseCase` -- Every method: `ctx, cancel := context.WithTimeout(ctx, uc.contextTimeout); defer cancel()` -- Business validation lives here (status enums, uniqueness checks, cross-entity rules) -- Set defaults on create requests (e.g., `if req.Status == "" { req.Status = "active" }`) -- Errors wrapped with `fmt.Errorf("...: %w", err)` - -## Controller (`api/controller/_controller.go`) - -- Struct holds `domain.ResourceUseCase`; no business logic -- Parse: `c.ShouldBindQuery` for GET params, `c.ShouldBindJSON` for request body, `c.Param("id")` for path params -- Return `domain.RespSuccess(data)` / `domain.RespError(err.Error())` with correct HTTP status -- Use `errors.Is(err, domain.ErrResourceNotFound)` to map sentinel errors to status codes -- Every handler has Swagger annotations (`@Summary`, `@Tags`, `@Security BearerAuth`, `@Param`, `@Success`, `@Failure`, `@Router`) - -### HTTP status mapping - -| Scenario | Status | -|----------|--------| -| Success (read/update/delete) | 200 | -| Success (create) | 201 | -| Validation error | 400 | -| Not found | 404 | -| Already exists / conflict | 409 | -| Server error | 500 | - -## Routes (`api/route/`) - -Add a `setupManagement(systemGroup *gin.RouterGroup, casbinMiddleware)` method in `protected.go` (or system routes file), then call it from `setupSystemRoutes`. - -REST convention: -- `GET /system/resource` — list (paginated) -- `POST /system/resource` — create -- `GET /system/resource/:id` — get by ID -- `PUT /system/resource/:id` — update -- `DELETE /system/resource/:id` — delete - -All system routes use `group.Use(casbinMiddleware.CheckAPIPermission())`. - -## Factory (`api/route/factory.go`) - -Wire in one method: -```go -func (f *ControllerFactory) CreateController() *controller.ResourceController { - repo := repository.NewResourceRepository(f.db) - uc := usecase.NewResourceUsecase(f.db, repo, f.timeout) - return &controller.ResourceController{ResourceUseCase: uc} -} -``` - -Available factory fields: `f.db` (`*ent.Client`), `f.app` (`*bootstrap.Application` — has `CasManager`, `FileRepo`, `ApiEngine`), `f.timeout` (`time.Duration`). - -## Auth & Middleware - -### JWT context keys (injected by `JwtAuthMiddleware`) -- `x-user-id`, `x-user-name`, `x-user-email`, `x-user-is-admin`, `x-user-roles` - -### Casbin middleware -`CheckAPIPermission()` enforces `(userID, requestPath, requestMethod)` — returns 403 if denied. Whitelisted paths (health, swagger) are auto-skipped. - -### API resource auto-scan -On startup, `bootstrap.InitApiResources` scans all Gin routes and persists records with ID format `METHOD:/api/v1/path`. Existing menu→API resource associations are preserved across rebuilds. diff --git a/.claude/skills/shadmin-dev/references/frontend.md b/.claude/skills/shadmin-dev/references/frontend.md deleted file mode 100644 index dac6c0a..0000000 --- a/.claude/skills/shadmin-dev/references/frontend.md +++ /dev/null @@ -1,169 +0,0 @@ -# Frontend Development Patterns - -React/TypeScript patterns for Shadmin frontend. Read this when implementing frontend layers. - -## Tech Stack - -- **React 19** + TypeScript strict mode -- **Vite** + SWC + TanStack Router plugin (file-based routing, auto-generates `routeTree.gen.ts`) -- **TanStack Query** — data fetching, caching, mutations -- **TanStack Table** — headless table with server-side pagination/filtering -- **Zustand** — auth and permission state (`auth-store`) -- **React Hook Form** + **Zod** — form state and validation -- **Shadcn UI** (Radix + Tailwind v4) — UI primitives in `components/ui/` (do not edit) -- **Axios** — HTTP via `apiClient` singleton in `services/config.ts` -- **Sonner** — toast notifications via `toast.success` / `toast.error` -- **Lucide React** — icons - -## Feature Module Structure - -``` -frontend/src/features/system// -├── components/ -│ ├── -provider.tsx # Context: dialog state + current row -│ ├── -columns.tsx # TanStack Table column definitions -│ ├── -table.tsx # Data table with server-side pagination -│ ├── -dialogs.tsx # Dialog aggregation (renders all dialogs) -│ ├── -primary-buttons.tsx # Header action buttons (permission-gated) -│ └── -form-dialog.tsx # Create/edit form (single component handles both) -├── data/ -│ └── schema.ts # Zod: data schema (API) + form schema (input) -├── hooks/ -│ └── use-.ts # TanStack Query hooks -└── index.tsx # Page entry component -``` - -## Types (`frontend/src/types/.ts`) - -- Field names use `snake_case` to match backend domain structs -- Date fields are `Date` objects (not strings) — parsed in the API service -- Go pointer fields (`*string`) become optional TypeScript fields (`name?: string`) -- Define `CreateRequest`, `UpdateRequest`, `QueryParams` interfaces alongside the entity - -## API Service (`frontend/src/services/Api.ts`) - -- Import `apiClient` from `@/services/config` -- Always read `response.data.data` — outer `.data` is Axios, inner `.data` is `domain.Response.Data` -- Build query strings with `URLSearchParams`, using `snake_case` param names -- Parse string dates to `Date` objects via a `parseResource(raw)` converter function -- Endpoint pattern: `/api/v1/{module}/{resource}` - -### `apiClient` behavior (`services/config.ts`) -- Base URL derived from `window.location` (works with Nginx reverse proxy) -- Auto-injects `Authorization: Bearer ` via request interceptor -- On 401: attempts token refresh, retries original request; on retry failure: redirects to login -- 300s timeout - -## Context Provider (`components/-provider.tsx`) - -Manages dialog state and selected row for the entire feature page. - -- Dialog type is a string union: `'add' | 'edit' | 'delete' | null` -- Use `useDialogState(null)` hook from `@/hooks/use-dialog-state` -- Export both `` and `useResource()` context hook -- `useResource()` throws if used outside provider - -## TanStack Query Hooks (`hooks/use-.ts`) - -- Query key: string constant (e.g., `const RESOURCE_KEY = 'resources'`) -- List hook: `queryKey: [RESOURCE_KEY, params]`, `staleTime: 5 * 60 * 1000` -- Single item hook: `enabled: !!id` to skip when no ID -- Mutations: `invalidateQueries({ queryKey: [RESOURCE_KEY] })` on success -- Error messages from `error?.response?.data?.msg` (backend `domain.Response.Msg`) -- Batch delete: `Promise.all(ids.map(deleteFn))` -- Toast on success/error via `sonner` - -## Table (`components/-table.tsx`) - -- `manualPagination: true` + `manualFiltering: true` — server handles both -- `pageCount = Math.ceil(totalCount / pageSize)` -- `useTableUrlState({ search, navigate })` syncs pagination and filters with URL -- `getRouteApi('/_authenticated/path')` for type-safe URL state access -- Columns include: checkbox select, data columns, actions column (permission-gated edit/delete) -- `DataTableRowActions` for row-level edit/delete; checks `hasPermission()` before rendering - -## Dialog Aggregation (`components/-dialogs.tsx`) - -- Renders all dialogs in one place at the bottom of the page -- String-based `open` state from provider determines which dialog is active -- Use unique `key` prop on each dialog to force remount when switching rows -- Edit dialog wrapped in `{currentRow && (...)}` to avoid rendering with stale data -- On close: `setTimeout(() => setCurrentRow(null), 500)` to delay cleanup until animation ends - -## Form Dialog (`components/-form-dialog.tsx`) - -- Single component handles both create and edit via `currentRow?: Resource` prop -- `isEdit = !!currentRow` determines title, submit behavior, and disabled fields -- `useEffect` resets the form when `currentRow` changes -- Combine `useCreateResource()` + `useUpdateResource()` mutations; `isSubmitting` from either `.isPending` -- Form: React Hook Form + Zod resolver; submit calls appropriate mutation then resets and closes - -## Zod Schemas (`data/schema.ts`) - -- **Data schema**: validates API responses — use `z.coerce.date()` for date fields -- **Form schema**: validates user input — use `.min(1, 'message')` for required fields -- Export `z.infer` types alongside schemas - -## Page Entry (`index.tsx`) - -Structure: `` wraps `
` + `
` + ``. - -- `getRouteApi()` for type-safe search params -- Map URL params → API query params at the top of the component -- States: loading skeleton → error state → data table -- `` must wrap the entire page for dialog context to work - -## Route File (`frontend/src/routes/_authenticated/.tsx`) - -```typescript -const searchSchema = z.object({ - page: z.number().optional().catch(1), - page_size: z.number().optional().catch(10), - search: z.string().optional().catch(''), - // add resource-specific filters here -}) - -export const Route = createFileRoute('/_authenticated/system/')({ - validateSearch: searchSchema, - component: ResourcePage, -}) -``` - -- `.catch(defaultValue)` provides safe fallbacks for malformed URL params -- Route path must match backend API structure -- Restart `pnpm dev` after adding a route to regenerate `routeTree.gen.ts` - -## Permission Constants (`frontend/src/constants/permissions.ts`) - -Add new permissions following the hierarchical pattern: -```typescript -SYSTEM: { - RESOURCE: { - ADD: 'system:resource:add', - EDIT: 'system:resource:edit', - DELETE: 'system:resource:delete', - } -} -``` - -Usage: `const { hasPermission } = usePermission()` then `hasPermission(PERMISSIONS.SYSTEM.RESOURCE.ADD)`. - -Admin users (`is_admin`) bypass all checks. Non-admin users are checked against the permissions array fetched from `/api/v1/resources` after login, stored in Zustand `auth-store`. - -For component-level gating: use `` or `` from `@/components/auth/`. - -## Naming Conventions - -| Type | Naming | Example | -|------|--------|---------| -| Components | PascalCase `.tsx` | `ProjectsTable.tsx` | -| Hooks | `use-kebab-case.ts` | `use-projects.ts` | -| Services | `camelCaseApi.ts` | `projectApi.ts` | -| Types | `kebab-case.ts` | `project.ts` | -| Route files | match URL path | `system/projects.tsx` | - -## Import Rules - -Always use the `@/` alias. Never use relative paths beyond `./` within a feature module. - -Import order (enforced by Prettier plugin): React → third-party → Radix/form libs → TanStack → project aliases (`@/stores` → `@/lib` → `@/components` → `@/features`) → relative (`./`). From 32650afb059886f87df673d24decfcd2e59d3dde Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:46:27 +0800 Subject: [PATCH 06/18] refactor: docs --- docs/getting-started/architecture.en.md | 2 +- docs/getting-started/architecture.zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/architecture.en.md b/docs/getting-started/architecture.en.md index 93b4bd1..789ad05 100644 --- a/docs/getting-started/architecture.en.md +++ b/docs/getting-started/architecture.en.md @@ -255,7 +255,7 @@ User → Role → Permission Policy → API Resource (path + method) ``` **Backend**: Casbin middleware checks whether `(userID, requestPath, requestMethod)` matches a policy. -**Frontend**: `auth-store` provides `hasPermission()` / `hasRole()` / `canAccessMenu()` methods. `PermissionButton` / `PermissionGuard` components control UI visibility. +**Frontend**: `auth-store` provides `hasPermission()` / `hasRole()` / `canAccessMenu()` methods. UI visibility is controlled by the `usePermission()` hook together with `auth-store` checks. ### Menu and Resource Mechanism diff --git a/docs/getting-started/architecture.zh.md b/docs/getting-started/architecture.zh.md index de415e8..6f81bbf 100644 --- a/docs/getting-started/architecture.zh.md +++ b/docs/getting-started/architecture.zh.md @@ -255,7 +255,7 @@ Shadmin 使用 **Casbin RBAC** 进行权限控制: ``` **后端**:Casbin 中间件检查 `(userID, requestPath, requestMethod)` 是否匹配策略。 -**前端**:`auth-store` 提供 `hasPermission()` / `hasRole()` / `canAccessMenu()` 方法,`PermissionButton` / `PermissionGuard` 组件控制 UI 显隐。 +**前端**:`auth-store` 提供 `hasPermission()` / `hasRole()` / `canAccessMenu()` 方法,UI 显隐由 `usePermission()` hook 配合 `auth-store` 判定控制。 ### 菜单与资源机制 From 867190504452532eaeb8447f6c52bbfb029085da Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:47:50 +0800 Subject: [PATCH 07/18] refactor: user source --- .../system/login-logs/components/login-logs-columns.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/features/system/login-logs/components/login-logs-columns.tsx b/frontend/src/features/system/login-logs/components/login-logs-columns.tsx index b5eea29..5c7de5c 100644 --- a/frontend/src/features/system/login-logs/components/login-logs-columns.tsx +++ b/frontend/src/features/system/login-logs/components/login-logs-columns.tsx @@ -1,4 +1,5 @@ import { type ColumnDef } from '@tanstack/react-table' +import { USER_SOURCE_LOCAL, userSourceLabel } from '@/constants/user-source' import { Badge } from '@/components/ui/badge' import type { LoginLog } from '../data/schema' @@ -54,13 +55,13 @@ export const loginLogsColumns: ColumnDef[] = [ displayName: '登录来源', }, cell: ({ row }) => { - const source = (row.getValue('source') as string) || 'local' + const source = row.getValue('source') as string | undefined return ( - {source} + {userSourceLabel(source)} ) }, From ec6b78e3b5fd4bb57a851702306799cb32b2f611 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:56:56 +0800 Subject: [PATCH 08/18] feat: show nik name --- frontend/src/constants/user-source.ts | 13 ++++++++++++ .../system/users/components/users-columns.tsx | 21 +++++++++++++++++++ frontend/src/types/user.ts | 4 +++- repository/user_repository.go | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 frontend/src/constants/user-source.ts diff --git a/frontend/src/constants/user-source.ts b/frontend/src/constants/user-source.ts new file mode 100644 index 0000000..271f005 --- /dev/null +++ b/frontend/src/constants/user-source.ts @@ -0,0 +1,13 @@ + +export const USER_SOURCE_LOCAL = 'shadmin' + +const USER_SOURCE_LABELS: Record = { + [USER_SOURCE_LOCAL]: '本地', + github: 'GitHub', + google: 'Google', +} + +export function userSourceLabel(source?: string): string { + if (!source) return '未知' + return USER_SOURCE_LABELS[source] ?? source +} diff --git a/frontend/src/features/system/users/components/users-columns.tsx b/frontend/src/features/system/users/components/users-columns.tsx index ea7a9a5..ad7d3ab 100644 --- a/frontend/src/features/system/users/components/users-columns.tsx +++ b/frontend/src/features/system/users/components/users-columns.tsx @@ -1,6 +1,7 @@ import { type ColumnDef } from '@tanstack/react-table' import { type User } from '@/types/user' import { cn } from '@/lib/utils' +import { userSourceLabel } from '@/constants/user-source' import { Badge } from '@/components/ui/badge' import { Checkbox } from '@/components/ui/checkbox' import { DataTableColumnHeader } from '@/components/data-table' @@ -51,6 +52,14 @@ export const usersColumns: ColumnDef[] = [ }, enableHiding: false, }, + { + accessorKey: 'nickname', + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue('nickname') || '-'}
, + enableSorting: false, + }, { accessorKey: 'email', header: ({ column }) => ( @@ -60,6 +69,18 @@ export const usersColumns: ColumnDef[] = [
{row.getValue('email')}
), }, + { + accessorKey: 'source', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + {userSourceLabel(row.getValue('source') as string | undefined)} + + ), + enableSorting: false, + }, { accessorKey: 'phone', header: ({ column }) => ( diff --git a/frontend/src/types/user.ts b/frontend/src/types/user.ts index 3cf9037..82677e7 100644 --- a/frontend/src/types/user.ts +++ b/frontend/src/types/user.ts @@ -11,12 +11,14 @@ export type UserStatus = z.infer export const userSchema = z.object({ id: z.string(), username: z.string(), + nickname: z.string().optional(), email: z.string(), phone: z.string().optional(), avatar: z.string().optional(), bio: z.string().optional(), - provider_avatar_url: z.string().optional(), + source: z.string().optional(), is_admin: z.boolean().optional(), + is_active: z.boolean().optional(), status: userStatusSchema, department_id: z.string().optional(), department_name: z.string().optional(), diff --git a/repository/user_repository.go b/repository/user_repository.go index e36628b..edd7cdd 100644 --- a/repository/user_repository.go +++ b/repository/user_repository.go @@ -185,6 +185,7 @@ func (ur *entUserRepository) Query(c context.Context, filter domain.UserQueryFil domainUser := &domain.User{ ID: u.ID, Username: u.Username, + Nickname: u.Nickname, Email: derefString(u.Email), Phone: derefString(u.Phone), Source: string(u.Source), From 2701d8bf339a03f4e73666e917c215f9a2a7c073 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:57:36 +0800 Subject: [PATCH 09/18] refactor: name --- .../features/system/roles/components/roles-create-dialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/features/system/roles/components/roles-create-dialog.tsx b/frontend/src/features/system/roles/components/roles-create-dialog.tsx index 94001ea..9dea044 100644 --- a/frontend/src/features/system/roles/components/roles-create-dialog.tsx +++ b/frontend/src/features/system/roles/components/roles-create-dialog.tsx @@ -42,7 +42,7 @@ import { useMenuSelection } from '../hooks/use-menu-selection' import { type RoleFormData, useRoleForm } from '../hooks/use-role-form' import { MenuTreeSection } from './menu-tree-section' -interface CreateRoleDialogProps { +interface RolesCreateDialogProps { open: boolean onOpenChange: (open: boolean) => void role?: Role | null // Optional role for edit mode @@ -52,7 +52,7 @@ export function RolesCreateDialog({ open, onOpenChange, role, -}: CreateRoleDialogProps) { +}: RolesCreateDialogProps) { const isEditMode = !!role const queryClient = useQueryClient() From 71230e0c6655dc8180482d48457405caa61162be Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:58:12 +0800 Subject: [PATCH 10/18] refactor: use credentials --- frontend/src/services/authApi.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/frontend/src/services/authApi.ts b/frontend/src/services/authApi.ts index 9744b83..7b540d6 100644 --- a/frontend/src/services/authApi.ts +++ b/frontend/src/services/authApi.ts @@ -4,7 +4,7 @@ import { getRefreshToken } from '@/lib/token-storage' // 登录请求类型 export interface LoginRequest { - identifier?: string + identifier: string password: string captcha_id: string captcha_x: number @@ -43,17 +43,7 @@ export interface DeviceActivateResponse { export async function login( credentials: LoginRequest ): Promise> { - const identifier = credentials.identifier ?? '' - - const payload = { - Identifier: identifier, - password: credentials.password, - captcha_id: credentials.captcha_id, - captcha_x: credentials.captcha_x, - captcha_y: credentials.captcha_y, - } - - const resp = await apiClient.post('/api/v1/auth/login', payload) + const resp = await apiClient.post('/api/v1/auth/login', credentials) return resp.data } From 5c185961cee3c94e44a87c7c53c4085eed629869 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 16:58:22 +0800 Subject: [PATCH 11/18] refactor: docs --- .github/skills/shadmin-dev/references/frontend.md | 6 +++--- README.md | 2 +- README.zh.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/skills/shadmin-dev/references/frontend.md b/.github/skills/shadmin-dev/references/frontend.md index dac6c0a..a701afb 100644 --- a/.github/skills/shadmin-dev/references/frontend.md +++ b/.github/skills/shadmin-dev/references/frontend.md @@ -106,7 +106,7 @@ Manages dialog state and selected row for the entire feature page. ## Page Entry (`index.tsx`) -Structure: `` wraps `
` + `
` + ``. +Structure: `` wraps `` + `
` + ``. - `getRouteApi()` for type-safe search params - Map URL params → API query params at the top of the component @@ -150,7 +150,7 @@ Usage: `const { hasPermission } = usePermission()` then `hasPermission(PERMISSIO Admin users (`is_admin`) bypass all checks. Non-admin users are checked against the permissions array fetched from `/api/v1/resources` after login, stored in Zustand `auth-store`. -For component-level gating: use `` or `` from `@/components/auth/`. +Component-level gating: `usePermission()` + conditional render — `hasPermission(key)`, `hasAnyPermission([...])`, `hasAllPermissions([...])`; no wrapper component. ## Naming Conventions @@ -166,4 +166,4 @@ For component-level gating: use `` or `` from Always use the `@/` alias. Never use relative paths beyond `./` within a feature module. -Import order (enforced by Prettier plugin): React → third-party → Radix/form libs → TanStack → project aliases (`@/stores` → `@/lib` → `@/components` → `@/features`) → relative (`./`). +Import order (enforced by Prettier plugin): React → third-party → Radix/form libs → TanStack → project aliases (`@/stores` → `@/lib` → `@/utils` → `@/constants` → `@/hooks` → `@/components` → `@/features`) → relative (`./`). diff --git a/README.md b/README.md index bfed72e..508acda 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ go run . - **Authentication**: JWT access + refresh tokens via `Authorization: Bearer ` - **API Authorization**: Casbin middleware checks `(userID, path, method)` on protected routes -- **Frontend Guards**: Permission‑aware components (`PermissionButton`, `PermissionGuard`) +- **Frontend Guards**: Permission‑aware UI via the `usePermission()` hook and `auth-store` checks (`hasPermission()` / `hasRole()`) - **Menu System**: Dynamic menus from `/api/v1/resources`, auto‑adapted to user permissions
diff --git a/README.zh.md b/README.zh.md index 06acc7a..88c3192 100644 --- a/README.zh.md +++ b/README.zh.md @@ -62,7 +62,7 @@ go run . - **认证**:JWT 访问令牌 + 刷新令牌,通过 `Authorization: Bearer ` 传递 - **API 鉴权**:Casbin 中间件对受保护路由检查 `(userID, path, method)` -- **前端守卫**:权限感知组件(`PermissionButton`、`PermissionGuard`) +- **前端守卫**:通过 `usePermission()` hook 与 `auth-store` 的 `hasPermission()` / `hasRole()` 判定控制 UI 显隐 - **菜单系统**:通过 `/api/v1/resources` 获取动态菜单树,自动适配用户权限
From d1db3dc0feebb0ce974de946f13a8cbe8b5e0992 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 17:44:58 +0800 Subject: [PATCH 12/18] refactor: request pages --- api/controller/auth_controller.go | 33 +++++++------- api/controller/helpers.go | 1 - api/controller/role_controller.go | 25 +++++------ domain/menu.go | 13 ++---- domain/request.go | 53 ++++++----------------- domain/response.go | 9 +++- domain/role.go | 2 + repository/apiresource_repository.go | 8 ++-- repository/dict_repository.go | 62 +++++++-------------------- repository/loginlog_repository.go | 6 +-- repository/menu_repository.go | 5 +-- repository/role_repository.go | 13 +++--- repository/user_repository.go | 64 +++++++--------------------- usecase/dict_usecase.go | 6 --- usecase/menu_usecase.go | 22 +++------- usecase/role_usecase.go | 10 +++-- 16 files changed, 114 insertions(+), 218 deletions(-) diff --git a/api/controller/auth_controller.go b/api/controller/auth_controller.go index 3524eda..ac5c862 100644 --- a/api/controller/auth_controller.go +++ b/api/controller/auth_controller.go @@ -108,24 +108,25 @@ func (lc *AuthController) Login(c *gin.Context) { // 创建记录登录日志的辅助函数 recordLoginLog := func(status, failureReason string) { - if lc.LoginLogUsecase != nil { - logRequest := &domain.CreateLoginLogRequest{ - Username: request.Identifier, - LoginIP: clientIP, - UserAgent: userAgent, - Status: status, - Source: constants.UserSourceLocal, - FailureReason: failureReason, - } + if lc.LoginLogUsecase == nil { + return + } - // 异步记录日志,不阻塞登录流程 - go func() { - _, logErr := lc.LoginLogUsecase.CreateLoginLog(c, logRequest) - if logErr != nil { - fmt.Printf("Failed to record login log: %v\n", logErr) - } - }() + logRequest := &domain.CreateLoginLogRequest{ + Username: request.Identifier, + LoginIP: clientIP, + UserAgent: userAgent, + Status: status, + Source: constants.UserSourceLocal, + FailureReason: failureReason, } + + ctx := context.WithoutCancel(c.Request.Context()) + go func() { + if _, logErr := lc.LoginLogUsecase.CreateLoginLog(ctx, logRequest); logErr != nil { + fmt.Printf("Failed to record login log: %v\n", logErr) + } + }() } // 检查SecurityManager是否初始化 diff --git a/api/controller/helpers.go b/api/controller/helpers.go index 6a665ca..4efb4d8 100644 --- a/api/controller/helpers.go +++ b/api/controller/helpers.go @@ -24,7 +24,6 @@ func BindQueryParams(c *gin.Context) domain.QueryParams { } params.SortBy = c.Query("sort_by") params.Order = c.Query("order") - _ = domain.ValidateQueryParams(¶ms) return params } diff --git a/api/controller/role_controller.go b/api/controller/role_controller.go index e0426a8..c71619b 100644 --- a/api/controller/role_controller.go +++ b/api/controller/role_controller.go @@ -29,17 +29,18 @@ func (rc *RoleController) getRoleIDOrBadRequest(c *gin.Context) (string, bool) { return roleID, true } +// writeRoleMutationError 把 role 领域错误映射为 HTTP 状态码。 func (rc *RoleController) writeRoleMutationError(c *gin.Context, err error, forbiddenErr error) { - if errors.Is(err, forbiddenErr) { + switch { + case forbiddenErr != nil && errors.Is(err, forbiddenErr): c.JSON(http.StatusForbidden, domain.RespError(err.Error())) - return - } - if err.Error() == "role not found" { + case errors.Is(err, domain.ErrRoleNotFound): c.JSON(http.StatusNotFound, domain.RespError(err.Error())) - return + case errors.Is(err, domain.ErrRoleNameExists): + c.JSON(http.StatusConflict, domain.RespError(err.Error())) + default: + c.JSON(http.StatusInternalServerError, domain.RespError(err.Error())) } - - c.JSON(http.StatusInternalServerError, domain.RespError(err.Error())) } // RoleInfo 角色信息结构 @@ -98,15 +99,11 @@ func (rc *RoleController) CreateRole(c *gin.Context) { // Create the role err := rc.RoleUseCase.Create(c.Request.Context(), &request) if err != nil { - if err.Error() == "role code already exists" { - c.JSON(http.StatusConflict, domain.RespError(err.Error())) - return - } - c.JSON(http.StatusInternalServerError, domain.RespError(err.Error())) + rc.writeRoleMutationError(c, err, nil) return } - c.JSON(http.StatusCreated, domain.RespSuccess(err)) + c.JSON(http.StatusCreated, domain.RespSuccess(request.Name)) } // getRoleByID extracts the role ID from the path, fetches the role, and writes @@ -119,7 +116,7 @@ func (rc *RoleController) getRoleByID(c *gin.Context) *domain.Role { role, err := rc.RoleUseCase.GetByID(c.Request.Context(), roleID) if err != nil { - if err.Error() == "role not found" { + if errors.Is(err, domain.ErrRoleNotFound) { c.JSON(http.StatusNotFound, domain.RespError(err.Error())) return nil } diff --git a/domain/menu.go b/domain/menu.go index 1925e0a..9ef31f2 100644 --- a/domain/menu.go +++ b/domain/menu.go @@ -127,22 +127,17 @@ type MenuItem struct { RequiresAdmin bool `json:"requiresAdmin"` } -// ValidateMenuQueryParams validates and sets default values for menu query parameters -func ValidateMenuQueryParams(params *MenuQueryParams) error { - // 使用通用的分页参数验证 - if err := ValidateQueryParams(¶ms.QueryParams); err != nil { - return err - } +// ValidateMenuQueryParams 归一化分页参数并填充菜单查询的业务默认值。 +func ValidateMenuQueryParams(params *MenuQueryParams) { + params.Paginate() // 设置业务默认值 if params.Type == "" { - params.Type = "menu" + params.Type = MenuTypeMenu } if params.Status == "" { params.Status = constants.StatusSuccess } - - return nil } // Menu status constants diff --git a/domain/request.go b/domain/request.go index 4e1a039..1c44c62 100644 --- a/domain/request.go +++ b/domain/request.go @@ -1,8 +1,13 @@ package domain -// QueryParams 通用查询参数,包含分页信息、租户信息和用户权限信息 +const ( + DefaultPage = 1 + DefaultPageSize = 10 + MaxPageSize = 10000 +) + +// QueryParams 通用查询参数,包含分页和排序信息。 type QueryParams struct { - IsAdmin bool `json:"-" form:"-"` // 是否管理员,不从请求参数获取,由中间件设置 Page int `json:"page" form:"page"` PageSize int `json:"page_size" form:"page_size"` SortBy string `json:"sort_by" form:"sort_by"` @@ -17,45 +22,15 @@ type SystemQueryParams struct { Order string `json:"order" form:"order"` // asc, desc } -// GetPage returns the page number, defaulting to 1 if not set -func (qp *QueryParams) GetPage() int { - if qp.Page <= 0 { - return 1 +func (qp *QueryParams) Paginate() (offset, limit int) { + if qp.Page < DefaultPage { + qp.Page = DefaultPage } - return qp.Page -} - -// GetPageSize returns the page size, defaulting to 10 if not set -func (qp *QueryParams) GetPageSize() int { if qp.PageSize <= 0 { - return 10 - } - if qp.PageSize > 10000 { - return 10000 - } - return qp.PageSize -} - -// Paginate returns (offset, limit, true) when pagination should be applied, -// or (0, 0, false) when all results should be returned. -func (qp *QueryParams) Paginate() (offset, limit int, ok bool) { - if qp.Page > 0 && qp.PageSize > 0 { - return (qp.Page - 1) * qp.PageSize, qp.PageSize, true - } - return 0, 0, false -} - -// ValidateQueryParams 验证和设置默认分页参数以及租户权限 -func ValidateQueryParams(params *QueryParams) error { - // 验证分页参数 - if params.Page <= 0 { - params.Page = 1 - } - if params.PageSize <= 0 { - params.PageSize = 10 + qp.PageSize = DefaultPageSize } - if params.PageSize > 10000 { - params.PageSize = 10000 + if qp.PageSize > MaxPageSize { + qp.PageSize = MaxPageSize } - return nil + return (qp.Page - 1) * qp.PageSize, qp.PageSize } diff --git a/domain/response.go b/domain/response.go index 98b6fdc..9c63bf4 100644 --- a/domain/response.go +++ b/domain/response.go @@ -3,7 +3,6 @@ package domain const ( SuccessCode = 0 FailCode = 1 - NotFondCode = 404 ) type Response struct { @@ -38,8 +37,14 @@ type PagedResult[T any] struct { TotalPages int `json:"total_pages"` } -// NewPagedResult 创建分页结果 +// NewPagedResult 创建分页结果。 func NewPagedResult[T any](data []T, total, page, pageSize int) *PagedResult[T] { + if page < DefaultPage { + page = DefaultPage + } + if pageSize <= 0 { + pageSize = DefaultPageSize + } totalPages := (total + pageSize - 1) / pageSize return &PagedResult[T]{ List: data, diff --git a/domain/role.go b/domain/role.go index 2ba3ef1..100239c 100644 --- a/domain/role.go +++ b/domain/role.go @@ -15,6 +15,8 @@ const ( var ( ErrCannotDeleteAdminRole = errors.New("不能删除系统管理员角色") ErrCannotRenameAdminRole = errors.New("不能修改系统管理员角色名称") + ErrRoleNotFound = errors.New("角色不存在") + ErrRoleNameExists = errors.New("角色名称已存在") ) // Role represents a custom role in the system diff --git a/repository/apiresource_repository.go b/repository/apiresource_repository.go index b613fa2..38936c4 100644 --- a/repository/apiresource_repository.go +++ b/repository/apiresource_repository.go @@ -68,11 +68,11 @@ func (arr *entApiResourceRepository) FetchPaged(ctx context.Context, params doma return nil, fmt.Errorf("failed to count API resources: %w", err) } - // Apply pagination and ordering + offset, limit := params.Paginate() query = query. Order(ent.Asc(apiresource.FieldModule), ent.Asc(apiresource.FieldPath), ent.Asc(apiresource.FieldMethod)). - Offset((params.GetPage() - 1) * params.GetPageSize()). - Limit(params.GetPageSize()) + Offset(offset). + Limit(limit) entApiResources, err := query.All(ctx) if err != nil { @@ -84,5 +84,5 @@ func (arr *entApiResourceRepository) FetchPaged(ctx context.Context, params doma apiResources[i] = arr.convertEntApiResourceToDomain(entApiResource) } - return domain.NewPagedResult(apiResources, total, params.GetPage(), params.GetPageSize()), nil + return domain.NewPagedResult(apiResources, total, params.Page, params.PageSize), nil } diff --git a/repository/dict_repository.go b/repository/dict_repository.go index c291f6f..8671dd5 100644 --- a/repository/dict_repository.go +++ b/repository/dict_repository.go @@ -90,50 +90,6 @@ func (dr *entDictRepository) convertEntDictItemToDomain(entItem *ent.DictItem) * } } -func (dr *entDictRepository) listPagedDictTypes(ctx context.Context, query *ent.DictTypeQuery, page int, pageSize int) ([]*domain.DictType, error) { - var entTypes []*ent.DictType - var err error - - if page > 0 && pageSize > 0 { - offset := (page - 1) * pageSize - entTypes, err = query.Offset(offset).Limit(pageSize).All(ctx) - } else { - entTypes, err = query.All(ctx) - } - if err != nil { - return nil, err - } - - result := make([]*domain.DictType, 0, len(entTypes)) - for _, entType := range entTypes { - result = append(result, dr.convertEntDictTypeToDomain(entType)) - } - - return result, nil -} - -func (dr *entDictRepository) listPagedDictItems(ctx context.Context, query *ent.DictItemQuery, page int, pageSize int) ([]*domain.DictItem, error) { - var entItems []*ent.DictItem - var err error - - if page > 0 && pageSize > 0 { - offset := (page - 1) * pageSize - entItems, err = query.Offset(offset).Limit(pageSize).All(ctx) - } else { - entItems, err = query.All(ctx) - } - if err != nil { - return nil, err - } - - result := make([]*domain.DictItem, 0, len(entItems)) - for _, entItem := range entItems { - result = append(result, dr.convertEntDictItemToDomain(entItem)) - } - - return result, nil -} - // 字典类型相关实现 func (dr *entDictRepository) CreateType(ctx context.Context, dictType *domain.DictType) error { @@ -240,11 +196,18 @@ func (dr *entDictRepository) FetchTypes(ctx context.Context, params domain.DictT query = query.Order(ent.Desc(dicttype.FieldCreatedAt)) } - result, err := dr.listPagedDictTypes(ctx, query, params.Page, params.PageSize) + // 应用统一分页窗口 + offset, limit := params.Paginate() + entTypes, err := query.Offset(offset).Limit(limit).All(ctx) if err != nil { return nil, err } + result := make([]*domain.DictType, 0, len(entTypes)) + for _, entType := range entTypes { + result = append(result, dr.convertEntDictTypeToDomain(entType)) + } + return domain.NewPagedResult(result, total, params.Page, params.PageSize), nil } @@ -456,11 +419,18 @@ func (dr *entDictRepository) FetchItems(ctx context.Context, params domain.DictI query = query.Order(ent.Asc(dictitem.FieldSort), ent.Desc(dictitem.FieldCreatedAt)) } - result, err := dr.listPagedDictItems(ctx, query, params.Page, params.PageSize) + // 应用统一分页窗口 + offset, limit := params.Paginate() + entItems, err := query.Offset(offset).Limit(limit).All(ctx) if err != nil { return nil, err } + result := make([]*domain.DictItem, 0, len(entItems)) + for _, entItem := range entItems { + result = append(result, dr.convertEntDictItemToDomain(entItem)) + } + return domain.NewPagedResult(result, total, params.Page, params.PageSize), nil } diff --git a/repository/loginlog_repository.go b/repository/loginlog_repository.go index cfc0f09..7c71964 100644 --- a/repository/loginlog_repository.go +++ b/repository/loginlog_repository.go @@ -111,10 +111,8 @@ func (lr *entLoginLogRepository) Query(c context.Context, filter domain.LoginLog baseQuery = baseQuery.Order(ent.Desc(loginlog.FieldLoginTime)) } - // 应用分页 - if offset, limit, ok := filter.Paginate(); ok { - baseQuery = baseQuery.Offset(offset).Limit(limit) - } + offset, limit := filter.Paginate() + baseQuery = baseQuery.Offset(offset).Limit(limit) logs, err := baseQuery.All(c) if err != nil { return nil, err diff --git a/repository/menu_repository.go b/repository/menu_repository.go index 7b79c74..547574b 100644 --- a/repository/menu_repository.go +++ b/repository/menu_repository.go @@ -102,9 +102,8 @@ func (mr *entMenuRepository) GetMenus(ctx context.Context, params domain.MenuQue if err != nil { return nil, err } - - // Apply pagination and ordering, and include API resources - offset := (params.Page - 1) * params.PageSize + // 不需要limit限制 + offset, _ := params.Paginate() menus, err := query. WithAPIResources(). Order(menu.BySequence(), menu.ByCreatedAt()). diff --git a/repository/role_repository.go b/repository/role_repository.go index 738c95f..e25b204 100644 --- a/repository/role_repository.go +++ b/repository/role_repository.go @@ -105,11 +105,12 @@ func (rr *entRoleRepository) FetchPaged(c context.Context, params domain.QueryPa } // Apply pagination and ordering + offset, limit := params.Paginate() query = query. WithMenus(). Order(ent.Asc(role.FieldSequence)). - Offset((params.Page - 1) * params.PageSize). - Limit(params.PageSize) + Offset(offset). + Limit(limit) entRoles, err := query.All(c) if err != nil { @@ -131,7 +132,7 @@ func (rr *entRoleRepository) GetByID(c context.Context, id string) (*domain.Role Only(c) if err != nil { if ent.IsNotFound(err) { - return nil, fmt.Errorf("role not found") + return nil, domain.ErrRoleNotFound } return nil, fmt.Errorf("failed to get role by ID: %w", err) } @@ -146,7 +147,7 @@ func (rr *entRoleRepository) GetByName(c context.Context, name string) (*domain. Only(c) if err != nil { if ent.IsNotFound(err) { - return nil, fmt.Errorf("role not found") + return nil, domain.ErrRoleNotFound } return nil, fmt.Errorf("failed to get role by name: %w", err) } @@ -179,7 +180,7 @@ func (rr *entRoleRepository) Delete(c context.Context, id string) error { err := rr.client.Role.DeleteOneID(id).Exec(c) if err != nil { if ent.IsNotFound(err) { - return fmt.Errorf("role not found") + return domain.ErrRoleNotFound } return fmt.Errorf("failed to delete role: %w", err) } @@ -208,7 +209,7 @@ func (rr *entRoleRepository) DeleteIfUnused(c context.Context, id, name string) if err := tx.Role.DeleteOneID(id).Exec(c); err != nil { if ent.IsNotFound(err) { - return fmt.Errorf("role not found") + return domain.ErrRoleNotFound } return fmt.Errorf("failed to delete role: %w", err) } diff --git a/repository/user_repository.go b/repository/user_repository.go index edd7cdd..9166a0b 100644 --- a/repository/user_repository.go +++ b/repository/user_repository.go @@ -46,15 +46,14 @@ func emptyToNil(s string) *string { return &s } -// entUserToDomainUser converts an ent.User to domain.User and extracts role IDs from edges -func entUserToDomainUser(u *ent.User) *domain.User { +// entUserToDomainUser converts an ent.User to domain.User and extracts role IDs from edges. +func entUserToDomainUser(u *ent.User, withPassword bool) *domain.User { domainUser := &domain.User{ ID: u.ID, Username: u.Username, Nickname: u.Nickname, Email: derefString(u.Email), Phone: derefString(u.Phone), - Password: derefString(u.Password), Source: string(u.Source), Avatar: u.Avatar, IsAdmin: u.IsAdmin, @@ -63,6 +62,9 @@ func entUserToDomainUser(u *ent.User) *domain.User { CreatedAt: u.CreatedAt, UpdatedAt: u.UpdatedAt, } + if withPassword { + domainUser.Password = derefString(u.Password) + } // Extract role IDs from database relationship if u.Edges.Roles != nil { @@ -170,57 +172,23 @@ func (ur *entUserRepository) Query(c context.Context, filter domain.UserQueryFil // 构建数据查询 (移除租户信息预加载) query := baseQuery - // 应用分页 - if offset, limit, ok := filter.Paginate(); ok { - query = query.Offset(offset).Limit(limit) + // 需要角色时在基础查询上一次性预加载,避免逐行回查(N+1) + if filter.IncludeRoles { + query = query.WithRoles() } + + offset, limit := filter.Paginate() + query = query.Offset(offset).Limit(limit) + users, err := query.WithDepartment().All(c) if err != nil { return nil, err } - // 转换为 domain.User (移除租户相关代码) + // 列表响应不携带密码哈希,与单条查询共用同一转换函数 var result []*domain.User for _, u := range users { - domainUser := &domain.User{ - ID: u.ID, - Username: u.Username, - Nickname: u.Nickname, - Email: derefString(u.Email), - Phone: derefString(u.Phone), - Source: string(u.Source), - Avatar: u.Avatar, - IsAdmin: u.IsAdmin, - Status: entStatusToDomainStatus(u.Status), - DepartmentID: u.DepartmentID, - CreatedAt: u.CreatedAt, - UpdatedAt: u.UpdatedAt, - } - if u.Edges.Department != nil { - domainUser.DepartmentName = u.Edges.Department.Name - } - - // 如果需要包含角色信息 (从数据库关系获取) - if filter.IncludeRoles { - // 重新查询包含角色信息的用户 - userWithRoles, err := ur.client.User. - Query(). - Where(user.ID(u.ID)). - WithRoles(). - First(c) - if err == nil && userWithRoles.Edges.Roles != nil { - var roleIDs []string - for _, role := range userWithRoles.Edges.Roles { - roleIDs = append(roleIDs, role.ID) - } - domainUser.Roles = roleIDs - if len(roleIDs) > 0 { - domainUser.IsActive = true // 有角色说明是活跃的 - } - } - } - - result = append(result, domainUser) + result = append(result, entUserToDomainUser(u, false)) } return domain.NewPagedResult(result, total, filter.Page, filter.PageSize), nil @@ -247,7 +215,7 @@ func (ur *entUserRepository) GetByIdentifier(c context.Context, identifier strin return nil, err } - return entUserToDomainUser(u), nil + return entUserToDomainUser(u, true), nil } func (ur *entUserRepository) GetByID(c context.Context, id string) (*domain.User, error) { @@ -262,7 +230,7 @@ func (ur *entUserRepository) GetByID(c context.Context, id string) (*domain.User return nil, err } - return entUserToDomainUser(u), nil + return entUserToDomainUser(u, true), nil } // Update 更新用户信息 diff --git a/usecase/dict_usecase.go b/usecase/dict_usecase.go index d290626..01a8b96 100644 --- a/usecase/dict_usecase.go +++ b/usecase/dict_usecase.go @@ -67,9 +67,6 @@ func (du *dictUsecase) ListDictTypes(ctx context.Context, params domain.DictType ctx, cancel := context.WithTimeout(ctx, du.contextTimeout) defer cancel() - // 验证和设置默认分页参数 - _ = domain.ValidateQueryParams(¶ms.QueryParams) - return du.dictRepository.FetchTypes(ctx, params) } @@ -139,9 +136,6 @@ func (du *dictUsecase) ListDictItems(ctx context.Context, params domain.DictItem ctx, cancel := context.WithTimeout(ctx, du.contextTimeout) defer cancel() - // 验证和设置默认分页参数 - _ = domain.ValidateQueryParams(¶ms.QueryParams) - return du.dictRepository.FetchItems(ctx, params) } diff --git a/usecase/menu_usecase.go b/usecase/menu_usecase.go index cdf0c3b..09b6dc0 100644 --- a/usecase/menu_usecase.go +++ b/usecase/menu_usecase.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "shadmin/domain" + "slices" "time" ) @@ -20,7 +21,7 @@ func NewMenuUsecase(menuRepository domain.MenuRepository, timeout time.Duration) } } -// Query operations +// GetMenuTree Query operations func (mu *menuUsecase) GetMenuTree(ctx context.Context) ([]domain.MenuTreeNode, error) { ctx, cancel := context.WithTimeout(ctx, mu.contextTimeout) defer cancel() @@ -31,8 +32,7 @@ func (mu *menuUsecase) GetMenus(ctx context.Context, params domain.MenuQueryPara ctx, cancel := context.WithTimeout(ctx, mu.contextTimeout) defer cancel() - // Validate query parameters - _ = domain.ValidateMenuQueryParams(¶ms) + domain.ValidateMenuQueryParams(¶ms) return mu.menuRepository.GetMenus(ctx, params) } @@ -51,13 +51,7 @@ func (mu *menuUsecase) CreateMenu(ctx context.Context, req *domain.CreateMenuReq // Validate menu type validTypes := []string{domain.MenuTypeMenu, domain.MenuTypeButton} - isValidType := false - for _, validType := range validTypes { - if req.Type == validType { - isValidType = true - break - } - } + isValidType := slices.Contains(validTypes, req.Type) if !isValidType { return nil, domain.ErrInvalidMenuType } @@ -91,13 +85,7 @@ func (mu *menuUsecase) UpdateMenu(ctx context.Context, id string, req *domain.Up // Validate menu type validTypes := []string{domain.MenuTypeMenu, domain.MenuTypeButton} - isValidType := false - for _, validType := range validTypes { - if req.Type == validType { - isValidType = true - break - } - } + isValidType := slices.Contains(validTypes, req.Type) if !isValidType { return nil, domain.ErrInvalidMenuType } diff --git a/usecase/role_usecase.go b/usecase/role_usecase.go index 0f9efac..0de0087 100644 --- a/usecase/role_usecase.go +++ b/usecase/role_usecase.go @@ -2,6 +2,7 @@ package usecase import ( "context" + "errors" "fmt" "log" "shadmin/domain" @@ -20,7 +21,10 @@ func (ru *roleUsecase) Create(c context.Context, request *domain.CreateRoleReque // Check if role with same name already exists existingRole, err := ru.roleRepository.GetByName(ctx, request.Name) if err == nil && existingRole != nil { - return err + return domain.ErrRoleNameExists + } + if err != nil && !errors.Is(err, domain.ErrRoleNotFound) { + return fmt.Errorf("failed to check existing role: %w", err) } // Create the role domain model @@ -76,7 +80,7 @@ func (ru *roleUsecase) Update(c context.Context, id string, request *domain.Upda // Get existing role existingRole, err := ru.roleRepository.GetByID(ctx, id) if err != nil { - return nil, fmt.Errorf("role not found: %w", err) + return nil, fmt.Errorf("failed to get role: %w", err) } // 系统内置角色名称受保护,不允许修改 @@ -131,7 +135,7 @@ func (ru *roleUsecase) Delete(c context.Context, id string) error { // 1. 检查角色是否存在 role, err := ru.roleRepository.GetByID(ctx, id) if err != nil { - return fmt.Errorf("role not found: %w", err) + return fmt.Errorf("failed to get role: %w", err) } // 系统内置角色受保护,不允许删除 From edb379531bf9fe6c28eed84e0f88c5ecad2e4b2d Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 21:21:57 +0800 Subject: [PATCH 13/18] perf: user token extract --- api/controller/auth_controller.go | 62 +++----- api/middleware/casbin_middleware.go | 23 ++- api/middleware/jwt_auth_middleware.go | 58 ++++--- domain/jwt_custom.go | 7 + internal/tokenservice/token_service.go | 32 +--- internal/tokenutil/tokenutil.go | 205 ++++--------------------- 6 files changed, 115 insertions(+), 272 deletions(-) diff --git a/api/controller/auth_controller.go b/api/controller/auth_controller.go index ac5c862..0ed96fa 100644 --- a/api/controller/auth_controller.go +++ b/api/controller/auth_controller.go @@ -16,6 +16,7 @@ import ( "shadmin/domain" "shadmin/internal/tokenservice" + "shadmin/pkg" "github.com/gin-gonic/gin" ) @@ -254,36 +255,33 @@ func (lc *AuthController) RefreshToken(c *gin.Context) { c.JSON(http.StatusBadRequest, domain.RespError("Invalid request format")) return } - // 验证刷新令牌是否有效 - isValid, err := lc.TokenService.IsAuthorized(request.RefreshToken, lc.Env.RefreshTokenSecret) - if err != nil || !isValid { + refreshClaims, err := lc.TokenService.ParseRefreshClaims(request.RefreshToken, lc.Env.RefreshTokenSecret) + if err != nil { c.JSON(http.StatusUnauthorized, domain.RespError("Invalid refresh token")) return } - // 黑名单校验:refresh token 的 jti 已登出则拒绝续发。 if lc.TokenBlacklist != nil { - if jti, jErr := lc.TokenService.ExtractJTI(request.RefreshToken, lc.Env.RefreshTokenSecret); jErr == nil && jti != "" { - revoked, rErr := lc.TokenBlacklist.Exists(c.Request.Context(), jti) - if rErr != nil { - c.JSON(http.StatusUnauthorized, domain.RespError("令牌无法验证")) - return - } - if revoked { - c.JSON(http.StatusUnauthorized, domain.RespError("令牌已登出")) - return - } + // 黑名单以 jti 为键:无 jti 的令牌无法吊销,直接拒绝 + if refreshClaims.JTI() == "" { + c.JSON(http.StatusUnauthorized, domain.RespError("Invalid refresh token")) + return } - } - // 从刷新令牌中提取用户ID - userID, err := lc.TokenService.ExtractIDFromToken(request.RefreshToken, lc.Env.RefreshTokenSecret) - if err != nil { - c.JSON(http.StatusUnauthorized, domain.RespError("Invalid refresh token")) - return + revoked, rErr := lc.TokenBlacklist.Exists(c.Request.Context(), refreshClaims.JTI()) + if rErr != nil { + c.JSON(http.StatusUnauthorized, domain.RespError("令牌无法验证")) + return + } + if revoked { + c.JSON(http.StatusUnauthorized, domain.RespError("令牌已登出")) + return + } } + userID := refreshClaims.ID + // 根据用户ID获取用户信息 user, err := lc.LoginUsecase.GetUserByID(c, userID) if err != nil { @@ -344,32 +342,20 @@ func (lc *AuthController) Logout(c *gin.Context) { // 从请求头中提取访问令牌 authHeader := c.Request.Header.Get("Authorization") var accessToken string - if authHeader != "" { - parts := strings.Split(authHeader, " ") - if len(parts) == 2 && parts[0] == "Bearer" { - accessToken = parts[1] - } + if scheme, token, found := strings.Cut(authHeader, " "); found && token != "" && strings.EqualFold(scheme, "Bearer") { + accessToken = token } - // 提取用户信息用于日志记录 + // 登出审计日志(不记录令牌内容) var userID, userName string if accessToken != "" { - // 从令牌中提取用户信息(即使令牌即将失效,我们仍然可以从中提取信息用于日志) - if claims, err := lc.TokenService.ExtractAllClaimsFromToken(accessToken, lc.Env.AccessTokenSecret); err == nil { + // 令牌即将失效时仍可解析出用户信息用于日志 + if claims, err := lc.TokenService.ParseAccessClaims(accessToken, lc.Env.AccessTokenSecret); err == nil { userID = claims.ID userName = claims.Name } } - - // 记录登出日志 - fmt.Printf("User logout - UserID: %s, UserName: %s, AccessToken: %s...\n", - userID, userName, - func() string { - if len(accessToken) > 10 { - return accessToken[:10] - } - return accessToken - }()) + pkg.Log.Infof("User logout - UserID: %s, UserName: %s", userID, userName) // 将 access/refresh token 的 jti 加入黑名单,TTL 设为 token 剩余有效期。 // 老令牌无 jti 时跳过;黑名单未配置时整体跳过(向后兼容)。 diff --git a/api/middleware/casbin_middleware.go b/api/middleware/casbin_middleware.go index 8f3567c..2ad0cfd 100644 --- a/api/middleware/casbin_middleware.go +++ b/api/middleware/casbin_middleware.go @@ -3,12 +3,15 @@ package middleware import ( "fmt" "net/http" + "strings" + "shadmin/domain" "shadmin/internal/casbin" "shadmin/internal/constants" - "strings" + "shadmin/pkg" "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" ) // CasbinMiddleware API权限鉴权中间件 @@ -32,28 +35,32 @@ func (m *CasbinMiddleware) CheckAPIPermission() gin.HandlerFunc { path := c.Request.URL.Path method := c.Request.Method - fmt.Printf("🔍 API权限检查> 用户ID %s, %s %s\n", userID, method, path) + fmt.Printf("🔍 user= %s method=%s path=%s\n", userID, method, path) // 跳过不需要权限校验的API if m.shouldSkipPermissionCheck(path) { - fmt.Printf("✅ 跳过权限检查: %s\n", path) c.Next() return } - // 包装用户ID后传给 Manager hasPermission, err := m.CasManager.CheckPermission(userID, path, method) - - fmt.Printf("🔍 检查结果: %t, error=%v\n", hasPermission, err) - if err != nil { - fmt.Printf("❌ 权限检查错误: %v\n", err) + pkg.Log.WithFields(logrus.Fields{ + "user_id": userID, + "method": method, + "path": path, + }).WithError(err).Error("API 权限检查失败") c.JSON(http.StatusInternalServerError, domain.RespError("权限检查失败")) c.Abort() return } if !hasPermission { + pkg.Log.WithFields(logrus.Fields{ + "user_id": userID, + "method": method, + "path": path, + }).Warn("API 权限不足") c.JSON(http.StatusForbidden, domain.RespError("权限不足")) c.Abort() return diff --git a/api/middleware/jwt_auth_middleware.go b/api/middleware/jwt_auth_middleware.go index 83d55ae..6b70d5e 100644 --- a/api/middleware/jwt_auth_middleware.go +++ b/api/middleware/jwt_auth_middleware.go @@ -2,11 +2,12 @@ package middleware import ( "net/http" + "strings" + "shadmin/domain" "shadmin/internal/auth" "shadmin/internal/constants" "shadmin/internal/tokenservice" - "strings" "github.com/gin-gonic/gin" ) @@ -16,22 +17,14 @@ func JwtAuthMiddleware(secret string, tokenBlacklist auth.JWTBlacklist) gin.Hand tokenService := tokenservice.NewTokenService() return func(c *gin.Context) { - authHeader := c.Request.Header.Get("Authorization") - t := strings.Split(authHeader, " ") - if len(t) != 2 { + authToken, ok := bearerToken(c.Request.Header.Get("Authorization")) + if !ok { c.JSON(http.StatusUnauthorized, domain.RespError("Not authorized")) c.Abort() return } - authToken := t[1] - authorized, err := tokenService.IsAuthorized(authToken, secret) - if !authorized { - c.JSON(http.StatusUnauthorized, domain.RespError(err.Error())) - c.Abort() - return - } - claims, err := tokenService.ExtractAllClaimsFromToken(authToken, secret) + claims, err := tokenService.ParseAccessClaims(authToken, secret) if err != nil { c.JSON(http.StatusUnauthorized, domain.RespError(err.Error())) c.Abort() @@ -39,18 +32,23 @@ func JwtAuthMiddleware(secret string, tokenBlacklist auth.JWTBlacklist) gin.Hand } if tokenBlacklist != nil { - if jti, jErr := tokenService.ExtractJTI(authToken, secret); jErr == nil && jti != "" { - revoked, rErr := tokenBlacklist.Exists(c.Request.Context(), jti) - if rErr != nil { - c.JSON(http.StatusUnauthorized, domain.RespError("令牌无法验证")) - c.Abort() - return - } - if revoked { - c.JSON(http.StatusUnauthorized, domain.RespError("令牌已登出")) - c.Abort() - return - } + // 黑名单以 jti 为键:无 jti 的令牌无法吊销,直接拒绝 + if claims.JTI() == "" { + c.JSON(http.StatusUnauthorized, domain.RespError("令牌无效")) + c.Abort() + return + } + + revoked, rErr := tokenBlacklist.Exists(c.Request.Context(), claims.JTI()) + if rErr != nil { + c.JSON(http.StatusUnauthorized, domain.RespError("令牌无法验证")) + c.Abort() + return + } + if revoked { + c.JSON(http.StatusUnauthorized, domain.RespError("令牌已登出")) + c.Abort() + return } } @@ -64,3 +62,15 @@ func JwtAuthMiddleware(secret string, tokenBlacklist auth.JWTBlacklist) gin.Hand c.Next() } } + +// bearerToken 从 Authorization 头中取出 Bearer 令牌。 +func bearerToken(header string) (string, bool) { + scheme, token, found := strings.Cut(header, " ") + if !found || token == "" || strings.Contains(token, " ") { + return "", false + } + if !strings.EqualFold(scheme, "Bearer") { + return "", false + } + return token, true +} diff --git a/domain/jwt_custom.go b/domain/jwt_custom.go index 6f23202..ca1ac75 100644 --- a/domain/jwt_custom.go +++ b/domain/jwt_custom.go @@ -13,7 +13,14 @@ type JwtCustomClaims struct { jwt.RegisteredClaims } +// JTI 返回登出黑名单使用的 jti。必须提供:外层 ID 字段遮蔽了内嵌的 RegisteredClaims.ID, +// 直接写 claims.ID 会拿到用户 ID。 +func (c *JwtCustomClaims) JTI() string { return c.RegisteredClaims.ID } + type JwtCustomRefreshClaims struct { ID string `json:"id"` jwt.RegisteredClaims } + +// JTI 返回登出黑名单使用的 jti,原因同 JwtCustomClaims.JTI。 +func (c *JwtCustomRefreshClaims) JTI() string { return c.RegisteredClaims.ID } diff --git a/internal/tokenservice/token_service.go b/internal/tokenservice/token_service.go index b8ac0b3..fe51030 100644 --- a/internal/tokenservice/token_service.go +++ b/internal/tokenservice/token_service.go @@ -29,34 +29,14 @@ func (ts *TokenService) CreateRefreshToken(user *domain.User, secret string, exp return tokenutil.CreateRefreshToken(user, secret, expiry) } -// ExtractIDFromToken 从令牌中提取用户ID -func (ts *TokenService) ExtractIDFromToken(requestToken string, secret string) (string, error) { - return tokenutil.ExtractIDFromToken(requestToken, secret) +// ParseAccessClaims 校验 access token 签名并解析全部 claims。 +func (ts *TokenService) ParseAccessClaims(requestToken string, secret string) (*domain.JwtCustomClaims, error) { + return tokenutil.ParseAccessClaims(requestToken, secret) } -// IsAuthorized 验证令牌是否有效 -func (ts *TokenService) IsAuthorized(requestToken string, secret string) (bool, error) { - return tokenutil.IsAuthorized(requestToken, secret) -} - -// ExtractEmailFromToken 从令牌中提取用户邮箱 -func (ts *TokenService) ExtractEmailFromToken(requestToken string, secret string) (string, error) { - return tokenutil.ExtractEmailFromToken(requestToken, secret) -} - -// ExtractIsAdminFromToken 从令牌中提取用户管理员状态 -func (ts *TokenService) ExtractIsAdminFromToken(requestToken string, secret string) (bool, error) { - return tokenutil.ExtractIsAdminFromToken(requestToken, secret) -} - -// ExtractAllClaimsFromToken 从令牌中提取所有自定义claims -func (ts *TokenService) ExtractAllClaimsFromToken(requestToken string, secret string) (*domain.JwtCustomClaims, error) { - return tokenutil.ExtractAllClaimsFromToken(requestToken, secret) -} - -// ExtractJTI 从令牌中提取 jti(用于服务端登出黑名单) -func (ts *TokenService) ExtractJTI(requestToken string, secret string) (string, error) { - return tokenutil.ExtractJTI(requestToken, secret) +// ParseRefreshClaims 校验 refresh token 签名并解析全部 claims。 +func (ts *TokenService) ParseRefreshClaims(requestToken string, secret string) (*domain.JwtCustomRefreshClaims, error) { + return tokenutil.ParseRefreshClaims(requestToken, secret) } // ExtractJTIAndExpiry 提取 jti 与过期时间(用于服务端登出黑名单) diff --git a/internal/tokenutil/tokenutil.go b/internal/tokenutil/tokenutil.go index 761d692..a50afbd 100644 --- a/internal/tokenutil/tokenutil.go +++ b/internal/tokenutil/tokenutil.go @@ -2,6 +2,7 @@ package tokenutil import ( "encoding/json" + "errors" "fmt" "time" @@ -11,6 +12,16 @@ import ( "github.com/rs/xid" ) +// hmacKeyFunc 只接受 HS256。 +func hmacKeyFunc(secret string) jwt.Keyfunc { + return func(token *jwt.Token) (any, error) { + if token.Method.Alg() != jwt.SigningMethodHS256.Alg() { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + return []byte(secret), nil + } +} + func CreateAccessToken(user *domain.User, secret string, expiry int) (accessToken string, err error) { return CreateAccessTokenWithIdentity(user, secret, expiry, "shadmin", user.ID) } @@ -31,7 +42,7 @@ func CreateAccessTokenWithIdentity(user *domain.User, secret string, expiry int, RegisteredClaims: jwt.RegisteredClaims{ Issuer: "shadmin", ExpiresAt: exp, - ID: xid.New().String(), // JTI,用于服务端登出黑名单 + ID: xid.New().String(), // jti:登出黑名单的键 Subject: subject, }, } @@ -49,7 +60,7 @@ func CreateRefreshToken(user *domain.User, secret string, expiry int) (refreshTo ID: user.ID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: exp, - ID: xid.New().String(), // JTI + ID: xid.New().String(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claimsRefresh) @@ -60,67 +71,35 @@ func CreateRefreshToken(user *domain.User, secret string, expiry int) (refreshTo return rt, err } -func IsAuthorized(requestToken string, secret string) (bool, error) { - _, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) - if err != nil { - return false, err - } - return true, nil -} - -func parseTokenClaims(requestToken string, secret string) (jwt.MapClaims, error) { - token, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) +// ParseAccessClaims 校验签名与 exp,并解析 access token 的全部 claims。 +func ParseAccessClaims(requestToken string, secret string) (*domain.JwtCustomClaims, error) { + claims := new(domain.JwtCustomClaims) + token, err := jwt.ParseWithClaims(requestToken, claims, hmacKeyFunc(secret)) if err != nil { return nil, err } - - claims, ok := token.Claims.(jwt.MapClaims) - if !ok || !token.Valid { - return nil, fmt.Errorf("invalid token") + if !token.Valid { + return nil, errors.New("invalid token") } - return claims, nil } -// ExtractJTI 从 token 的 jti 声明中提取唯一标识,用于服务端登出黑名单。 -// 老 token 无 jti 时返回空串(中间件视为不在黑名单,向后兼容)。 -func ExtractJTI(requestToken string, secret string) (string, error) { - token, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) +// ParseRefreshClaims 校验签名与 exp,并解析 refresh token 的全部 claims。 +func ParseRefreshClaims(requestToken string, secret string) (*domain.JwtCustomRefreshClaims, error) { + claims := new(domain.JwtCustomRefreshClaims) + token, err := jwt.ParseWithClaims(requestToken, claims, hmacKeyFunc(secret)) if err != nil { - return "", err + return nil, err } - claims, ok := token.Claims.(jwt.MapClaims) - if !ok || !token.Valid { - return "", fmt.Errorf("invalid token") + if !token.Valid { + return nil, errors.New("invalid token") } - jti, _ := claims["jti"].(string) - return jti, nil + return claims, nil } -// ExtractJTIAndExpiry 一次解析取出 jti 与过期时间,专供登出黑名单使用。 -// jti 为空串表示老令牌无 jti;ok=false 表示令牌不可解析或无 exp。 +// ExtractJTIAndExpiry 解析出 jti 与过期时间,供登出黑名单使用;ok=false 表示令牌不可用或无 exp。 func ExtractJTIAndExpiry(requestToken string, secret string) (jti string, expiresAt time.Time, ok bool) { - token, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) + token, err := jwt.Parse(requestToken, hmacKeyFunc(secret)) if err != nil || !token.Valid { return "", time.Time{}, false } @@ -146,129 +125,3 @@ func ExtractJTIAndExpiry(requestToken string, secret string) (jti string, expire } return jti, expiresAt, true } - -func ExtractIDFromToken(requestToken string, secret string) (string, error) { - token, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) - - if err != nil { - return "", err - } - - claims, ok := token.Claims.(jwt.MapClaims) - - if !ok && !token.Valid { - return "", fmt.Errorf("invalid token") - } - - return claims["id"].(string), nil -} - -// ExtractEmailFromToken 从token中提取用户邮箱 -func ExtractEmailFromToken(requestToken string, secret string) (string, error) { - token, err := jwt.Parse(requestToken, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - return []byte(secret), nil - }) - - if err != nil { - return "", err - } - - claims, ok := token.Claims.(jwt.MapClaims) - if !ok && !token.Valid { - return "", fmt.Errorf("invalid token") - } - - email, exists := claims["email"] - if !exists { - return "", nil // 邮箱不存在时返回空字符串 - } - - emailStr, ok := email.(string) - if !ok { - return "", fmt.Errorf("email claim is not a string") - } - - return emailStr, nil -} - -// ExtractIsAdminFromToken 从token中提取用户是否为管理员 -func ExtractIsAdminFromToken(requestToken string, secret string) (bool, error) { - claims, err := parseTokenClaims(requestToken, secret) - if err != nil { - return false, err - } - - isAdmin, exists := claims["is_admin"] - if !exists { - return false, nil // is_admin不存在时返回false - } - - isAdminBool, ok := isAdmin.(bool) - if !ok { - return false, fmt.Errorf("is_admin claim is not a boolean") - } - - return isAdminBool, nil -} - -// ExtractAllClaimsFromToken 从token中提取所有自定义claims -func ExtractAllClaimsFromToken(requestToken string, secret string) (*domain.JwtCustomClaims, error) { - claims, err := parseTokenClaims(requestToken, secret) - if err != nil { - return nil, err - } - - // 安全地提取各个字段 - customClaims := &domain.JwtCustomClaims{} - - if id, exists := claims["id"]; exists { - if idStr, ok := id.(string); ok { - customClaims.ID = idStr - } - } - - if name, exists := claims["name"]; exists { - if nameStr, ok := name.(string); ok { - customClaims.Name = nameStr - } - } - - if email, exists := claims["email"]; exists { - if emailStr, ok := email.(string); ok { - customClaims.Email = emailStr - } - } - - if isAdmin, exists := claims["is_admin"]; exists { - if isAdminBool, ok := isAdmin.(bool); ok { - customClaims.IsAdmin = isAdminBool - } - } - - if roles, exists := claims["roles"]; exists { - if rolesSlice, ok := roles.([]interface{}); ok { - customClaims.Roles = make([]string, len(rolesSlice)) - for i, role := range rolesSlice { - if roleStr, ok := role.(string); ok { - customClaims.Roles[i] = roleStr - } - } - } - } - - if subject, exists := claims["sub"]; exists { - if subjectStr, ok := subject.(string); ok { - customClaims.Subject = subjectStr - } - } - - return customClaims, nil -} From ab877a082a0aae2e0f24566d0cda12b18e29c31a Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 21:25:31 +0800 Subject: [PATCH 14/18] fxi: lib update --- frontend/package.json | 100 +- frontend/pnpm-lock.yaml | 3284 +++++++++++++++++++++------------------ 2 files changed, 1814 insertions(+), 1570 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 5119336..3555efc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,72 +19,72 @@ "knip": "knip" }, "dependencies": { - "@hookform/resolvers": "^5.4.0", - "@radix-ui/react-alert-dialog": "^1.1.19", - "@radix-ui/react-avatar": "^1.2.2", - "@radix-ui/react-checkbox": "^1.3.7", - "@radix-ui/react-collapsible": "^1.1.16", - "@radix-ui/react-dialog": "^1.1.19", - "@radix-ui/react-direction": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.20", + "@hookform/resolvers": "^5.9.1", + "@radix-ui/react-alert-dialog": "^1.1.23", + "@radix-ui/react-avatar": "^1.2.6", + "@radix-ui/react-checkbox": "^1.3.11", + "@radix-ui/react-collapsible": "^1.1.20", + "@radix-ui/react-dialog": "^1.1.23", + "@radix-ui/react-direction": "^1.1.4", + "@radix-ui/react-dropdown-menu": "^2.1.24", "@radix-ui/react-icons": "^1.3.2", - "@radix-ui/react-label": "^2.1.11", - "@radix-ui/react-popover": "^1.1.19", - "@radix-ui/react-radio-group": "^1.4.3", - "@radix-ui/react-scroll-area": "^1.2.14", - "@radix-ui/react-select": "^2.3.3", - "@radix-ui/react-separator": "^1.1.11", - "@radix-ui/react-slot": "^1.3.0", - "@radix-ui/react-switch": "^1.3.3", - "@radix-ui/react-tabs": "^1.1.17", - "@radix-ui/react-tooltip": "^1.2.12", - "@tailwindcss/vite": "^4.3.2", - "@tanstack/react-query": "^5.101.2", - "@tanstack/react-router": "^1.170.17", + "@radix-ui/react-label": "^2.1.15", + "@radix-ui/react-popover": "^1.1.23", + "@radix-ui/react-radio-group": "^1.4.7", + "@radix-ui/react-scroll-area": "^1.2.18", + "@radix-ui/react-select": "^2.3.7", + "@radix-ui/react-separator": "^1.1.15", + "@radix-ui/react-slot": "^1.3.3", + "@radix-ui/react-switch": "^1.3.7", + "@radix-ui/react-tabs": "^1.1.21", + "@radix-ui/react-tooltip": "^1.2.16", + "@tailwindcss/vite": "^4.3.3", + "@tanstack/react-query": "^5.102.8", + "@tanstack/react-router": "^1.170.34", "@tanstack/react-table": "^8.21.3", - "axios": "^1.18.1", + "axios": "^1.20.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "1.1.1", "date-fns": "^4.4.0", - "dompurify": "^3.4.11", + "dompurify": "^3.4.15", "go-captcha-react": "^1.0.5", - "input-otp": "^1.4.2", - "lucide-react": "^1.24.0", - "react": "^19.2.7", + "input-otp": "^1.5.0", + "lucide-react": "^1.44.0", + "react": "^19.3.0", "react-day-picker": "10.0.1", - "react-dom": "^19.2.7", - "react-hook-form": "^7.81.0", + "react-dom": "^19.3.0", + "react-hook-form": "^7.87.0", "react-top-loading-bar": "^3.0.2", - "recharts": "^3.9.2", - "sonner": "^2.0.7", + "recharts": "^3.10.1", + "sonner": "^2.0.8", "tailwind-merge": "^3.6.0", - "tailwindcss": "^4.3.2", + "tailwindcss": "^4.3.3", "tw-animate-css": "^1.4.0", - "zod": "^4.4.3", - "zustand": "^5.0.14" + "zod": "^4.6.1", + "zustand": "^5.0.15" }, "devDependencies": { "@eslint/js": "^10.0.1", - "@faker-js/faker": "^10.5.0", - "@tanstack/eslint-plugin-query": "^5.101.2", - "@tanstack/react-query-devtools": "^5.101.2", - "@tanstack/react-router-devtools": "^1.167.0", - "@tanstack/router-plugin": "^1.168.19", + "@faker-js/faker": "^10.6.0", + "@tanstack/eslint-plugin-query": "^5.102.8", + "@tanstack/react-query-devtools": "^5.102.8", + "@tanstack/react-router-devtools": "^1.167.1", + "@tanstack/router-plugin": "^1.168.37", "@trivago/prettier-plugin-sort-imports": "^6.0.2", - "@types/node": "^25.9.5", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react-swc": "^4.3.1", - "eslint": "^10.7.0", + "@types/node": "^25.9.6", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react-swc": "^4.3.3", + "eslint": "^10.10.0", "eslint-plugin-react-hooks": "^7.1.1", - "eslint-plugin-react-refresh": "^0.5.3", - "globals": "^17.7.0", - "knip": "^6.26.0", - "prettier": "^3.9.5", - "prettier-plugin-tailwindcss": "^0.8.0", + "eslint-plugin-react-refresh": "^0.5.6", + "globals": "^17.12.0", + "knip": "^6.35.1", + "prettier": "^3.9.6", + "prettier-plugin-tailwindcss": "^0.8.1", "typescript": "~6.0.3", - "typescript-eslint": "^8.63.0", - "vite": "^8.1.4" + "typescript-eslint": "^8.70.0", + "vite": "^8.3.0" } } diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 41f87f6..3127394 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -9,77 +9,77 @@ importers: .: dependencies: '@hookform/resolvers': - specifier: ^5.4.0 - version: 5.4.0(react-hook-form@7.81.0(react@19.2.7)) + specifier: ^5.9.1 + version: 5.9.1(@standard-schema/spec@1.1.0)(react-hook-form@7.87.0(react@19.3.0))(zod@4.6.1) '@radix-ui/react-alert-dialog': - specifier: ^1.1.19 - version: 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.23 + version: 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-avatar': - specifier: ^1.2.2 - version: 1.2.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.2.6 + version: 1.2.6(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-checkbox': - specifier: ^1.3.7 - version: 1.3.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.3.11 + version: 1.3.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-collapsible': - specifier: ^1.1.16 - version: 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.20 + version: 1.1.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-dialog': - specifier: ^1.1.19 - version: 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.23 + version: 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-direction': - specifier: ^1.1.2 - version: 1.1.2(@types/react@19.2.17)(react@19.2.7) + specifier: ^1.1.4 + version: 1.1.4(@types/react@19.3.0)(react@19.3.0) '@radix-ui/react-dropdown-menu': - specifier: ^2.1.20 - version: 2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^2.1.24 + version: 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-icons': specifier: ^1.3.2 - version: 1.3.2(react@19.2.7) + version: 1.3.2(react@19.3.0) '@radix-ui/react-label': - specifier: ^2.1.11 - version: 2.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^2.1.15 + version: 2.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-popover': - specifier: ^1.1.19 - version: 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.23 + version: 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-radio-group': - specifier: ^1.4.3 - version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.4.7 + version: 1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-scroll-area': - specifier: ^1.2.14 - version: 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.2.18 + version: 1.2.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-select': - specifier: ^2.3.3 - version: 2.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^2.3.7 + version: 2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-separator': - specifier: ^1.1.11 - version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-slot': - specifier: ^1.3.0 - version: 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-switch': specifier: ^1.3.3 - version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-switch': + specifier: ^1.3.7 + version: 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-tabs': - specifier: ^1.1.17 - version: 1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.1.21 + version: 1.1.21(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@radix-ui/react-tooltip': - specifier: ^1.2.12 - version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.2.16 + version: 1.2.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@tailwindcss/vite': - specifier: ^4.3.2 - version: 4.3.2(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) + specifier: ^4.3.3 + version: 4.3.3(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0)) '@tanstack/react-query': - specifier: ^5.101.2 - version: 5.101.2(react@19.2.7) + specifier: ^5.102.8 + version: 5.102.8(react@19.3.0) '@tanstack/react-router': - specifier: ^1.170.17 - version: 1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.170.34 + version: 1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@tanstack/react-table': specifier: ^8.21.3 - version: 8.21.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 8.21.3(react-dom@19.3.0(react@19.3.0))(react@19.3.0) axios: - specifier: ^1.18.1 - version: 1.18.1 + specifier: ^1.20.0 + version: 1.20.0 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -88,122 +88,122 @@ importers: version: 2.1.1 cmdk: specifier: 1.1.1 - version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.1.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) date-fns: specifier: ^4.4.0 version: 4.4.0 dompurify: - specifier: ^3.4.11 - version: 3.4.11 + specifier: ^3.4.15 + version: 3.4.15 go-captcha-react: specifier: ^1.0.5 - version: 1.0.5(react@19.2.7) + version: 1.0.5(react@19.3.0) input-otp: - specifier: ^1.4.2 - version: 1.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.5.0 + version: 1.5.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) lucide-react: - specifier: ^1.24.0 - version: 1.24.0(react@19.2.7) + specifier: ^1.44.0 + version: 1.44.0(react@19.3.0) react: - specifier: ^19.2.7 - version: 19.2.7 + specifier: ^19.3.0 + version: 19.3.0 react-day-picker: specifier: 10.0.1 - version: 10.0.1(@types/react@19.2.17)(react@19.2.7) + version: 10.0.1(@types/react@19.3.0)(react@19.3.0) react-dom: - specifier: ^19.2.7 - version: 19.2.7(react@19.2.7) + specifier: ^19.3.0 + version: 19.3.0(react@19.3.0) react-hook-form: - specifier: ^7.81.0 - version: 7.81.0(react@19.2.7) + specifier: ^7.87.0 + version: 7.87.0(react@19.3.0) react-top-loading-bar: specifier: ^3.0.2 - version: 3.0.2(react@19.2.7) + version: 3.0.2(react@19.3.0) recharts: - specifier: ^3.9.2 - version: 3.9.2(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@19.2.7)(react@19.2.7)(redux@5.0.1) + specifier: ^3.10.1 + version: 3.10.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react-is@19.2.7)(react@19.3.0)(redux@5.0.1) sonner: - specifier: ^2.0.7 - version: 2.0.7(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^2.0.8 + version: 2.0.8(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) tailwind-merge: specifier: ^3.6.0 version: 3.6.0 tailwindcss: - specifier: ^4.3.2 - version: 4.3.2 + specifier: ^4.3.3 + version: 4.3.3 tw-animate-css: specifier: ^1.4.0 version: 1.4.0 zod: - specifier: ^4.4.3 - version: 4.4.3 + specifier: ^4.6.1 + version: 4.6.1 zustand: - specifier: ^5.0.14 - version: 5.0.14(@types/react@19.2.17)(immer@11.1.11)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)) + specifier: ^5.0.15 + version: 5.0.15(@types/react@19.3.0)(immer@11.1.18)(react@19.3.0)(use-sync-external-store@1.7.0(react@19.3.0)) devDependencies: '@eslint/js': specifier: ^10.0.1 - version: 10.0.1(eslint@10.7.0(jiti@2.7.0)) + version: 10.0.1(eslint@10.10.0(jiti@2.7.0)) '@faker-js/faker': - specifier: ^10.5.0 - version: 10.5.0 + specifier: ^10.6.0 + version: 10.6.0 '@tanstack/eslint-plugin-query': - specifier: ^5.101.2 - version: 5.101.2(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) + specifier: ^5.102.8 + version: 5.102.8(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) '@tanstack/react-query-devtools': - specifier: ^5.101.2 - version: 5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7) + specifier: ^5.102.8 + version: 5.102.8(@tanstack/react-query@5.102.8(react@19.3.0))(react@19.3.0) '@tanstack/react-router-devtools': - specifier: ^1.167.0 - version: 1.167.0(@tanstack/react-router@1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.14)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.167.1 + version: 1.167.1(@tanstack/react-router@1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(@tanstack/router-core@1.171.29)(csstype@3.2.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) '@tanstack/router-plugin': - specifier: ^1.168.19 - version: 1.168.19(@tanstack/react-router@1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(rolldown@1.1.5)(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) + specifier: ^1.168.37 + version: 1.168.37(@tanstack/react-router@1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(rolldown@1.2.8)(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0)) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.2 - version: 6.0.2(prettier@3.9.5) + version: 6.0.2(prettier@3.9.6) '@types/node': - specifier: ^25.9.5 - version: 25.9.5 + specifier: ^25.9.6 + version: 25.9.6 '@types/react': - specifier: ^19.2.17 - version: 19.2.17 + specifier: ^19.3.0 + version: 19.3.0 '@types/react-dom': - specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.17) + specifier: ^19.3.0 + version: 19.3.0(@types/react@19.3.0) '@vitejs/plugin-react-swc': - specifier: ^4.3.1 - version: 4.3.1(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) + specifier: ^4.3.3 + version: 4.3.3(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0)) eslint: - specifier: ^10.7.0 - version: 10.7.0(jiti@2.7.0) + specifier: ^10.10.0 + version: 10.10.0(jiti@2.7.0) eslint-plugin-react-hooks: specifier: ^7.1.1 - version: 7.1.1(eslint@10.7.0(jiti@2.7.0)) + version: 7.1.1(eslint@10.10.0(jiti@2.7.0)) eslint-plugin-react-refresh: - specifier: ^0.5.3 - version: 0.5.3(eslint@10.7.0(jiti@2.7.0)) + specifier: ^0.5.6 + version: 0.5.6(eslint@10.10.0(jiti@2.7.0)) globals: - specifier: ^17.7.0 - version: 17.7.0 + specifier: ^17.12.0 + version: 17.12.0 knip: - specifier: ^6.26.0 - version: 6.26.0 + specifier: ^6.35.1 + version: 6.35.1 prettier: - specifier: ^3.9.5 - version: 3.9.5 + specifier: ^3.9.6 + version: 3.9.6 prettier-plugin-tailwindcss: - specifier: ^0.8.0 - version: 0.8.0(@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.5))(prettier@3.9.5) + specifier: ^0.8.1 + version: 0.8.1(@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6))(prettier@3.9.6) typescript: specifier: ~6.0.3 version: 6.0.3 typescript-eslint: - specifier: ^8.63.0 - version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) + specifier: ^8.70.0 + version: 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) vite: - specifier: ^8.1.4 - version: 8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0) + specifier: ^8.3.0 + version: 8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0) packages: @@ -219,8 +219,8 @@ packages: resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.29.7': @@ -257,8 +257,8 @@ packages: resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} engines: {node: '>=6.0.0'} hasBin: true @@ -266,34 +266,34 @@ packages: resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} - '@date-fns/tz@1.5.0': - resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==} + '@cacheable/memory@2.2.0': + resolution: {integrity: sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==} - '@emnapi/core@1.11.0': - resolution: {integrity: sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==} + '@cacheable/utils@2.5.0': + resolution: {integrity: sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@date-fns/tz@1.5.0': + resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==} - '@emnapi/runtime@1.11.0': - resolution: {integrity: sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -306,8 +306,8 @@ packages: resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.6.0': - resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.2.1': @@ -327,33 +327,106 @@ packages: resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.2': - resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + '@eslint/plugin-kit@0.7.3': + resolution: {integrity: sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@faker-js/faker@10.5.0': - resolution: {integrity: sha512-bsxD8WLS5lIj7aaoCx1YJkktqYj5vlBUE6HWzu2Q51ksrGJ0H737ECCKlFU7Yf8Br45z9t99frBp/J7kzbMPAg==} + '@faker-js/faker@10.6.0': + resolution: {integrity: sha512-3RQHgEtvL1Frl/d1cSreo7qhJ3Gk1OdNUai/CtZ8G+wYeRQnJih3s9xJ9/kgYekPQRdwgh0HXRPqMlzWGwivIQ==} engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} - '@floating-ui/core@1.7.5': - resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} - '@floating-ui/dom@1.7.6': - resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} - '@floating-ui/react-dom@2.1.8': - resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} + '@floating-ui/react-dom@2.1.9': + resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/utils@0.2.11': - resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} - '@hookform/resolvers@5.4.0': - resolution: {integrity: sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw==} + '@hookform/resolvers@5.9.1': + resolution: {integrity: sha512-7b7vsbraJxKgjVSA1Nur9tLwj539WGJUBLA7QNvXnFoT2pM5Z7G+6rlukk4B2/QrTZy6huRtH6wKeESPKuIr6w==} peerDependencies: + '@sinclair/typebox': '>=0.25.24' + '@standard-schema/spec': ^1.0.0 + '@typeschema/main': '>=0.13.7' + '@vinejs/vine': ^2.0.0 || ^3.0.0 || ^4.0.0 + ajv: ^8.12.0 + ajv-errors: ^3.0.0 + ajv-formats: ^2.1.1 + arktype: ^2.0.0 + ata-validator: ^1.2.0 + class-transformer: '>=0.4.0' + class-validator: '>=0.12.0' + computed-types: ^1.0.0 + effect: ^3.10.3 + fluentvalidation-ts: ^3.0.0 + fp-ts: ^2.7.0 + io-ts: ^2.0.0 + joi: ^17.0.0 || ^18.0.0 + nope-validator: '>=0.12.0' react-hook-form: ^7.55.0 + superstruct: '>=0.12.0' + typanion: ^3.3.2 + valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc' + vest: '>=6.0.0' + yup: ^1.0.0 + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@sinclair/typebox': + optional: true + '@standard-schema/spec': + optional: true + '@typeschema/main': + optional: true + '@vinejs/vine': + optional: true + ajv: + optional: true + ajv-errors: + optional: true + ajv-formats: + optional: true + arktype: + optional: true + ata-validator: + optional: true + class-transformer: + optional: true + class-validator: + optional: true + computed-types: + optional: true + effect: + optional: true + fluentvalidation-ts: + optional: true + fp-ts: + optional: true + io-ts: + optional: true + joi: + optional: true + nope-validator: + optional: true + superstruct: + optional: true + typanion: + optional: true + valibot: + optional: true + vest: + optional: true + yup: + optional: true + zod: + optional: true '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} @@ -385,262 +458,267 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} + engines: {node: '>= 18'} + peerDependencies: + keyv: ^5.6.0 + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} + + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 - '@oxc-parser/binding-android-arm-eabi@0.137.0': - resolution: {integrity: sha512-KDs+0VPdEmasOkpuJHW9V5WCF+cvYdMQv2Jd+aJXt+cxIx12NToRQRbXaRwUEDsZw+/jMk81Ve8ZFbjUkJTOwA==} + '@oxc-parser/binding-android-arm-eabi@0.148.0': + resolution: {integrity: sha512-pHASv9g5pASxb7akHERZNSkrEqPhFaUix98o7d9hbTpolnnFWl7UiRrcMhCsV1+iVO4/cJwKsbKRJTFNs2tdBQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.137.0': - resolution: {integrity: sha512-WhALNzfy3x/RfC6bsqX+csavuUY0yHHE7XfgPE5M542uhoBZUUoGTPG+nkMbGoG4+gcfss5s7urMyn5QBHu0sw==} + '@oxc-parser/binding-android-arm64@0.148.0': + resolution: {integrity: sha512-sg/6Ez0KdAygsu0POELux9wN1Po2CP93WY8eNl4DBKIGprsd4QSHBXOb471Pu9i2OCD5sLkISSb2agZEhVn2Zw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.137.0': - resolution: {integrity: sha512-bFPr5hgmNMOMoyPTGtdsK4Ug21RovIPojRMgDDhSp1LtCnc/DkLwGONKjgRjszg677RlGnkYSviQ8hHaUPOVYA==} + '@oxc-parser/binding-darwin-arm64@0.148.0': + resolution: {integrity: sha512-yiSJmzGUvCUaJT8X3j40gVcX+ckuHQMuiOtF8DvzTs5+JtB/7XuHFPp4M+vv5u+HlBtDUd4Ks5pyHpWz8mfnkg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.137.0': - resolution: {integrity: sha512-CL5dMm1asqXIDZHg14FLxj3Mc36w8PI7xCWh1uA4is6z8g2XrIILoTcQYOxDbwzuk34RDPX5IAGUxZr6LA9KAg==} + '@oxc-parser/binding-darwin-x64@0.148.0': + resolution: {integrity: sha512-6ZeklaamrMy4H2JmhvcJg6iip59tYILtuLaILxyAHT3l5FDxnI5ihVievAft5ZmAbqtlWHErOi1OpJK8gy1wcA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.137.0': - resolution: {integrity: sha512-79h8rYGnSlKPGWo7mHr2ixO6ea7aW8B0CT965SZ8SLbNnCOH5aOYBTeVXUY6eMvEaiLyWr8Skuiugr5pDYgLGw==} + '@oxc-parser/binding-freebsd-x64@0.148.0': + resolution: {integrity: sha512-vFsPx+a/qFECPnz/H8nC6x6MDvnWscLTCo/5muojEF54ERUq1kdgbvnWo95YnkhjF9sTIcG/uDxQBh1gffaufQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.137.0': - resolution: {integrity: sha512-ASgmlSimhGyr0lksgVIo6hibz1obnDq4qJbiMX/AzltfgPnanRrzG1Q+23g8ljOHOjv6dsznkUuCYL3gg0sY1Q==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.148.0': + resolution: {integrity: sha512-eOr3M+6iGbbxNL4PSS0VtsyQ2eOUxSBh00BqO22SbolDimPSYsBuLr/LCrZBkiqW2BoabhR6V4R8jrRAay7hjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.137.0': - resolution: {integrity: sha512-AU2J9aa22Sx32wRGnDjybOU9TQXXQUud5sdUi+ZB0XxwM8aToWLweV+yA0wlQm0yIUVqljquqoHCYEq9II8gJQ==} + '@oxc-parser/binding-linux-arm-musleabihf@0.148.0': + resolution: {integrity: sha512-58ZKDw0mQRbCNfrd2IDyV4o8T7enzGERJn41BH2tjrZVGyiKiFzcfDicuB7Zcpb/1xIOrObovr8Dja6lZi8dLw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.137.0': - resolution: {integrity: sha512-GdEtiG89yMr7XkUGxifgodXEEm2f+xW2f9CpDjlgAnBOwhTmrpQMvhOGobLVKUyzf/qHBXW16smk5zbF3nZU6w==} + '@oxc-parser/binding-linux-arm64-gnu@0.148.0': + resolution: {integrity: sha512-Fnu95O4eZ5i++GPvIzBEZ8y4ddTLR+D9paYa8JRaRk6ZK7nHQiWP5xtrhcPQsXqgat1d7sU/d5rbbI0p1FTHSQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-musl@0.137.0': - resolution: {integrity: sha512-EGJ+Bs8iXx8KBH8DQ5BLoEm5lnHaYjlh4/8j8vFhrr/6z4tqONy5BZDzLpKmmNWlN6Hlc5r8YOuBVHqZ9vRFEQ==} + '@oxc-parser/binding-linux-arm64-musl@0.148.0': + resolution: {integrity: sha512-3CQy/BMdx7N7H3qrcPxUL+a2CwUZodUcf6oq8iJuNZ9C6Ol1aq3mcWzsgySJ7CHFLvpX21ZDPp1r1X0QLbu/AQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-ppc64-gnu@0.137.0': - resolution: {integrity: sha512-vzFUQENy/fnbSe5DZWovq6tIBc1uhuMztanSW6rz1e9WdQE4gHwYuD7ZII6JnrJifd1R3RSoqiZbgRFlVL2tYQ==} + '@oxc-parser/binding-linux-ppc64-gnu@0.148.0': + resolution: {integrity: sha512-9LkaYvfiF8hMOw900csAvkf1oxE8XlmMeGowu5BcastSSwV8mKvKRMNU7HsV+ycyj1dQD8pX5qgOw8ja6SJacg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.137.0': - resolution: {integrity: sha512-SfVI14HBQs9gtLcUD5hTt5hsNbdrqSUNg9S8muN+LhVQ5nf1WwH3hAoK6B9NKgdYgWAQSXFXGiiBedQ4r/BKuw==} + '@oxc-parser/binding-linux-riscv64-gnu@0.148.0': + resolution: {integrity: sha512-2GBiM9h26dR4WJfhoMvnFMnFLf7m/kYs4UMqjvrOfQG4BV1nuTJDH22Zc2MQr3INZF7nSKYQ6xlhD3hQ7A6gug==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-musl@0.137.0': - resolution: {integrity: sha512-e7Ppy4FCIFNQxT/ikSeIWFoQ0l+N9vgtRBtLcyZXeolTzApyVoPqEXsYPrcdM/9i0Bwk8knvYd37vaEMxHyi6g==} + '@oxc-parser/binding-linux-riscv64-musl@0.148.0': + resolution: {integrity: sha512-uPqZexvKJmEgq4mAu36qe2xTfXZE7oyik1R7KtZ5tl8qKlq1U1fIqTFRUEBZqRGvforoTrGIpatRzcoPKO66RA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-s390x-gnu@0.137.0': - resolution: {integrity: sha512-Bho5qFwdhqsIFR7gipYEUlqvi3SRrY8sugxXig380MIaakBB1PyU9+7dBiBVScfImTNWhijUxdBwqrprGdq5WA==} + '@oxc-parser/binding-linux-s390x-gnu@0.148.0': + resolution: {integrity: sha512-9oUHvnTbp7ZraFsTC8PN6XhdhPSSxZumYvixWl7Smi353gEULvK6yV0sXNVrdFMHQeaDKFCi8TgDhNK7/A+Y+Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.137.0': - resolution: {integrity: sha512-36mGWtg7PyFzjJwGDkH6/F4o2nIDEoKXLPr/X/lwqklkomQwJJt1I5GJVmGhovUEmgPK5WAeAZMqlFCehwiy9Q==} + '@oxc-parser/binding-linux-x64-gnu@0.148.0': + resolution: {integrity: sha512-2qhDSJwKzbSZzF7lDqqk8sr/yXsmwr3PeUa4/nazIF+zFAYz1gVPEfC34GQtGxzJUUmklaYAL63368LEfrMeyw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-musl@0.137.0': - resolution: {integrity: sha512-/Jqx6+N7A44n2BdvUr7pXhVr2vFjs6WGH3unZRczwrfiH0H1zY0QwKQMG/dtRiTlKGDKGukznPT8lx84/oEsZg==} + '@oxc-parser/binding-linux-x64-musl@0.148.0': + resolution: {integrity: sha512-qQoPDZUFV0bh9xA09XydmkjMBpgc1ukJuhMvzQ9QeVmFaHTS9W5TE5CoLmSl3QQyUP9OuHO3x/WPZTIIZPWR3Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxc-parser/binding-openharmony-arm64@0.137.0': - resolution: {integrity: sha512-9Uj0qHNNl+OgT1UTGwF7ixIXU6T1u2SbMidmgPy/h1h/fl2gRS6YpAxxY1gwHofcWjoTwkoMFd8xs5Vuj6GOFA==} + '@oxc-parser/binding-openharmony-arm64@0.148.0': + resolution: {integrity: sha512-1UGbaQWEXUCLqAmaR5kwRDjx/R4S5LQKZkM9CHmaHkuKhriOF32aRLfS0jCRNE2yGQJLMEA1z9UucbBVqjXnDw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-wasm32-wasi@0.137.0': - resolution: {integrity: sha512-gW2vfkytNGgMVADiuzdvOfw0mWG9za20F/1fCJsif5aBMAvWJTSbpIXbIe0XkOe0VENk+PadpQ7cZgUy2sUJcA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@oxc-parser/binding-win32-arm64-msvc@0.137.0': - resolution: {integrity: sha512-x+pFANF0yL5uK/6T7lu6SlR5qid6sp//eZXKLq5iNsIE+EQg6EaS8/wsW7E91nXXjpnPhSoMOHXShSVhGRdn8w==} + '@oxc-parser/binding-win32-arm64-msvc@0.148.0': + resolution: {integrity: sha512-pWKdzRDNG2+NK4h/V6U/CYERcfYD6u28h5IB/VJVsrZaD3muvE58tUj22lieL5vLZ+XFi1GPv9YXckZbJZ9BLA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.137.0': - resolution: {integrity: sha512-sQUqym80PFi6McRsIqfJrSu2JrSClEZIXXD+/FjAFoULEKzOPsldIdFBG96xdX8aVMzCNQ9792FPx3MfkEIrFA==} + '@oxc-parser/binding-win32-ia32-msvc@0.148.0': + resolution: {integrity: sha512-i3p4x+mvwtjcE1J5HM6V7ggsbXiznExN/4MkNyOy3dfXrVV3bnkSfmZxvo6/84qCVX4ShkpNE1SKt9biIF31GQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.137.0': - resolution: {integrity: sha512-2AsevxlvNN4WKxpEn3RtqD5zbqMaXF+T7JXblsP4gVuY+vC9dXS4ED/PwfRCliFqoeisYS3Iro4DHzxr0TEvVA==} + '@oxc-parser/binding-win32-x64-msvc@0.148.0': + resolution: {integrity: sha512-Ye6vB7VQulghWYkYkECOBYFRVEizz4XyRTUAv+t8BuyurhKU7uD0P9eowL+mKG5Mf8MSYx+DI3Cm8SKZvYG7bQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxc-project/types@0.137.0': - resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} + '@oxc-project/types@0.148.0': + resolution: {integrity: sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==} - '@oxc-project/types@0.139.0': - resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.149.0': + resolution: {integrity: sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==} - '@oxc-resolver/binding-android-arm-eabi@11.21.3': - resolution: {integrity: sha512-eNU11A2WNizh04v3uyaJCootrHIaS0B9aHYXvAvVnPNk4xYSjMUjHnhQ6dewPN2MRYDskV85d1N0Aw0WNWhcyg==} + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.21.3': - resolution: {integrity: sha512-8Q+ZjTLvn2dIcWsrmhdrEihm7q+ag/k+mkry7Z+t0QbbHaVxXQfvH9AewyVMh/WrpEKhQ3DDgx9fYbqeCpeOEw==} + '@oxc-resolver/binding-android-arm64@11.24.2': + resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.21.3': - resolution: {integrity: sha512-wkh0qKZGHXVUDxFw3oA1TXnU2BDYY/r775oJflGeIr8uDPPoN2pk8gijQIzYRT6hoql/lg3+Tx/SaTn9e2/aGg==} + '@oxc-resolver/binding-darwin-arm64@11.24.2': + resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.21.3': - resolution: {integrity: sha512-HbNc23FAQYbuyDV2vBWMez4u4mrsm5RAkniGZAWqr6lYZ3N4beeqIb776jzwRl8qL2zRhHVXpUj97X0QgogVzg==} + '@oxc-resolver/binding-darwin-x64@11.24.2': + resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.21.3': - resolution: {integrity: sha512-K6xNsTUPEUdfrn0+kbMq5nOUB5w1C5pavPQngt4TM2FpN91lP0PBe2srSpamb4d69O7h86oAi/qWX/kZNRSjkw==} + '@oxc-resolver/binding-freebsd-x64@11.24.2': + resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': - resolution: {integrity: sha512-VcFmOpcpWX1zoEy8M58tR2M9YxM+Z9RuQhqAx5q0CTmrruaP7Gveejg75hzd/5sg5nk9G3aLALEa3hE2FsmmTQ==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': - resolution: {integrity: sha512-quVoxFLBy43hWaQbbDtQNRwAX5vX76mv7n64icAtQcJ3eNgVeblqmkupF/hAneNthdqSlnd1sTjb3aQSaDPaCQ==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': - resolution: {integrity: sha512-X0AqNZgcD07Q4V3RDK18/vYOj/HQT/FnmEFGYS2jTWqY7JO13ryE3TEs3eAIgUJhBnNkpEaiXqz3VK8M7qQhWQ==} + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-musl@11.21.3': - resolution: {integrity: sha512-YkaQnaKYdbuaXvRt5Qd0GpbihzVnyfR6z1SpYfIUC6RTu4NF7lDKPjVkYb+jRI2gedVO2rVpN35Y6akG6ud4Lw==} + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': - resolution: {integrity: sha512-gB9HwhrPiFqUzDeEq+y/CgAijz1YdI6BnXz5GaH2Pa9cWdutchlkGFAiAuGb/PjVQpiK6NFKzFuztxrweoit7A==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': - resolution: {integrity: sha512-zjDWBlYk8QGv0H8dsPUWqkfjYIIjG2TvspGkzXL0eImbgxtZorA/klKeHyolevoT3Kvbi+1iMr9Lhrh7jf54Og==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': - resolution: {integrity: sha512-4UfsQvacV388y1zpXL7C1x1FNYaV52JtuNRiuzrfQA2z1z6ElVrsidkGsrvQ5EgeSq1Pj7kaKqrgGkvFuxJ/tw==} + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': - resolution: {integrity: sha512-b5uH+HKH0MP5mNBYaK75SKsJbw52URqrx2LavYdq6wb0l3ExAG5niYRP9DWUNHdKilpaBVM2bXk9HNWrH3ew7Q==} + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.21.3': - resolution: {integrity: sha512-PjYlmilBpNRh2ntXNYAK3Am5w/nPfEpnU/96iNx7CI8EzAn12J4JRiec63wHJTH31nLoCNxBg/829pN+3CfG3Q==} + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-musl@11.21.3': - resolution: {integrity: sha512-QTBAb7JuHlZ7JUEyM8UiQi2f7m/L4swBhP2TNpYIDc9Wp/wRw1G/8sl6i13aIzQAXH7LKIm294LeOHd0lQR8zA==} + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.21.3': - resolution: {integrity: sha512-4j1DFwjwv36ec9kds0jU/ucQ5Ha4ERO/H95BxR5JFf0kqUUAJ1kwII7XhTc1vZrkdJkvLGC9Q2MbpObpum8RBg==} + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.21.3': - resolution: {integrity: sha512-i8oluoel5kru/j1WNrjmQSiA3GQ7wvIYVR1IwIoZtKogAhya2iub+ZKIeSIkcJOrnzQ18Tzl/F+kL3fYOxZLvA==} + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': - resolution: {integrity: sha512-M/8dw8dD6aOs+NlPJax401CZB9I7Aut84isQLgALGGwke4Afvw+/7yYhZb94yXf6t2sPLhQLmSmtSV+2FhsOWg==} + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.21.3': - resolution: {integrity: sha512-H7BCt/VnS9hnmMp42eGhZ99izSCRvlnWwy/N71K1/J8QoExwY4262Z8QiEkMDtduRJrztayDxETTckmUuAVL9Q==} + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} cpu: [x64] os: [win32] - '@radix-ui/number@1.1.2': - resolution: {integrity: sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==} + '@radix-ui/number@1.1.3': + resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==} - '@radix-ui/primitive@1.1.5': - resolution: {integrity: sha512-d86WIWFYNtGA0H/d8exstrTRTp7eWJYlYJbtNofxr/3ljupZYn6EFDG/Qgu/0Kc8v7yMUxySagqJsL1+PdYjWg==} + '@radix-ui/primitive@1.1.7': + resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==} - '@radix-ui/react-alert-dialog@1.1.19': - resolution: {integrity: sha512-FA7n1f6D/DwGE0+AWxiY5LacNbbExQuEgMubeG06idEaH+mSLuf9dp/qBNqOnvbTQ+4gZ2ue1RATF1Ub91Mg5g==} + '@radix-ui/react-alert-dialog@1.1.23': + resolution: {integrity: sha512-VAYOiQRqj3GPpYJE0I9J+X8Ip05cyVlNdKOFeiGS2Ou1HHGfpl0BxOyZm6nmVDyU+W+NF3/XLzmjHmVGydhwgA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -652,8 +730,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-arrow@1.1.11': - resolution: {integrity: sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==} + '@radix-ui/react-arrow@1.1.15': + resolution: {integrity: sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -665,8 +743,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-avatar@1.2.2': - resolution: {integrity: sha512-sST0qh8GzOB7besQ3tMLWLyngnRuSk0gc/Hm+667KYKQFCt6Y6ZXv25WlqM7dIDK54ULCh5+CHmk4LIolzfz+A==} + '@radix-ui/react-avatar@1.2.6': + resolution: {integrity: sha512-4ULOTJ/mqy2hT9GlWa/MFHxHSvH3nJzHnZM1waNsc5Bonv7i70aNenghXmD97S6OJ81ekXONGGt4nT1r0PfEdA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -678,8 +756,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-checkbox@1.3.7': - resolution: {integrity: sha512-JroKHfQBfh+fDuzpPsBC+pESkhuq8ql4hljTguz8MWnS35cISr3d/Jhl9kYrB44FlDtxCArYdDvTx+BSsJ64rQ==} + '@radix-ui/react-checkbox@1.3.11': + resolution: {integrity: sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -691,8 +769,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collapsible@1.1.16': - resolution: {integrity: sha512-opfXRe6nnzyGmCDPx+l1Aqo/RbqWtQal2FnsBqF9hhePp6j0LsRoBaRxcMOlTv+uYTJVtWYZKg9t9wTe+BA/ZA==} + '@radix-ui/react-collapsible@1.1.20': + resolution: {integrity: sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -704,8 +782,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.12': - resolution: {integrity: sha512-nb67INpE0IahJKN7EYPp9m9YGwYeKlnzxT3MwXVkgCskaSJia97kG4T0ywpjNUSSnoJk/uvk12V8vbrEHEj+/Q==} + '@radix-ui/react-collection@1.1.15': + resolution: {integrity: sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -717,8 +795,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-compose-refs@1.1.3': - resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==} + '@radix-ui/react-compose-refs@1.1.5': + resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -726,8 +804,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context@1.2.0': - resolution: {integrity: sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg==} + '@radix-ui/react-context@1.2.2': + resolution: {integrity: sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -735,8 +813,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.1.19': - resolution: {integrity: sha512-+HhbN2+YtkRgVirjZ2afMeutQRuGOrdkWR5+EFC58SJojGmtyNQwYzgi6tHBpOxvFHefMtPeHdgtjz0BOGxFQg==} + '@radix-ui/react-dialog@1.1.23': + resolution: {integrity: sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -748,8 +826,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-direction@1.1.2': - resolution: {integrity: sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==} + '@radix-ui/react-direction@1.1.4': + resolution: {integrity: sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -757,8 +835,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dismissable-layer@1.1.15': - resolution: {integrity: sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==} + '@radix-ui/react-dismissable-layer@1.1.19': + resolution: {integrity: sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -770,8 +848,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.20': - resolution: {integrity: sha512-slfm+rRaZRuQBvHq60lXvSVUPhid0IPtjSZzIuUlWZMUs01iYZNlGS3mJgRD3ChLQVBAYlKiL/tFyWGX+dz8Xw==} + '@radix-ui/react-dropdown-menu@2.1.24': + resolution: {integrity: sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -783,8 +861,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-guards@1.1.4': - resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==} + '@radix-ui/react-focus-guards@1.1.6': + resolution: {integrity: sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -792,8 +870,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-scope@1.1.12': - resolution: {integrity: sha512-jjk/lqTeNL0azUx5ZYzVrl4NgaDIrdzTNE4mABV9yBFI7FQqN7pIgzV1bTleUezP2QiTGA1BFTqY8MegDgWX9A==} + '@radix-ui/react-focus-scope@1.1.16': + resolution: {integrity: sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -810,8 +888,8 @@ packages: peerDependencies: react: ^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc - '@radix-ui/react-id@1.1.2': - resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==} + '@radix-ui/react-id@1.1.4': + resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -819,8 +897,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-label@2.1.11': - resolution: {integrity: sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==} + '@radix-ui/react-label@2.1.15': + resolution: {integrity: sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -832,8 +910,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menu@2.1.20': - resolution: {integrity: sha512-VsUrXxFe9d2ScbZF0fR/oPR1+qjyeLs5p0jzG8h90puMoA9bq4SirYlXbE+USRg9Q2qTeJSFNqjw2nts8jJe4w==} + '@radix-ui/react-menu@2.1.24': + resolution: {integrity: sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -845,8 +923,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.19': - resolution: {integrity: sha512-jkrTdQVxnIB8fpn0NyyxW9CTB5aCXZZelVz5z+Xmii6g5WxMqS3fInNslZ63puP39+Puu4jYohUK31y3dT87gQ==} + '@radix-ui/react-popover@1.1.23': + resolution: {integrity: sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -858,8 +936,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popper@1.3.3': - resolution: {integrity: sha512-mS7dGpyjv6b+gsDjLF7e0ia1W4Im1B1hSCy2yuXlHuvnZxHKagfDaobt/KAKt27EpZMit2pss8eJBVyVjEWM+g==} + '@radix-ui/react-popper@1.3.7': + resolution: {integrity: sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -871,8 +949,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-portal@1.1.13': - resolution: {integrity: sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==} + '@radix-ui/react-portal@1.1.17': + resolution: {integrity: sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -884,8 +962,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.1.7': - resolution: {integrity: sha512-zBZ4QM5XG3JRanDmqXYf3MD6th4AFXFmgU6KNMFzUaV6F3uw9I5/zjMUvFriSEn5ewo1nxuibvyxJdmLlDcslA==} + '@radix-ui/react-presence@1.1.10': + resolution: {integrity: sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -897,8 +975,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@2.1.7': - resolution: {integrity: sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==} + '@radix-ui/react-primitive@2.1.10': + resolution: {integrity: sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -910,8 +988,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-radio-group@1.4.3': - resolution: {integrity: sha512-WwZFjWV4s3aC1QtR3k04R+oANHtX2q6fgKlc7MCEiDNlnTxCZ3H8k3mHtEgVlOejystwk1WQgarQhNOQZ2bK1g==} + '@radix-ui/react-radio-group@1.4.7': + resolution: {integrity: sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -923,8 +1001,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.15': - resolution: {integrity: sha512-40svmmugfM3mUN7VUDGVE1tQGOhyi8enlGD0CNJEcMM36C1f71PKM21DFgNHUfem0XnA+d8H8oN3Z9ZpJjSslg==} + '@radix-ui/react-roving-focus@1.1.19': + resolution: {integrity: sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -936,8 +1014,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-scroll-area@1.2.14': - resolution: {integrity: sha512-bBODCWZK7JTbQLHs0uIP4f73wIWatakK4OS33UzkR1x897wu0PuO658a3f+6P2GEGyDzGYMuHRatMVoAk9WZTw==} + '@radix-ui/react-scroll-area@1.2.18': + resolution: {integrity: sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -949,8 +1027,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-select@2.3.3': - resolution: {integrity: sha512-L5RQTXz6Anxsf9CCv+pTgiAsUpyVj7rJxsGtmhFaEOJ++cVfXucv4qWfsIO0AIB4NAhi3yovWGVMKKS1Xf1Wrg==} + '@radix-ui/react-select@2.3.7': + resolution: {integrity: sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -962,8 +1040,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-separator@1.1.11': - resolution: {integrity: sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==} + '@radix-ui/react-separator@1.1.15': + resolution: {integrity: sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -975,8 +1053,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-slot@1.3.0': - resolution: {integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==} + '@radix-ui/react-slot@1.3.3': + resolution: {integrity: sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -984,8 +1062,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-switch@1.3.3': - resolution: {integrity: sha512-1+mlB4/lxJfk5tgJ4g+R5mUCbRpPE1T9+UsEyeLYbGgMtwiMgmuTnfKz4Mw1nHALHjuwyxw4MLd4cSHn6pNSlQ==} + '@radix-ui/react-switch@1.3.7': + resolution: {integrity: sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -997,8 +1075,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tabs@1.1.17': - resolution: {integrity: sha512-nRyXnrAVCwjeXcHbvEbLS6ndbTeKHG1RqCP4A8Gw5L4cemDzPXdD8rAmr6wet0v57R69wGvuIIsFjHSVkZiMzQ==} + '@radix-ui/react-tabs@1.1.21': + resolution: {integrity: sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1010,8 +1088,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tooltip@1.2.12': - resolution: {integrity: sha512-U3HoftgWnmla78vzQbLvKKb7bUYJxoiiqYFzp1wu/TBMyDqMZSuCl3aRICsD6EfVEwcJD2mumGDGUXLFVqQHKA==} + '@radix-ui/react-tooltip@1.2.16': + resolution: {integrity: sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1023,8 +1101,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-use-callback-ref@1.1.2': - resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==} + '@radix-ui/react-use-callback-ref@1.1.4': + resolution: {integrity: sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1032,8 +1110,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.2.3': - resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==} + '@radix-ui/react-use-controllable-state@1.2.6': + resolution: {integrity: sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1041,8 +1119,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-effect-event@0.0.3': - resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==} + '@radix-ui/react-use-effect-event@0.0.5': + resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1050,8 +1128,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-is-hydrated@0.1.1': - resolution: {integrity: sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==} + '@radix-ui/react-use-is-hydrated@0.1.3': + resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1059,8 +1137,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-layout-effect@1.1.2': - resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==} + '@radix-ui/react-use-layout-effect@1.1.4': + resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1068,8 +1146,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-previous@1.1.2': - resolution: {integrity: sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==} + '@radix-ui/react-use-previous@1.1.4': + resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1077,8 +1155,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-rect@1.1.2': - resolution: {integrity: sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==} + '@radix-ui/react-use-rect@1.1.4': + resolution: {integrity: sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1086,8 +1164,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-size@1.1.2': - resolution: {integrity: sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==} + '@radix-ui/react-use-size@1.1.4': + resolution: {integrity: sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1095,8 +1173,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-visually-hidden@1.2.7': - resolution: {integrity: sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==} + '@radix-ui/react-visually-hidden@1.2.11': + resolution: {integrity: sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1108,8 +1186,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/rect@1.1.2': - resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} + '@radix-ui/rect@1.1.3': + resolution: {integrity: sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==} '@reduxjs/toolkit@2.12.0': resolution: {integrity: sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==} @@ -1122,97 +1200,98 @@ packages: react-redux: optional: true - '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + '@rolldown/binding-android-arm-eabi@1.2.8': + resolution: {integrity: sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.8': + resolution: {integrity: sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.5': - resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + '@rolldown/binding-darwin-arm64@1.2.8': + resolution: {integrity: sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.5': - resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + '@rolldown/binding-darwin-x64@1.2.8': + resolution: {integrity: sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.5': - resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + '@rolldown/binding-freebsd-x64@1.2.8': + resolution: {integrity: sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': - resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.8': + resolution: {integrity: sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.5': - resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + '@rolldown/binding-linux-arm64-gnu@1.2.8': + resolution: {integrity: sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.5': - resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + '@rolldown/binding-linux-arm64-musl@1.2.8': + resolution: {integrity: sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.5': - resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + '@rolldown/binding-linux-ppc64-gnu@1.2.8': + resolution: {integrity: sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.5': - resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + '@rolldown/binding-linux-s390x-gnu@1.2.8': + resolution: {integrity: sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.1.5': - resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + '@rolldown/binding-linux-x64-gnu@1.2.8': + resolution: {integrity: sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.5': - resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + '@rolldown/binding-linux-x64-musl@1.2.8': + resolution: {integrity: sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.5': - resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + '@rolldown/binding-openharmony-arm64@1.2.8': + resolution: {integrity: sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.5': - resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.1.5': - resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + '@rolldown/binding-win32-arm64-msvc@1.2.8': + resolution: {integrity: sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.5': - resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + '@rolldown/binding-win32-x64-msvc@1.2.8': + resolution: {integrity: sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1226,86 +1305,86 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@swc/core-darwin-arm64@1.15.43': - resolution: {integrity: sha512-v1aVuvXdo/BHxJzco9V2xpHrvwWmhfS8t6gziY5wJxd+Z2h8AeJRnAwPD8itCDaGXVBwJ/CaKfxEzTkG0Va0OA==} + '@swc/core-darwin-arm64@1.16.2': + resolution: {integrity: sha512-i/j0HNbnn79qnTVPicvay92Nark8fW8NQqn1e2mGERjUXNpBV0+SwQxlRpk2zBhn6laJ8PDI6Kn1nHZhnz3LCA==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.15.43': - resolution: {integrity: sha512-lp3d4Lamc8dt5huYdGLSR+9hLxmfr1jb0l+4XXG2zPqZwYWRN9R0U2qYoTrggiU2RWW0oV9VbWM3kBnqIc2kdQ==} + '@swc/core-darwin-x64@1.16.2': + resolution: {integrity: sha512-HrwqHyEyHVXO3qTk8EkNK7/b6sOZSEoNh+pot6RdE5x0LbNqfo8LtJUvi3UTXr+5ja/o5HbJdW80eCXo+NjbiA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.15.43': - resolution: {integrity: sha512-JWTQQELtsG5GgphDrr/XqqmM2pDN3cZqbMS0Mrg+iTiXL3F74sn/S2IyYE/5u4h2KLkTf9qQ7dXyxsbx7YzkeA==} + '@swc/core-linux-arm-gnueabihf@1.16.2': + resolution: {integrity: sha512-MdXi83Z/gGp1LIrg+h7HKxiul/z/Bty/ZJSvYAFqDl9zteC1XLSAZdScquKtXPp50rdyXqritTDCqQBhwVfZKA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.15.43': - resolution: {integrity: sha512-B4otJRdPWIsmiSBf0uG7Z/+vMWmkufjz5MmYxubwKuZazDW14Zd3symga1N62QR4RT+kEFeHEgsXfZGyn/w0hw==} + '@swc/core-linux-arm64-gnu@1.16.2': + resolution: {integrity: sha512-/jcTmK6Ktz3owM3YtiKvjofV6p3VpHnYzTIrOGwDIOsDigRAAVuZ8east33wYO/7UTdKYFlyHNnJNT0WJqOA3Q==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [glibc] - '@swc/core-linux-arm64-musl@1.15.43': - resolution: {integrity: sha512-6zB6OnpViBxYy4tgY3v2i6AZY9fwkcHZ032UOwtwUuW1d19sdT07qF0kZe6/3UR1tUaK6jjg2rmVcUIBCEYVjQ==} + '@swc/core-linux-arm64-musl@1.16.2': + resolution: {integrity: sha512-4gFarKaFnlJTSlJYKmMhV4u+3YE4uYfiydpBoYjmgQhCf9lAieOq+WilZaK9vVSHeqLuQpTEiGULZqAdsRX5Dw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [musl] - '@swc/core-linux-ppc64-gnu@1.15.43': - resolution: {integrity: sha512-coxE1ZWdB3uSDVNoEtYNrRi/1epvckZx9cTJ8ICUxTMTxGk+yvQ/Twacp3ruZSaMPGCriUjP86C37VhaT6nyRg==} + '@swc/core-linux-ppc64-gnu@1.16.2': + resolution: {integrity: sha512-syqSLGd6KlZ1PciNzs6bIUlhOuFztZufebOHaERjc4N4SqNZxyqYd4I+jj/EfOYnpe0kNjccn9HJLN1p5dz3+w==} engines: {node: '>=10'} cpu: [ppc64] os: [linux] libc: [glibc] - '@swc/core-linux-s390x-gnu@1.15.43': - resolution: {integrity: sha512-lXfLhs+LpBsD5inuYx+YDH5WsPPBQ95KPUiy8P5wq9ob9xKDZFqwNfU2QW6bGO8NqRO/H9JQomTSt5Yyh+FGfA==} + '@swc/core-linux-s390x-gnu@1.16.2': + resolution: {integrity: sha512-ZBBLK+ewGyXLzWeMS7wbKtWBdnif6etn7xvPY/iOfbdsjX/+bgkp1pQt2lWF2wlu2hXYZuhJ/tHZE/QR8/apzg==} engines: {node: '>=10'} cpu: [s390x] os: [linux] libc: [glibc] - '@swc/core-linux-x64-gnu@1.15.43': - resolution: {integrity: sha512-07XnKwTmKy8TGOZG3D9fRnLWGynxPjwQnZLVmBFbo6F+7vHYzBIOuwXEhemrChBWb6yDNZsVCcMWCPX6FDD2xg==} + '@swc/core-linux-x64-gnu@1.16.2': + resolution: {integrity: sha512-LyHJgxCA4Tje0ysBMbEb0tt/ie8kgUKoFE3JAKFhpevmTmhYEoC0H9s47WuDsqiFckF1ITUguZIXJG6K5e0dvg==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [glibc] - '@swc/core-linux-x64-musl@1.15.43': - resolution: {integrity: sha512-TJc+bsSIaBh+hZvZ5GRtW/K1bw66TJ9vsUwvVIsZdiWxU5ObLwZvfcnZ3UpgVfMnFibRes9uriJrQNBHEEogRQ==} + '@swc/core-linux-x64-musl@1.16.2': + resolution: {integrity: sha512-PghXJlVM1cgtLfNUR1vxFo1z+PDRAe8cWAJlZZ7spmeiN7BospGXg/MHUg7oNSgwSX7Zo//YKv9P5yD9apsFJQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [musl] - '@swc/core-win32-arm64-msvc@1.15.43': - resolution: {integrity: sha512-jfd7s2/bUQYkOHLs+LWQNKZdmDa8+sufKLllhpWAhVQ2GDCwsHe3vR/j+OSiItZNtkzFuaawa3+SAKz9y5gYfw==} + '@swc/core-win32-arm64-msvc@1.16.2': + resolution: {integrity: sha512-StTOSefYBxemvNYYUI3UmO1a8y+hSPjjfHogC2TEHL+Z1PlEBim/XtLas5rS04jAzT9RrNmbtX911SZ42H9jSQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.15.43': - resolution: {integrity: sha512-rLAE8JvucqEW1ZGohxPQrQWPBQeJG4+ypKbWfdlU/qmKScvCkxf9/Jxnzki1dkUQCQ7P5Enp13RlvqOlvx/32g==} + '@swc/core-win32-ia32-msvc@1.16.2': + resolution: {integrity: sha512-fycER209DYIzsibpTMC+chND05OfOjgztWL9U8OE6/uUlsOUZH3eh98isBLEnOymYUhlJLEt5++W1+KL/FOh5Q==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.15.43': - resolution: {integrity: sha512-h8MLDHZcfIukwQWj03rIJZx1I0E81AYj2X7J/nGErG4nz+QAv6G1Z+peotvinL3lqpbo32tLYSMFo32/ySzxKg==} + '@swc/core-win32-x64-msvc@1.16.2': + resolution: {integrity: sha512-cSd1z6ivSrJPVr+moVwOHWjeKy6TpO4/Shwcv5KCrKYXCccxwh4pRy1C3fDioNx2PF1jPZWHKZjtXt+Be9VbaQ==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.15.43': - resolution: {integrity: sha512-1CuKjFkPxIgGdeHVuNbkxmBxkcbdc08u0aiI43pFq6yY1tTVKmXT9hFEooyyKs/sJ3xf1GPHyEwTtk9Xl8dvQw==} + '@swc/core@1.16.2': + resolution: {integrity: sha512-95I4kiSMeveI/Mhi+tE4fiWcWLUMfzfKrk0jtr8LRMqHgOgq+xHS+zExkDqoO4b5OeeuXHMWVdD5MeP3X6sULw==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -1316,72 +1395,72 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/types@0.1.27': - resolution: {integrity: sha512-K6h3iUlqeM946U4sXFYeahefR1YBbXJvko+hv8WS8/0BNJ4OHiHRywMnQUJCqkR7Y9+hqQ1TvEpiKqUhz7NEFg==} + '@swc/types@0.1.28': + resolution: {integrity: sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==} - '@tailwindcss/node@4.3.2': - resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} - '@tailwindcss/oxide-android-arm64@4.3.2': - resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.3.2': - resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.3.2': - resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.3.2': - resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': - resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': - resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': - resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': - resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.3.2': - resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.3.2': - resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -1392,71 +1471,71 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': - resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': - resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.3.2': - resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.3.2': - resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 - '@tanstack/eslint-plugin-query@5.101.2': - resolution: {integrity: sha512-cPE99s3XZwlObfn8lCezT4j4JLj2CVzpIEywx0H4hzfPsX/o9QhdwaOwcDXxrQAqx2ds7TbvTinxhB8B/ywb6w==} + '@tanstack/eslint-plugin-query@5.102.8': + resolution: {integrity: sha512-zRjG2PL3zvoqnsSNJFyfX5Mo+OwRwTbLERwZVO3oNQQn82V949INwaLrprzsOW/ivuow7gASeAUUC24xH7kwSQ==} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ^5.4.0 || ^6.0.0 + typescript: ^5.6.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: typescript: optional: true - '@tanstack/history@1.162.0': - resolution: {integrity: sha512-79pf/RkhteYZTRgcR4F9kbk84P2N8rugQJswxfIqovlbRiT3yI7eBE+5QorIrZaOKktsgzRlXh1l/du/xpl4iA==} + '@tanstack/history@1.162.3': + resolution: {integrity: sha512-zZTDxZxdDxZudHXGp42d221R/sEKoQPbZsW2ezpdWknHpOmJVLyiljW21pdWtKXfMnLq+Kg5VJpVBwOe18+ZzQ==} engines: {node: '>=20.19'} - '@tanstack/query-core@5.101.2': - resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} + '@tanstack/query-core@5.102.8': + resolution: {integrity: sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==} - '@tanstack/query-devtools@5.101.2': - resolution: {integrity: sha512-o+wHcqgN7Pp0s8v1i0UGq/ZrrEKrxdIiMQmKRdYb2w7NPtylYSJ4+wg/tIn71m9DLstwUwdEGAvROdly6HXP6w==} + '@tanstack/query-devtools@5.102.8': + resolution: {integrity: sha512-ZgeMKuF5d/zOE+tgWm3cSbD6Zcbr6IugVsnbHzUcSismqLZDSUPBKM6ILUxExgwe6rPAOox2x5bA5T+PSOQG0Q==} - '@tanstack/react-query-devtools@5.101.2': - resolution: {integrity: sha512-eU7HctdA9gDjqoERoEdzLbw9DiqnBDfh5+Hu0u26gjqoHJezOpQAuiesDL2VvkU+2cPV76zgv0tMZsOrI4LjnQ==} + '@tanstack/react-query-devtools@5.102.8': + resolution: {integrity: sha512-QKb7A44BZOU7nxsGA4gFN1fofjYovar5O0T83Ff4Y+2eRq09RGFrAzzutVdF/6/emfSaMDohp6e759BjB3fxEw==} peerDependencies: - '@tanstack/react-query': ^5.101.2 + '@tanstack/react-query': ^5.102.8 react: ^18 || ^19 - '@tanstack/react-query@5.101.2': - resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} + '@tanstack/react-query@5.102.8': + resolution: {integrity: sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==} peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.167.0': - resolution: {integrity: sha512-nGw095EG7IHx0h5NtlEmzf6vcCTaFNPWdTSuDKazajhN0ct/v/TkekJ9J6KYUCeV1a8/2ZmToc58M+0rrOyn7w==} + '@tanstack/react-router-devtools@1.167.1': + resolution: {integrity: sha512-pjfGrmjj4d7naEPM7oshqFfwBoxDPNo/UxltlHH5ePbHsJ+plBhd+JaAewm1ueYOjZ0js9hckjWWDYXpCrSfKw==} engines: {node: '>=20.19'} peerDependencies: - '@tanstack/react-router': ^1.170.0 - '@tanstack/router-core': ^1.170.0 + '@tanstack/react-router': ^1.170.19 + '@tanstack/router-core': ^1.171.16 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' peerDependenciesMeta: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.170.17': - resolution: {integrity: sha512-ppLkjCfSMaeug9rmFRYzOd4TIqWV+yTE7tzIny7alJsSnM7w4lzEZm6eqCehG0SPetpZ0R3K+UnanSmBgOAVcQ==} + '@tanstack/react-router@1.170.34': + resolution: {integrity: sha512-zYy1SNjIIAEMfU9mqmB5171PeELs/k3SR+U6QxDKSqyMLw4Aq6R+eC57Sa8iB6X91q1ouES30khauyYww4JMcQ==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -1475,30 +1554,30 @@ packages: react: '>=16.8' react-dom: '>=16.8' - '@tanstack/router-core@1.171.14': - resolution: {integrity: sha512-Mo3hwx0qB0cJsVYGDjG0+Ouf7VV74h/vsoDMGztdlyzDanp4gBA2s7IVvm6hFrmQM6GpD9F0Z7SqD7OldfLE7g==} + '@tanstack/router-core@1.171.29': + resolution: {integrity: sha512-tBXJrU4rDl+UsfTvP/WM1pcQ+fXk4rb2uuK/FMw29JNHEkFdEbptA0yvk8vkNjooTF7DAiTUrZMf2H4X7eGt4g==} engines: {node: '>=20.19'} - '@tanstack/router-devtools-core@1.168.0': - resolution: {integrity: sha512-wQoQhlBK7nlZgqzaqdYXKWNTpdHdsaREdaPhFZVH0/Ador+F+eM3/NF2i3f2LPeS0GgKraZUQXe1Q/1+KHyEYg==} + '@tanstack/router-devtools-core@1.168.1': + resolution: {integrity: sha512-qr4voa4cpSMwQvS3867xkU3AB3MtJbTuovKIy+btjJ/Faju6er9w0nDylmD+005Mk/3YKw9/iueZJl2JAB7JOA==} engines: {node: '>=20.19'} peerDependencies: - '@tanstack/router-core': ^1.170.0 + '@tanstack/router-core': ^1.171.16 csstype: ^3.0.10 peerDependenciesMeta: csstype: optional: true - '@tanstack/router-generator@1.167.18': - resolution: {integrity: sha512-kFvM4caRds9Q3EXg64bZubJ6rbDxyV0YDSBSGvOGzmKspQPdz5Xrh0uj5T1Ov8avUUg+c761u04VQAaEzSBXRw==} + '@tanstack/router-generator@1.167.35': + resolution: {integrity: sha512-1Bfvhon3+4khnB1E1+p9ub5diTzSZ782FiHipGX5wyAPOKdR5dQ1L2XGuZ2BCJQCynhQNYSW2CVJ5DvRHVixlw==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.168.19': - resolution: {integrity: sha512-aFglwLc+bbPTgZlkXn3PvOwpjJAfgUyPGSuql4MP3XrqTTh6WkBiy2RYb6oaG5h0s7EKwivEuq85K3Y4V0Mt1g==} + '@tanstack/router-plugin@1.168.37': + resolution: {integrity: sha512-LO+HAUnFGuC/s2zz6I7ZlSiFroq5obhNNJrkvn7+ALakXfMdo8sOvSqhdHgFh+3Em5rTpd+HVBgbSqLWsgXnTw==} engines: {node: '>=20.19'} peerDependencies: '@rsbuild/core': '>=1.0.2 || ^2.0.0' - '@tanstack/react-router': ^1.170.17 + '@tanstack/react-router': ^1.170.34 vite: '>=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0' vite-plugin-solid: ^2.11.10 || ^3.0.0-0 webpack: '>=5.92.0' @@ -1514,8 +1593,8 @@ packages: webpack: optional: true - '@tanstack/router-utils@1.162.2': - resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==} + '@tanstack/router-utils@1.162.3': + resolution: {integrity: sha512-Icb0xGuG1+54IV0WMLRcc3ErTx2HeJWyPG661FkQ8UT6guoBq1FJjFRqlG/JS0xi4mFFkBhvwO7tbLa32f3yxA==} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': @@ -1569,8 +1648,8 @@ packages: '@types/d3-scale@4.0.9': resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} - '@types/d3-shape@3.1.8': - resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + '@types/d3-shape@3.2.0': + resolution: {integrity: sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==} '@types/d3-time@3.0.4': resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} @@ -1587,16 +1666,16 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.9.5': - resolution: {integrity: sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==} + '@types/node@25.9.6': + resolution: {integrity: sha512-JR6Q/PV5DKFvjrGFVqQJdeG0qvsqQQLDa3TzFrqVwhqRXqwNaxPo2KYCtCQXpOdIulCouKwT7a6in9nFthBAzw==} - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} peerDependencies: - '@types/react': ^19.2.0 + '@types/react': ^19.3.0 - '@types/react@19.2.17': - resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -1604,67 +1683,67 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@typescript-eslint/eslint-plugin@8.63.0': - resolution: {integrity: sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==} + '@typescript-eslint/eslint-plugin@8.70.0': + resolution: {integrity: sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.63.0 + '@typescript-eslint/parser': ^8.70.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.63.0': - resolution: {integrity: sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==} + '@typescript-eslint/parser@8.70.0': + resolution: {integrity: sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.63.0': - resolution: {integrity: sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==} + '@typescript-eslint/project-service@8.70.0': + resolution: {integrity: sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.63.0': - resolution: {integrity: sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==} + '@typescript-eslint/scope-manager@8.70.0': + resolution: {integrity: sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.63.0': - resolution: {integrity: sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==} + '@typescript-eslint/tsconfig-utils@8.70.0': + resolution: {integrity: sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.63.0': - resolution: {integrity: sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==} + '@typescript-eslint/type-utils@8.70.0': + resolution: {integrity: sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.63.0': - resolution: {integrity: sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==} + '@typescript-eslint/types@8.70.0': + resolution: {integrity: sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.63.0': - resolution: {integrity: sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==} + '@typescript-eslint/typescript-estree@8.70.0': + resolution: {integrity: sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.63.0': - resolution: {integrity: sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==} + '@typescript-eslint/utils@8.70.0': + resolution: {integrity: sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.63.0': - resolution: {integrity: sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==} + '@typescript-eslint/visitor-keys@8.70.0': + resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react-swc@4.3.1': - resolution: {integrity: sha512-PaeokKjAGraNN+s5SIApgsktnJprIyt3zgEIu7awnEdfn29QiB2crTcCzyi2XGpX9rUnTc0cKU07Wm0N0g7H2w==} + '@vitejs/plugin-react-swc@4.3.3': + resolution: {integrity: sha512-bti8ZAcvz4Lh6/e4Uk2k3aa1TiUXbbMsahuqOHvd3MveFTkKDZOA6wQVkpj7J/+tepX/wGfe+lsGh/t24HTXMQ==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4 || ^5 || ^6 || ^7 || ^8 @@ -1674,8 +1753,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true @@ -1697,8 +1776,8 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axios@1.18.1: - resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + axios@1.20.0: + resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==} babel-dead-code-elimination@1.0.12: resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} @@ -1715,18 +1794,21 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - brace-expansion@2.1.2: - resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} browserslist@4.28.4: resolution: {integrity: sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + cacheable@2.5.0: + resolution: {integrity: sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1848,8 +1930,8 @@ packages: resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} - dompurify@3.4.11: - resolution: {integrity: sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==} + dompurify@3.4.15: + resolution: {integrity: sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} @@ -1858,8 +1940,8 @@ packages: electron-to-chromium@1.5.387: resolution: {integrity: sha512-TaxwufTFDufvPEoXdhwVrA3UdFWBeWGkYoJ1K8ldF1xe6gKfth6iRNS5lTQ5JPNOHdGQm8PT1QYKUqFLCiUefQ==} - enhanced-resolve@5.21.6: - resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + enhanced-resolve@5.24.5: + resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} engines: {node: '>=10.13.0'} es-define-property@1.0.1: @@ -1878,8 +1960,8 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-toolkit@1.49.0: - resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es-toolkit@1.52.0: + resolution: {integrity: sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==} escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} @@ -1895,8 +1977,8 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 - eslint-plugin-react-refresh@0.5.3: - resolution: {integrity: sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA==} + eslint-plugin-react-refresh@0.5.6: + resolution: {integrity: sha512-uZnh24On2bk478AkaDAKcpRiYhS3qFSaSNvpXxV6/Ek/BBDICkWGG7MnBSfjnIlCVBei5vsLlIeQYxbF22+Udg==} peerDependencies: eslint: ^9 || ^10 @@ -1912,8 +1994,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.7.0: - resolution: {integrity: sha512-GVTD7s1vdIl6UYvAfriOPeY1Df8LIZjfofLvHwde+erDHGGuHyuM6xoxRxmHiebhYuD2p1vN4wWh0XzPARSGDQ==} + eslint@10.10.0: + resolution: {integrity: sha512-NPXn6r5zl4uET1DAVPaOwzX3rut4c0wcmw3dWJAfOsTM5+TogXo0DDjz8pwm/hL8cyVNpHqeK4JpN0NjnyFFNw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1966,20 +2048,18 @@ packages: picomatch: optional: true - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + file-entry-cache@11.1.5: + resolution: {integrity: sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==} find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} + flat-cache@6.1.23: + resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==} - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} follow-redirects@1.16.0: resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} @@ -1994,8 +2074,8 @@ packages: resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} - formatly@0.3.0: - resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + formatly@0.7.0: + resolution: {integrity: sha512-7CXJtIIA0zy/u12StsYk25qVKxvdLA2ep2sTNxK3ov0mGNIIDqIvAXDSgTnAfDJFsPfWjuz0WjfYSdpvnLA5Tg==} engines: {node: '>=18.3.0'} hasBin: true @@ -2023,15 +2103,15 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-tsconfig@4.14.0: - resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - globals@17.7.0: - resolution: {integrity: sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==} + globals@17.12.0: + resolution: {integrity: sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==} engines: {node: '>=18'} go-captcha-react@1.0.5: @@ -2060,6 +2140,10 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hashery@1.5.1: + resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==} + engines: {node: '>=20'} + hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} @@ -2070,6 +2154,12 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hookified@1.15.1: + resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + + hookified@2.2.0: + resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -2078,19 +2168,19 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.6: - resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + ignore@7.0.9: + resolution: {integrity: sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==} engines: {node: '>= 4'} - immer@11.1.11: - resolution: {integrity: sha512-qzXuyXAkPySAGYkfsAwodDPWT8Zm7/Uo5BNt4BjhMhG5WlWyZZ4wQqnWwdS8kjlQ1Cwu6gjw3A6+0gTQwlyYtw==} + immer@11.1.18: + resolution: {integrity: sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ==} imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - input-otp@1.4.2: - resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} + input-otp@1.5.0: + resolution: {integrity: sha512-3AcfdW1sNG0FmSA5hHMBXG7jNW5CdcdKs8ln8JOmn6S2SRkoXoJx+2UwC+ZvjflfnOdHJx0SfQ9/YjlxVYLtGQ==} peerDependencies: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc @@ -2107,8 +2197,8 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - isbot@5.2.0: - resolution: {integrity: sha512-gbZiGCb4B5xaoxg9mS7koAyRdvJnArk10VLSHOgz6rtBG93/pi1xOFaVvXMKZ7JXgyZ8zAbNRK5uIBdIUTFSqw==} + isbot@5.2.2: + resolution: {integrity: sha512-iQcBXcd+Rv/pkubRyGh2utW2j1oPG5hZY6TUhVPpqK4G+o3IbxpJNx04hgksjc/N7GK5pEorUxDeg31cFgEk/w==} engines: {node: '>=18'} isexe@2.0.0: @@ -2129,9 +2219,6 @@ packages: engines: {node: '>=6'} hasBin: true - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -2143,11 +2230,11 @@ packages: engines: {node: '>=6'} hasBin: true - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} - knip@6.26.0: - resolution: {integrity: sha512-e9eELEEpBpGTd4H4HB7818/DYj9dMzMyUqAddfYwUN/EbSkgIjOuWEF96W/xHsmV0SDrsdXjIM+oZ2xpPzPsBA==} + knip@6.35.1: + resolution: {integrity: sha512-22wnEnv4do2fvoeJsxpFCG/MBxReNxoCVBccaCl7suUJsG+F0UvxI9ycxZ9YgtLHSSjrZl5tOas0JZ/R1vJ93g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2161,30 +2248,60 @@ packages: cpu: [arm64] os: [android] + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.32.0: resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.32.0: resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.32.0: resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.32.0: resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} @@ -2192,6 +2309,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} @@ -2199,6 +2323,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} @@ -2206,6 +2337,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} @@ -2213,22 +2351,45 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.32.0: resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2239,8 +2400,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lucide-react@1.24.0: - resolution: {integrity: sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==} + lucide-react@1.44.0: + resolution: {integrity: sha512-2egNApH4hX4j/qdCgRublh88+9u3mEhz9iSlW5ckm4kaQEqZbXbMr0l5u5JZLy8nmWRx2dbHGQkEDYz6C9aCgw==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2259,8 +2420,8 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} minimatch@9.0.9: @@ -2270,8 +2431,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2286,12 +2447,12 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - oxc-parser@0.137.0: - resolution: {integrity: sha512-yFImD+WLElJpLKy8llG1qe4DCmMsL18peRp8XP1JKfig/gISbJkglnpDtX2aTmAn10kZF7164HbN2H8QPsXxGg==} + oxc-parser@0.148.0: + resolution: {integrity: sha512-syxUKHeUll89RIABQADcI7sikYrwyssvA6gj4phSSIPezKVM8yMaLAiLLSc7fmzVvrwybfFGFbW5zme9sX87rg==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-resolver@11.21.3: - resolution: {integrity: sha512-2Mx3fKQz7+xgrBONjsxOgCGtMHOn38/HxMzW1I5efwXB5a4lRN0Vp40gYUJFBWJslcrvwoofTrqoTnLbwTd3pA==} + oxc-resolver@11.24.2: + resolution: {integrity: sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==} p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} @@ -2301,6 +2462,9 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + package-manager-detector@1.8.0: + resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} + parse-imports-exports@0.2.4: resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} @@ -2321,20 +2485,20 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} - postcss@8.5.16: - resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + postcss@8.5.28: + resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-plugin-tailwindcss@0.8.0: - resolution: {integrity: sha512-V8ITGH87yuBDF6JpEZTOVlUz/saAwqb8f3HRgUj8Lh+tGCcrmorhsLpYqzygwFwK0PE2Ib6Mv3M7T/uE2tZV1g==} + prettier-plugin-tailwindcss@0.8.1: + resolution: {integrity: sha512-iaFMYqDsE4ffdDkn5qup0j5f2aCEBFZrdrZnvu9QKTlWx/iGPeQ4HHu7b7fCPMxeo9nwQBiOAh2nSypdFYWJkw==} engines: {node: '>=20.19'} peerDependencies: '@ianvs/prettier-plugin-sort-imports': '*' @@ -2388,8 +2552,8 @@ packages: prettier-plugin-svelte: optional: true - prettier@3.9.5: - resolution: {integrity: sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==} + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} engines: {node: '>=14'} hasBin: true @@ -2401,6 +2565,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qified@0.10.1: + resolution: {integrity: sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==} + engines: {node: '>=20'} + react-day-picker@10.0.1: resolution: {integrity: sha512-eNh6BlwcYInWaJtRv18mXQ06Ys/H6rdTZAnTaSdOYJuTpwP1JMCHNd1FDRadA+gbeinq+psdULN5Xnowy9mV8w==} engines: {node: '>=18'} @@ -2411,13 +2579,13 @@ packages: '@types/react': optional: true - react-dom@19.2.7: - resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + react-dom@19.3.0: + resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==} peerDependencies: - react: ^19.2.7 + react: ^19.3.0 - react-hook-form@7.81.0: - resolution: {integrity: sha512-ocbmr2p5KBMoAfj4WCUvped33lVi1Kd5DuDUvQDnB6VEAacOjPI/jMbtDdbhco4y9ct4xUuCmMY0b/C9L0QHjw==} + react-hook-form@7.87.0: + resolution: {integrity: sha512-zhFzWvLxNHH+8839OnZcUxgMZw88ah2jZWDWvKWgF3Tpbnd0vKL+dlcuU3nZVWESZQjd81EW8K+wU+cYfYAc0w==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -2473,16 +2641,16 @@ packages: peerDependencies: react: ^16 || ^17 || ^18 || ^19 - react@19.2.7: - resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + react@19.3.0: + resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} engines: {node: '>=0.10.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} - recharts@3.9.2: - resolution: {integrity: sha512-G4fy+Pk46RaXgwWMh+Nzhyo/lbFAVqXo9gtetlyehe6Ehge9CsgDuOTwQDD+i1+llaLktNBiNq4bhnGlDRXFtw==} + recharts@3.10.1: + resolution: {integrity: sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA==} engines: {node: '>=18'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2500,16 +2668,19 @@ packages: reselect@5.2.0: resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} + reselect@5.3.0: + resolution: {integrity: sha512-XGoLeRAVzUTcJ1qkxPQhDJyIZ5d6zzZD9nT7AEZOaaU9UbWclhycElmhO+VD5bFeLuzhPBaOV2oXC8uG35ZSpg==} + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - rolldown@1.1.5: - resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + rolldown@1.2.8: + resolution: {integrity: sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -2520,14 +2691,14 @@ packages: engines: {node: '>=10'} hasBin: true - seroval-plugins@1.5.4: - resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} + seroval-plugins@1.6.7: + resolution: {integrity: sha512-4Nk35ttD3DTDJW4hgw5StsVAPeU6qnDFnULAouw6tQ7oLTV/ICXrWpsXo2EE52eSP2joUMazbVf52mFEcADqRw==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.5.4: - resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} + seroval@1.6.7: + resolution: {integrity: sha512-AeDcLh0yO2SFm9W71essgnSzLV9DI8ZH0x0knXn2DMnUZj728mpLbxjlbB6IqKCmqh8JA3cEqRyGoNkt584JcQ==} engines: {node: '>=10'} shebang-command@2.0.0: @@ -2538,15 +2709,19 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - smol-toml@1.7.0: - resolution: {integrity: sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} engines: {node: '>= 18'} - sonner@2.0.7: - resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} + sonner@2.0.8: + resolution: {integrity: sha512-UM/ByIoFra8yzV75n1o0Puu0bw5U/9UNnDacrJNspekBewIfsQ3D6ez1nvlWpt7aTsO6rujQtifBpycwIivqlg==} peerDependencies: + '@types/react': ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -2559,8 +2734,8 @@ packages: tailwind-merge@3.6.0: resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} - tailwindcss@4.3.2: - resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} @@ -2589,8 +2764,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.63.0: - resolution: {integrity: sha512-xgwXyzG4sK9ALkBxbyGkTMMOS+imnW65iPhxCQMK83KhxyoDNW7l+IDqEf9vMdoUidHpOoS967RCq4eMiTexwQ==} + typescript-eslint@8.70.0: + resolution: {integrity: sha512-P/W5cz70/cQAuKfY3xwQMWWTV7BvJ0mAQmi+9mBcsVPaBUpd6Ohpa+fECv9rBFrQcig86jAiNBFNWUqnTjr4pw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -2601,8 +2776,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - unbash@4.0.2: - resolution: {integrity: sha512-8gwNZ29+0/3zmXw7ToIHZtg6wK37xnniRUdBt7B27xZxaxfgR5tGMaGHT0t0dLtBV9fXE7zurh0s6Z1DHVjfWg==} + unbash@4.0.11: + resolution: {integrity: sha512-FoSOKV7NEofQSkAefMVHam4ZPKYMxjAydxiV72UFEDNV/YofxjGfiZ2A9pZjdL/lRJzTjcu4PABo1JYJX8N5iQ==} engines: {node: '>=14'} undici-types@7.24.6: @@ -2670,21 +2845,21 @@ packages: '@types/react': optional: true - use-sync-external-store@1.6.0: - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + use-sync-external-store@1.7.0: + resolution: {integrity: sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite@8.1.4: - resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + vite@8.3.0: + resolution: {integrity: sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.7.1 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -2755,11 +2930,11 @@ packages: peerDependencies: zod: ^3.25.0 || ^4.0.0 - zod@4.4.3: - resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zod@4.6.1: + resolution: {integrity: sha512-341aRWQsve0rvronKNTqZpjmzdbUDlFuzHaI/XLg/Ej82qffDJRRfBTCuv7+9q/rMjB6LSLyEBnW4InJeMtt/Q==} - zustand@5.0.14: - resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==} + zustand@5.0.15: + resolution: {integrity: sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -2789,14 +2964,14 @@ snapshots: '@babel/core@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -2806,10 +2981,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.7': + '@babel/generator@7.29.8': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -2826,8 +3001,8 @@ snapshots: '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color @@ -2836,7 +3011,7 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.8 transitivePeerDependencies: - supports-color @@ -2849,55 +3024,56 @@ snapshots: '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 - '@babel/parser@7.29.7': + '@babel/parser@7.29.8': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 - '@babel/traverse@7.29.7': + '@babel/traverse@7.29.8': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.29.7': + '@babel/types@7.29.8': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@date-fns/tz@1.5.0': {} - - '@emnapi/core@1.11.0': + '@cacheable/memory@2.2.0': dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true + '@cacheable/utils': 2.5.0 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.1 + keyv: 5.6.0 - '@emnapi/core@1.11.1': + '@cacheable/utils@2.5.0': dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true + hashery: 1.5.1 + keyv: 5.6.0 + + '@date-fns/tz@1.5.0': {} - '@emnapi/runtime@1.11.0': + '@emnapi/core@1.11.2': dependencies: + '@emnapi/wasi-threads': 1.2.2 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': + '@emnapi/runtime@1.11.2': dependencies: tslib: 2.8.1 optional: true @@ -2907,9 +3083,9 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.7.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.10.1(eslint@10.10.0(jiti@2.7.0))': dependencies: - eslint: 10.7.0(jiti@2.7.0) + eslint: 10.10.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2918,11 +3094,11 @@ snapshots: dependencies: '@eslint/object-schema': 3.0.5 debug: 4.4.3 - minimatch: 10.2.5 + minimatch: 10.2.6 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.6.0': + '@eslint/config-helpers@0.7.0': dependencies: '@eslint/core': 1.2.1 @@ -2930,40 +3106,43 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.7.0(jiti@2.7.0))': + '@eslint/js@10.0.1(eslint@10.10.0(jiti@2.7.0))': optionalDependencies: - eslint: 10.7.0(jiti@2.7.0) + eslint: 10.10.0(jiti@2.7.0) '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.7.2': + '@eslint/plugin-kit@0.7.3': dependencies: '@eslint/core': 1.2.1 levn: 0.4.1 - '@faker-js/faker@10.5.0': {} + '@faker-js/faker@10.6.0': {} - '@floating-ui/core@1.7.5': + '@floating-ui/core@1.8.0': dependencies: - '@floating-ui/utils': 0.2.11 + '@floating-ui/utils': 0.2.12 - '@floating-ui/dom@1.7.6': + '@floating-ui/dom@1.8.0': dependencies: - '@floating-ui/core': 1.7.5 - '@floating-ui/utils': 0.2.11 + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 - '@floating-ui/react-dom@2.1.8(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@floating-ui/react-dom@2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@floating-ui/dom': 1.7.6 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@floating-ui/dom': 1.8.0 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) - '@floating-ui/utils@0.2.11': {} + '@floating-ui/utils@0.2.12': {} - '@hookform/resolvers@5.4.0(react-hook-form@7.81.0(react@19.2.7))': + '@hookform/resolvers@5.9.1(@standard-schema/spec@1.1.0)(react-hook-form@7.87.0(react@19.3.0))(zod@4.6.1)': dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.81.0(react@19.2.7) + react-hook-form: 7.87.0(react@19.3.0) + optionalDependencies: + '@standard-schema/spec': 1.1.0 + zod: 4.6.1 '@humanfs/core@0.19.2': dependencies: @@ -2983,7 +3162,7 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': @@ -2993,713 +3172,704 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': + '@keyv/bigmap@1.3.1(keyv@5.6.0)': dependencies: - '@emnapi/core': 1.11.0 - '@emnapi/runtime': 1.11.0 - '@tybys/wasm-util': 0.10.3 - optional: true + hashery: 1.5.1 + hookified: 1.15.1 + keyv: 5.6.0 - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@keyv/serialize@1.1.1': {} + + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 '@tybys/wasm-util': 0.10.3 optional: true - '@oxc-parser/binding-android-arm-eabi@0.137.0': - optional: true - - '@oxc-parser/binding-android-arm64@0.137.0': + '@oxc-parser/binding-android-arm-eabi@0.148.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.137.0': + '@oxc-parser/binding-android-arm64@0.148.0': optional: true - '@oxc-parser/binding-darwin-x64@0.137.0': + '@oxc-parser/binding-darwin-arm64@0.148.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.137.0': + '@oxc-parser/binding-darwin-x64@0.148.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.137.0': + '@oxc-parser/binding-freebsd-x64@0.148.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.137.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.148.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.137.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.148.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.137.0': + '@oxc-parser/binding-linux-arm64-gnu@0.148.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.137.0': + '@oxc-parser/binding-linux-arm64-musl@0.148.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.137.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.148.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.137.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.148.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.137.0': + '@oxc-parser/binding-linux-riscv64-musl@0.148.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.137.0': + '@oxc-parser/binding-linux-s390x-gnu@0.148.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.137.0': + '@oxc-parser/binding-linux-x64-gnu@0.148.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.137.0': + '@oxc-parser/binding-linux-x64-musl@0.148.0': optional: true - '@oxc-parser/binding-wasm32-wasi@0.137.0': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@oxc-parser/binding-openharmony-arm64@0.148.0': optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.137.0': + '@oxc-parser/binding-win32-arm64-msvc@0.148.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.137.0': + '@oxc-parser/binding-win32-ia32-msvc@0.148.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.137.0': + '@oxc-parser/binding-win32-x64-msvc@0.148.0': optional: true - '@oxc-project/types@0.137.0': {} + '@oxc-project/types@0.148.0': {} - '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.149.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.21.3': + '@oxc-resolver/binding-android-arm-eabi@11.24.2': optional: true - '@oxc-resolver/binding-android-arm64@11.21.3': + '@oxc-resolver/binding-android-arm64@11.24.2': optional: true - '@oxc-resolver/binding-darwin-arm64@11.21.3': + '@oxc-resolver/binding-darwin-arm64@11.24.2': optional: true - '@oxc-resolver/binding-darwin-x64@11.21.3': + '@oxc-resolver/binding-darwin-x64@11.24.2': optional: true - '@oxc-resolver/binding-freebsd-x64@11.21.3': + '@oxc-resolver/binding-freebsd-x64@11.24.2': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.21.3': + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.21.3': + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.21.3': + '@oxc-resolver/binding-linux-x64-musl@11.24.2': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.21.3': + '@oxc-resolver/binding-openharmony-arm64@11.24.2': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.21.3': + '@oxc-resolver/binding-wasm32-wasi@11.24.2': dependencies: - '@emnapi/core': 1.11.0 - '@emnapi/runtime': 1.11.0 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.21.3': + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': optional: true - '@radix-ui/number@1.1.2': {} + '@radix-ui/number@1.1.3': {} - '@radix-ui/primitive@1.1.5': {} + '@radix-ui/primitive@1.1.7': {} - '@radix-ui/react-alert-dialog@1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-alert-dialog@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dialog': 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-arrow@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-arrow@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-avatar@1.2.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.1(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-avatar@1.2.6(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-checkbox@1.3.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-checkbox@1.3.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-collapsible@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-collapsible@1.1.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-collection@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-collection@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-compose-refs@1.1.3(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-compose-refs@1.1.5(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-context@1.2.0(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-context@1.2.2(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 - - '@radix-ui/react-dialog@1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@types/react': 19.3.0 + + '@radix-ui/react-dialog@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) aria-hidden: 1.2.6 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-direction@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-direction@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-dismissable-layer@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-dismissable-layer@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-dropdown-menu@2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-menu': 2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-dropdown-menu@2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-focus-guards@1.1.4(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-focus-guards@1.1.6(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-focus-scope@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-focus-scope@1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-icons@1.3.2(react@19.2.7)': + '@radix-ui/react-icons@1.3.2(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 - '@radix-ui/react-id@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-id@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-label@2.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-label@2.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-menu@2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-menu@2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) aria-hidden: 1.2.6 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-popover@1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-popover@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) aria-hidden: 1.2.6 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-popper@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-arrow': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-rect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/rect': 1.1.2 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-popper@1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@floating-ui/react-dom': 2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-rect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/rect': 1.1.3 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-portal@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-portal@1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-presence@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-presence@1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-primitive@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-primitive@2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-radio-group@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-radio-group@1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-roving-focus@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.1(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-roving-focus@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-scroll-area@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/number': 1.1.2 - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-scroll-area@1.2.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-select@2.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/number': 1.1.2 - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-select@2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) aria-hidden: 1.2.6 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-separator@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-separator@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-slot@1.3.0(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-slot@1.3.3(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 - - '@radix-ui/react-switch@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + + '@radix-ui/react-switch@1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-tabs@1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-tabs@1.1.21(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) - - '@radix-ui/react-tooltip@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@radix-ui/primitive': 1.1.5 - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + + '@radix-ui/react-tooltip@1.2.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-effect-event@0.0.3(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-is-hydrated@0.1.1(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-previous@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-previous@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-rect@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-rect@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/rect': 1.1.2 - react: 19.2.7 + '@radix-ui/rect': 1.1.3 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-use-size@1.1.2(@types/react@19.2.17)(react@19.2.7)': + '@radix-ui/react-use-size@1.1.4(@types/react@19.3.0)(react@19.3.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) - react: 19.2.7 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@radix-ui/react-visually-hidden@1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-visually-hidden@1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) - '@radix-ui/rect@1.1.2': {} + '@radix-ui/rect@1.1.3': {} - '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1))(react@19.2.7)': + '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1))(react@19.3.0)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 - immer: 11.1.11 + immer: 11.1.18 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) - reselect: 5.2.0 + reselect: 5.3.0 optionalDependencies: - react: 19.2.7 - react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) + react: 19.3.0 + react-redux: 9.3.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1) - '@rolldown/binding-android-arm64@1.1.5': + '@rolldown/binding-android-arm-eabi@1.2.8': optional: true - '@rolldown/binding-darwin-arm64@1.1.5': + '@rolldown/binding-android-arm64@1.2.8': optional: true - '@rolldown/binding-darwin-x64@1.1.5': + '@rolldown/binding-darwin-arm64@1.2.8': optional: true - '@rolldown/binding-freebsd-x64@1.1.5': + '@rolldown/binding-darwin-x64@1.2.8': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + '@rolldown/binding-freebsd-x64@1.2.8': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.5': + '@rolldown/binding-linux-arm-gnueabihf@1.2.8': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.5': + '@rolldown/binding-linux-arm64-gnu@1.2.8': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.5': + '@rolldown/binding-linux-arm64-musl@1.2.8': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.5': + '@rolldown/binding-linux-ppc64-gnu@1.2.8': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.5': + '@rolldown/binding-linux-s390x-gnu@1.2.8': optional: true - '@rolldown/binding-linux-x64-musl@1.1.5': + '@rolldown/binding-linux-x64-gnu@1.2.8': optional: true - '@rolldown/binding-openharmony-arm64@1.1.5': + '@rolldown/binding-linux-x64-musl@1.2.8': optional: true - '@rolldown/binding-wasm32-wasi@1.1.5': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@rolldown/binding-openharmony-arm64@1.2.8': optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.5': + '@rolldown/binding-win32-arm64-msvc@1.2.8': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.5': + '@rolldown/binding-win32-x64-msvc@1.2.8': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -3708,235 +3878,235 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@swc/core-darwin-arm64@1.15.43': + '@swc/core-darwin-arm64@1.16.2': optional: true - '@swc/core-darwin-x64@1.15.43': + '@swc/core-darwin-x64@1.16.2': optional: true - '@swc/core-linux-arm-gnueabihf@1.15.43': + '@swc/core-linux-arm-gnueabihf@1.16.2': optional: true - '@swc/core-linux-arm64-gnu@1.15.43': + '@swc/core-linux-arm64-gnu@1.16.2': optional: true - '@swc/core-linux-arm64-musl@1.15.43': + '@swc/core-linux-arm64-musl@1.16.2': optional: true - '@swc/core-linux-ppc64-gnu@1.15.43': + '@swc/core-linux-ppc64-gnu@1.16.2': optional: true - '@swc/core-linux-s390x-gnu@1.15.43': + '@swc/core-linux-s390x-gnu@1.16.2': optional: true - '@swc/core-linux-x64-gnu@1.15.43': + '@swc/core-linux-x64-gnu@1.16.2': optional: true - '@swc/core-linux-x64-musl@1.15.43': + '@swc/core-linux-x64-musl@1.16.2': optional: true - '@swc/core-win32-arm64-msvc@1.15.43': + '@swc/core-win32-arm64-msvc@1.16.2': optional: true - '@swc/core-win32-ia32-msvc@1.15.43': + '@swc/core-win32-ia32-msvc@1.16.2': optional: true - '@swc/core-win32-x64-msvc@1.15.43': + '@swc/core-win32-x64-msvc@1.16.2': optional: true - '@swc/core@1.15.43': + '@swc/core@1.16.2': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.27 + '@swc/types': 0.1.28 optionalDependencies: - '@swc/core-darwin-arm64': 1.15.43 - '@swc/core-darwin-x64': 1.15.43 - '@swc/core-linux-arm-gnueabihf': 1.15.43 - '@swc/core-linux-arm64-gnu': 1.15.43 - '@swc/core-linux-arm64-musl': 1.15.43 - '@swc/core-linux-ppc64-gnu': 1.15.43 - '@swc/core-linux-s390x-gnu': 1.15.43 - '@swc/core-linux-x64-gnu': 1.15.43 - '@swc/core-linux-x64-musl': 1.15.43 - '@swc/core-win32-arm64-msvc': 1.15.43 - '@swc/core-win32-ia32-msvc': 1.15.43 - '@swc/core-win32-x64-msvc': 1.15.43 + '@swc/core-darwin-arm64': 1.16.2 + '@swc/core-darwin-x64': 1.16.2 + '@swc/core-linux-arm-gnueabihf': 1.16.2 + '@swc/core-linux-arm64-gnu': 1.16.2 + '@swc/core-linux-arm64-musl': 1.16.2 + '@swc/core-linux-ppc64-gnu': 1.16.2 + '@swc/core-linux-s390x-gnu': 1.16.2 + '@swc/core-linux-x64-gnu': 1.16.2 + '@swc/core-linux-x64-musl': 1.16.2 + '@swc/core-win32-arm64-msvc': 1.16.2 + '@swc/core-win32-ia32-msvc': 1.16.2 + '@swc/core-win32-x64-msvc': 1.16.2 '@swc/counter@0.1.3': {} - '@swc/types@0.1.27': + '@swc/types@0.1.28': dependencies: '@swc/counter': 0.1.3 - '@tailwindcss/node@4.3.2': + '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.21.6 + enhanced-resolve: 5.24.5 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.3.2 + tailwindcss: 4.3.3 - '@tailwindcss/oxide-android-arm64@4.3.2': + '@tailwindcss/oxide-android-arm64@4.3.3': optional: true - '@tailwindcss/oxide-darwin-arm64@4.3.2': + '@tailwindcss/oxide-darwin-arm64@4.3.3': optional: true - '@tailwindcss/oxide-darwin-x64@4.3.2': + '@tailwindcss/oxide-darwin-x64@4.3.3': optional: true - '@tailwindcss/oxide-freebsd-x64@4.3.2': + '@tailwindcss/oxide-freebsd-x64@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.3.2': + '@tailwindcss/oxide-linux-x64-musl@4.3.3': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.3.2': + '@tailwindcss/oxide-wasm32-wasi@4.3.3': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': optional: true - '@tailwindcss/oxide@4.3.2': + '@tailwindcss/oxide@4.3.3': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-arm64': 4.3.2 - '@tailwindcss/oxide-darwin-x64': 4.3.2 - '@tailwindcss/oxide-freebsd-x64': 4.3.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 - '@tailwindcss/oxide-linux-x64-musl': 4.3.2 - '@tailwindcss/oxide-wasm32-wasi': 4.3.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 - - '@tailwindcss/vite@4.3.2(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0))': - dependencies: - '@tailwindcss/node': 4.3.2 - '@tailwindcss/oxide': 4.3.2 - tailwindcss: 4.3.2 - vite: 8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0) - - '@tanstack/eslint-plugin-query@5.101.2(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': - dependencies: - '@typescript-eslint/utils': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.7.0(jiti@2.7.0) + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0) + + '@tanstack/eslint-plugin-query@5.102.8(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/utils': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.10.0(jiti@2.7.0) optionalDependencies: typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@tanstack/history@1.162.0': {} + '@tanstack/history@1.162.3': {} - '@tanstack/query-core@5.101.2': {} + '@tanstack/query-core@5.102.8': {} - '@tanstack/query-devtools@5.101.2': {} + '@tanstack/query-devtools@5.102.8': {} - '@tanstack/react-query-devtools@5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7)': + '@tanstack/react-query-devtools@5.102.8(@tanstack/react-query@5.102.8(react@19.3.0))(react@19.3.0)': dependencies: - '@tanstack/query-devtools': 5.101.2 - '@tanstack/react-query': 5.101.2(react@19.2.7) - react: 19.2.7 + '@tanstack/query-devtools': 5.102.8 + '@tanstack/react-query': 5.102.8(react@19.3.0) + react: 19.3.0 - '@tanstack/react-query@5.101.2(react@19.2.7)': + '@tanstack/react-query@5.102.8(react@19.3.0)': dependencies: - '@tanstack/query-core': 5.101.2 - react: 19.2.7 + '@tanstack/query-core': 5.102.8 + react: 19.3.0 - '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.14)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router-devtools@1.167.1(@tanstack/react-router@1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(@tanstack/router-core@1.171.29)(csstype@3.2.3)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@tanstack/react-router': 1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@tanstack/router-devtools-core': 1.168.0(@tanstack/router-core@1.171.14)(csstype@3.2.3) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@tanstack/react-router': 1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@tanstack/router-devtools-core': 1.168.1(@tanstack/router-core@1.171.29)(csstype@3.2.3) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) optionalDependencies: - '@tanstack/router-core': 1.171.14 + '@tanstack/router-core': 1.171.29 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router@1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: - '@tanstack/history': 1.162.0 - '@tanstack/react-store': 0.9.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@tanstack/router-core': 1.171.14 - isbot: 5.2.0 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@tanstack/history': 1.162.3 + '@tanstack/react-store': 0.9.3(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@tanstack/router-core': 1.171.29 + isbot: 5.2.2 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) - '@tanstack/react-store@0.9.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-store@0.9.3(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@tanstack/store': 0.9.3 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - use-sync-external-store: 1.6.0(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + use-sync-external-store: 1.7.0(react@19.3.0) - '@tanstack/react-table@8.21.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-table@8.21.3(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: '@tanstack/table-core': 8.21.3 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) - '@tanstack/router-core@1.171.14': + '@tanstack/router-core@1.171.29': dependencies: - '@tanstack/history': 1.162.0 + '@tanstack/history': 1.162.3 cookie-es: 3.1.1 - seroval: 1.5.4 - seroval-plugins: 1.5.4(seroval@1.5.4) + seroval: 1.6.7 + seroval-plugins: 1.6.7(seroval@1.6.7) - '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.14)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.168.1(@tanstack/router-core@1.171.29)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.171.14 + '@tanstack/router-core': 1.171.29 clsx: 2.1.1 goober: 2.1.19(csstype@3.2.3) optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.167.18': + '@tanstack/router-generator@1.167.35': dependencies: - '@babel/types': 7.29.7 - '@tanstack/router-core': 1.171.14 - '@tanstack/router-utils': 1.162.2 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.29 + '@tanstack/router-utils': 1.162.3 '@tanstack/virtual-file-routes': 1.162.0 jiti: 2.7.0 magic-string: 0.30.21 - prettier: 3.9.5 - zod: 4.4.3 + prettier: 3.9.6 + zod: 4.6.1 transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.19(@tanstack/react-router@1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(rolldown@1.1.5)(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.37(@tanstack/react-router@1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(rolldown@1.2.8)(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - '@tanstack/router-core': 1.171.14 - '@tanstack/router-generator': 1.167.18 - '@tanstack/router-utils': 1.162.2 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.29 + '@tanstack/router-generator': 1.167.35 + '@tanstack/router-utils': 1.162.3 chokidar: 5.0.0 - unplugin: 3.3.0(rolldown@1.1.5)(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)) - zod: 4.4.3 + unplugin: 3.3.0(rolldown@1.2.8)(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0)) + zod: 4.6.1 optionalDependencies: - '@tanstack/react-router': 1.170.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0) + '@tanstack/react-router': 1.170.34(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + vite: 8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0) transitivePeerDependencies: - '@farmfe/core' - '@rspack/core' @@ -3947,11 +4117,11 @@ snapshots: - supports-color - unloader - '@tanstack/router-utils@1.162.2': + '@tanstack/router-utils@1.162.3': dependencies: - '@babel/generator': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 ansis: 4.3.1 babel-dead-code-elimination: 1.0.12 diff: 8.0.4 @@ -3966,17 +4136,17 @@ snapshots: '@tanstack/virtual-file-routes@1.162.0': {} - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.5)': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6)': dependencies: - '@babel/generator': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.8 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 javascript-natural-sort: 0.7.1 lodash-es: 4.18.1 minimatch: 9.0.9 parse-imports-exports: 0.2.4 - prettier: 3.9.5 + prettier: 3.9.6 transitivePeerDependencies: - supports-color @@ -4001,7 +4171,7 @@ snapshots: dependencies: '@types/d3-time': 3.0.4 - '@types/d3-shape@3.1.8': + '@types/d3-shape@3.2.0': dependencies: '@types/d3-path': 3.1.1 @@ -4015,15 +4185,15 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.9.5': + '@types/node@25.9.6': dependencies: undici-types: 7.24.6 - '@types/react-dom@19.2.3(@types/react@19.2.17)': + '@types/react-dom@19.3.0(@types/react@19.3.0)': dependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - '@types/react@19.2.17': + '@types/react@19.3.0': dependencies: csstype: 3.2.3 @@ -4032,74 +4202,74 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@typescript-eslint/eslint-plugin@8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.63.0 - '@typescript-eslint/type-utils': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/utils': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.63.0 - eslint: 10.7.0(jiti@2.7.0) - ignore: 7.0.6 + '@typescript-eslint/parser': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.0 + eslint: 10.10.0(jiti@2.7.0) + ignore: 7.0.9 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/parser@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.63.0 - '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.63.0 + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.0 debug: 4.4.3 - eslint: 10.7.0(jiti@2.7.0) + eslint: 10.10.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.63.0(typescript@6.0.3)': + '@typescript-eslint/project-service@8.70.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.63.0(typescript@6.0.3) - '@typescript-eslint/types': 8.63.0 + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.63.0': + '@typescript-eslint/scope-manager@8.70.0': dependencies: - '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/visitor-keys': 8.63.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 - '@typescript-eslint/tsconfig-utils@8.63.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.70.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.7.0(jiti@2.7.0) + eslint: 10.10.0(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.63.0': {} + '@typescript-eslint/types@8.70.0': {} - '@typescript-eslint/typescript-estree@8.63.0(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.70.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.63.0(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.63.0(typescript@6.0.3) - '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/visitor-keys': 8.63.0 + '@typescript-eslint/project-service': 8.70.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 debug: 4.4.3 - minimatch: 10.2.5 + minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -4107,35 +4277,35 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/utils@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.7.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.63.0 - '@typescript-eslint/types': 8.63.0 - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - eslint: 10.7.0(jiti@2.7.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.10.0(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(typescript@6.0.3) + eslint: 10.10.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.63.0': + '@typescript-eslint/visitor-keys@8.70.0': dependencies: - '@typescript-eslint/types': 8.63.0 + '@typescript-eslint/types': 8.70.0 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react-swc@4.3.1(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0))': + '@vitejs/plugin-react-swc@4.3.3(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - '@swc/core': 1.15.43 - vite: 8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0) + '@swc/core': 1.16.2 + vite: 8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0) transitivePeerDependencies: - '@swc/helpers' - acorn-jsx@5.3.2(acorn@8.17.0): + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: - acorn: 8.17.0 + acorn: 8.18.0 - acorn@8.17.0: {} + acorn@8.18.0: {} agent-base@6.0.2: dependencies: @@ -4158,7 +4328,7 @@ snapshots: asynckit@0.4.0: {} - axios@1.18.1: + axios@1.20.0: dependencies: follow-redirects: 1.16.0 form-data: 4.0.6 @@ -4171,9 +4341,9 @@ snapshots: babel-dead-code-elimination@1.0.12: dependencies: '@babel/core': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color @@ -4183,11 +4353,11 @@ snapshots: baseline-browser-mapping@2.10.42: {} - brace-expansion@2.1.2: + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.7: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -4199,6 +4369,14 @@ snapshots: node-releases: 2.0.50 update-browserslist-db: 1.2.3(browserslist@4.28.4) + cacheable@2.5.0: + dependencies: + '@cacheable/memory': 2.2.0 + '@cacheable/utils': 2.5.0 + hookified: 1.15.1 + keyv: 5.6.0 + qified: 0.10.1 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -4208,7 +4386,7 @@ snapshots: chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 class-variance-authority@0.7.1: dependencies: @@ -4218,14 +4396,14 @@ snapshots: clsx@2.1.1: {} - cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + cmdk@1.1.1(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-dialog': 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -4302,7 +4480,7 @@ snapshots: diff@8.0.4: {} - dompurify@3.4.11: + dompurify@3.4.15: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -4314,7 +4492,7 @@ snapshots: electron-to-chromium@1.5.387: {} - enhanced-resolve@5.21.6: + enhanced-resolve@5.24.5: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -4334,26 +4512,26 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.4 - es-toolkit@1.49.0: {} + es-toolkit@1.52.0: {} escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@7.1.1(eslint@10.7.0(jiti@2.7.0)): + eslint-plugin-react-hooks@7.1.1(eslint@10.10.0(jiti@2.7.0)): dependencies: '@babel/core': 7.29.7 - '@babel/parser': 7.29.7 - eslint: 10.7.0(jiti@2.7.0) + '@babel/parser': 7.29.8 + eslint: 10.10.0(jiti@2.7.0) hermes-parser: 0.25.1 - zod: 4.4.3 - zod-validation-error: 4.0.2(zod@4.4.3) + zod: 4.6.1 + zod-validation-error: 4.0.2(zod@4.6.1) transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.5.3(eslint@10.7.0(jiti@2.7.0)): + eslint-plugin-react-refresh@0.5.6(eslint@10.10.0(jiti@2.7.0)): dependencies: - eslint: 10.7.0(jiti@2.7.0) + eslint: 10.10.0(jiti@2.7.0) eslint-scope@9.1.2: dependencies: @@ -4366,14 +4544,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.7.0(jiti@2.7.0): + eslint@10.10.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.7.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.10.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 - '@eslint/config-helpers': 0.6.0 + '@eslint/config-helpers': 0.7.0 '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.2 + '@eslint/plugin-kit': 0.7.3 '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -4388,14 +4566,14 @@ snapshots: esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 + file-entry-cache: 11.1.5 find-up: 5.0.0 glob-parent: 6.0.2 ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -4405,8 +4583,8 @@ snapshots: espree@11.2.0: dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 5.0.1 esquery@1.7.0: @@ -4433,25 +4611,26 @@ snapshots: dependencies: walk-up-path: 4.0.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.7 - file-entry-cache@8.0.0: + file-entry-cache@11.1.5: dependencies: - flat-cache: 4.0.1 + flat-cache: 6.1.23 find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@4.0.1: + flat-cache@6.1.23: dependencies: - flatted: 3.4.2 - keyv: 4.5.4 + cacheable: 2.5.0 + flatted: 3.4.4 + hookified: 1.15.1 - flatted@3.4.2: {} + flatted@3.4.4: {} follow-redirects@1.16.0: {} @@ -4463,9 +4642,10 @@ snapshots: hasown: 2.0.4 mime-types: 2.1.35 - formatly@0.3.0: + formatly@0.7.0: dependencies: fd-package-json: 2.0.0 + package-manager-detector: 1.8.0 fsevents@2.3.3: optional: true @@ -4494,7 +4674,7 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.2 - get-tsconfig@4.14.0: + get-tsconfig@4.14.3: dependencies: resolve-pkg-maps: 1.0.0 @@ -4502,12 +4682,12 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@17.7.0: {} + globals@17.12.0: {} - go-captcha-react@1.0.5(react@19.2.7): + go-captcha-react@1.0.5(react@19.3.0): dependencies: classnames: 2.5.1 - react: 19.2.7 + react: 19.3.0 goober@2.1.19(csstype@3.2.3): dependencies: @@ -4523,6 +4703,10 @@ snapshots: dependencies: has-symbols: 1.1.0 + hashery@1.5.1: + dependencies: + hookified: 1.15.1 + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -4533,6 +4717,10 @@ snapshots: dependencies: hermes-estree: 0.25.1 + hookified@1.15.1: {} + + hookified@2.2.0: {} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 @@ -4542,16 +4730,16 @@ snapshots: ignore@5.3.2: {} - ignore@7.0.6: {} + ignore@7.0.9: {} - immer@11.1.11: {} + immer@11.1.18: {} imurmurhash@0.1.4: {} - input-otp@1.4.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + input-otp@1.5.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) internmap@2.0.3: {} @@ -4561,7 +4749,7 @@ snapshots: dependencies: is-extglob: 2.1.1 - isbot@5.2.0: {} + isbot@5.2.2: {} isexe@2.0.0: {} @@ -4573,33 +4761,31 @@ snapshots: jsesc@3.1.0: {} - json-buffer@3.0.1: {} - json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} - keyv@4.5.4: + keyv@5.6.0: dependencies: - json-buffer: 3.0.1 + '@keyv/serialize': 1.1.1 - knip@6.26.0: + knip@6.35.1: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - formatly: 0.3.0 - get-tsconfig: 4.14.0 + fdir: 6.5.0(picomatch@4.0.7) + formatly: 0.7.0 + get-tsconfig: 4.14.3 jiti: 2.7.0 - oxc-parser: 0.137.0 - oxc-resolver: 11.21.3 - picomatch: 4.0.5 - smol-toml: 1.7.0 + oxc-parser: 0.148.0 + oxc-resolver: 11.24.2 + picomatch: 4.0.7 + smol-toml: 1.8.0 strip-json-comments: 5.0.3 tinyglobby: 0.2.17 - unbash: 4.0.2 + unbash: 4.0.11 yaml: 2.9.0 - zod: 4.4.3 + zod: 4.6.1 levn@0.4.1: dependencies: @@ -4609,36 +4795,69 @@ snapshots: lightningcss-android-arm64@1.32.0: optional: true + lightningcss-android-arm64@1.33.0: + optional: true + lightningcss-darwin-arm64@1.32.0: optional: true + lightningcss-darwin-arm64@1.33.0: + optional: true + lightningcss-darwin-x64@1.32.0: optional: true + lightningcss-darwin-x64@1.33.0: + optional: true + lightningcss-freebsd-x64@1.32.0: optional: true + lightningcss-freebsd-x64@1.33.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: optional: true + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + lightningcss-linux-arm64-gnu@1.32.0: optional: true + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + lightningcss-linux-arm64-musl@1.32.0: optional: true + lightningcss-linux-arm64-musl@1.33.0: + optional: true + lightningcss-linux-x64-gnu@1.32.0: optional: true + lightningcss-linux-x64-gnu@1.33.0: + optional: true + lightningcss-linux-x64-musl@1.32.0: optional: true + lightningcss-linux-x64-musl@1.33.0: + optional: true + lightningcss-win32-arm64-msvc@1.32.0: optional: true + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + lightningcss-win32-x64-msvc@1.32.0: optional: true + lightningcss-win32-x64-msvc@1.33.0: + optional: true + lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 @@ -4655,6 +4874,22 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -4665,13 +4900,13 @@ snapshots: dependencies: yallist: 3.1.1 - lucide-react@1.24.0(react@19.2.7): + lucide-react@1.44.0(react@19.3.0): dependencies: - react: 19.2.7 + react: 19.3.0 magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 math-intrinsics@1.1.0: {} @@ -4681,17 +4916,17 @@ snapshots: dependencies: mime-db: 1.52.0 - minimatch@10.2.5: + minimatch@10.2.6: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 ms@2.1.3: {} - nanoid@3.3.15: {} + nanoid@3.3.18: {} natural-compare@1.4.0: {} @@ -4706,52 +4941,51 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - oxc-parser@0.137.0: + oxc-parser@0.148.0: dependencies: - '@oxc-project/types': 0.137.0 + '@oxc-project/types': 0.148.0 optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.137.0 - '@oxc-parser/binding-android-arm64': 0.137.0 - '@oxc-parser/binding-darwin-arm64': 0.137.0 - '@oxc-parser/binding-darwin-x64': 0.137.0 - '@oxc-parser/binding-freebsd-x64': 0.137.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.137.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.137.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.137.0 - '@oxc-parser/binding-linux-arm64-musl': 0.137.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.137.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.137.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.137.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.137.0 - '@oxc-parser/binding-linux-x64-gnu': 0.137.0 - '@oxc-parser/binding-linux-x64-musl': 0.137.0 - '@oxc-parser/binding-openharmony-arm64': 0.137.0 - '@oxc-parser/binding-wasm32-wasi': 0.137.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.137.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.137.0 - '@oxc-parser/binding-win32-x64-msvc': 0.137.0 - - oxc-resolver@11.21.3: + '@oxc-parser/binding-android-arm-eabi': 0.148.0 + '@oxc-parser/binding-android-arm64': 0.148.0 + '@oxc-parser/binding-darwin-arm64': 0.148.0 + '@oxc-parser/binding-darwin-x64': 0.148.0 + '@oxc-parser/binding-freebsd-x64': 0.148.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.148.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.148.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.148.0 + '@oxc-parser/binding-linux-arm64-musl': 0.148.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.148.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.148.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.148.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.148.0 + '@oxc-parser/binding-linux-x64-gnu': 0.148.0 + '@oxc-parser/binding-linux-x64-musl': 0.148.0 + '@oxc-parser/binding-openharmony-arm64': 0.148.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.148.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.148.0 + '@oxc-parser/binding-win32-x64-msvc': 0.148.0 + + oxc-resolver@11.24.2: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.21.3 - '@oxc-resolver/binding-android-arm64': 11.21.3 - '@oxc-resolver/binding-darwin-arm64': 11.21.3 - '@oxc-resolver/binding-darwin-x64': 11.21.3 - '@oxc-resolver/binding-freebsd-x64': 11.21.3 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.21.3 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.21.3 - '@oxc-resolver/binding-linux-arm64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-arm64-musl': 11.21.3 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-riscv64-musl': 11.21.3 - '@oxc-resolver/binding-linux-s390x-gnu': 11.21.3 - '@oxc-resolver/binding-linux-x64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-x64-musl': 11.21.3 - '@oxc-resolver/binding-openharmony-arm64': 11.21.3 - '@oxc-resolver/binding-wasm32-wasi': 11.21.3 - '@oxc-resolver/binding-win32-arm64-msvc': 11.21.3 - '@oxc-resolver/binding-win32-x64-msvc': 11.21.3 + '@oxc-resolver/binding-android-arm-eabi': 11.24.2 + '@oxc-resolver/binding-android-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-x64': 11.24.2 + '@oxc-resolver/binding-freebsd-x64': 11.24.2 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-arm64-musl': 11.24.2 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-musl': 11.24.2 + '@oxc-resolver/binding-linux-s390x-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-musl': 11.24.2 + '@oxc-resolver/binding-openharmony-arm64': 11.24.2 + '@oxc-resolver/binding-wasm32-wasi': 11.24.2 + '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 + '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 p-limit@3.1.0: dependencies: @@ -4761,6 +4995,8 @@ snapshots: dependencies: p-limit: 3.1.0 + package-manager-detector@1.8.0: {} + parse-imports-exports@0.2.4: dependencies: parse-statements: 1.0.11 @@ -4775,106 +5011,110 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.5: {} + picomatch@4.0.7: {} - postcss@8.5.16: + postcss@8.5.28: dependencies: - nanoid: 3.3.15 + nanoid: 3.3.18 picocolors: 1.1.1 source-map-js: 1.2.1 prelude-ls@1.2.1: {} - prettier-plugin-tailwindcss@0.8.0(@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.5))(prettier@3.9.5): + prettier-plugin-tailwindcss@0.8.1(@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6))(prettier@3.9.6): dependencies: - prettier: 3.9.5 + prettier: 3.9.6 optionalDependencies: - '@trivago/prettier-plugin-sort-imports': 6.0.2(prettier@3.9.5) + '@trivago/prettier-plugin-sort-imports': 6.0.2(prettier@3.9.6) - prettier@3.9.5: {} + prettier@3.9.6: {} proxy-from-env@2.1.0: {} punycode@2.3.1: {} - react-day-picker@10.0.1(@types/react@19.2.17)(react@19.2.7): + qified@0.10.1: + dependencies: + hookified: 2.2.0 + + react-day-picker@10.0.1(@types/react@19.3.0)(react@19.3.0): dependencies: '@date-fns/tz': 1.5.0 date-fns: 4.4.0 - react: 19.2.7 + react: 19.3.0 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - react-dom@19.2.7(react@19.2.7): + react-dom@19.3.0(react@19.3.0): dependencies: - react: 19.2.7 - scheduler: 0.27.0 + react: 19.3.0 + scheduler: 0.28.0 - react-hook-form@7.81.0(react@19.2.7): + react-hook-form@7.87.0(react@19.3.0): dependencies: - react: 19.2.7 + react: 19.3.0 react-is@19.2.7: {} - react-redux@9.3.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1): + react-redux@9.3.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 - react: 19.2.7 - use-sync-external-store: 1.6.0(react@19.2.7) + react: 19.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 redux: 5.0.1 - react-remove-scroll-bar@2.3.8(@types/react@19.2.17)(react@19.2.7): + react-remove-scroll-bar@2.3.8(@types/react@19.3.0)(react@19.3.0): dependencies: - react: 19.2.7 - react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.0) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - react-remove-scroll@2.7.2(@types/react@19.2.17)(react@19.2.7): + react-remove-scroll@2.7.2(@types/react@19.3.0)(react@19.3.0): dependencies: - react: 19.2.7 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.17)(react@19.2.7) - react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + react: 19.3.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.3.0)(react@19.3.0) + react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.17)(react@19.2.7) - use-sidecar: 1.1.3(@types/react@19.2.17)(react@19.2.7) + use-callback-ref: 1.3.3(@types/react@19.3.0)(react@19.3.0) + use-sidecar: 1.1.3(@types/react@19.3.0)(react@19.3.0) optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7): + react-style-singleton@2.2.3(@types/react@19.3.0)(react@19.3.0): dependencies: get-nonce: 1.0.1 - react: 19.2.7 + react: 19.3.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - react-top-loading-bar@3.0.2(react@19.2.7): + react-top-loading-bar@3.0.2(react@19.3.0): dependencies: - react: 19.2.7 + react: 19.3.0 - react@19.2.7: {} + react@19.3.0: {} - readdirp@5.0.0: {} + readdirp@5.1.1: {} - recharts@3.9.2(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@19.2.7)(react@19.2.7)(redux@5.0.1): + recharts@3.10.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react-is@19.2.7)(react@19.3.0)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1))(react@19.2.7) + '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1))(react@19.3.0) clsx: 2.1.1 decimal.js-light: 2.5.1 - es-toolkit: 1.49.0 + es-toolkit: 1.52.0 eventemitter3: 5.0.4 - immer: 11.1.11 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + immer: 11.1.18 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) react-is: 19.2.7 - react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) + react-redux: 9.3.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1) reselect: 5.2.0 tiny-invariant: 1.3.3 - use-sync-external-store: 1.6.0(react@19.2.7) + use-sync-external-store: 1.7.0(react@19.3.0) victory-vendor: 37.3.6 transitivePeerDependencies: - '@types/react' @@ -4888,40 +5128,42 @@ snapshots: reselect@5.2.0: {} + reselect@5.3.0: {} + resolve-pkg-maps@1.0.0: {} - rolldown@1.1.5: + rolldown@1.2.8: dependencies: - '@oxc-project/types': 0.139.0 + '@oxc-project/types': 0.149.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.5 - '@rolldown/binding-darwin-arm64': 1.1.5 - '@rolldown/binding-darwin-x64': 1.1.5 - '@rolldown/binding-freebsd-x64': 1.1.5 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 - '@rolldown/binding-linux-arm64-gnu': 1.1.5 - '@rolldown/binding-linux-arm64-musl': 1.1.5 - '@rolldown/binding-linux-ppc64-gnu': 1.1.5 - '@rolldown/binding-linux-s390x-gnu': 1.1.5 - '@rolldown/binding-linux-x64-gnu': 1.1.5 - '@rolldown/binding-linux-x64-musl': 1.1.5 - '@rolldown/binding-openharmony-arm64': 1.1.5 - '@rolldown/binding-wasm32-wasi': 1.1.5 - '@rolldown/binding-win32-arm64-msvc': 1.1.5 - '@rolldown/binding-win32-x64-msvc': 1.1.5 - - scheduler@0.27.0: {} + '@rolldown/binding-android-arm-eabi': 1.2.8 + '@rolldown/binding-android-arm64': 1.2.8 + '@rolldown/binding-darwin-arm64': 1.2.8 + '@rolldown/binding-darwin-x64': 1.2.8 + '@rolldown/binding-freebsd-x64': 1.2.8 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.8 + '@rolldown/binding-linux-arm64-gnu': 1.2.8 + '@rolldown/binding-linux-arm64-musl': 1.2.8 + '@rolldown/binding-linux-ppc64-gnu': 1.2.8 + '@rolldown/binding-linux-s390x-gnu': 1.2.8 + '@rolldown/binding-linux-x64-gnu': 1.2.8 + '@rolldown/binding-linux-x64-musl': 1.2.8 + '@rolldown/binding-openharmony-arm64': 1.2.8 + '@rolldown/binding-win32-arm64-msvc': 1.2.8 + '@rolldown/binding-win32-x64-msvc': 1.2.8 + + scheduler@0.28.0: {} semver@6.3.1: {} semver@7.8.5: {} - seroval-plugins@1.5.4(seroval@1.5.4): + seroval-plugins@1.6.7(seroval@1.6.7): dependencies: - seroval: 1.5.4 + seroval: 1.6.7 - seroval@1.5.4: {} + seroval@1.6.7: {} shebang-command@2.0.0: dependencies: @@ -4929,12 +5171,14 @@ snapshots: shebang-regex@3.0.0: {} - smol-toml@1.7.0: {} + smol-toml@1.8.0: {} - sonner@2.0.7(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + sonner@2.0.8(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 source-map-js@1.2.1: {} @@ -4942,7 +5186,7 @@ snapshots: tailwind-merge@3.6.0: {} - tailwindcss@4.3.2: {} + tailwindcss@4.3.3: {} tapable@2.3.3: {} @@ -4950,8 +5194,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 ts-api-utils@2.5.0(typescript@6.0.3): dependencies: @@ -4965,31 +5209,31 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3): + typescript-eslint@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.63.0(@typescript-eslint/parser@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/parser': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.63.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.7.0(jiti@2.7.0) + '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.70.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.10.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color typescript@6.0.3: {} - unbash@4.0.2: {} + unbash@4.0.11: {} undici-types@7.24.6: {} - unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0)): + unplugin@3.3.0(rolldown@1.2.8)(vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@jridgewell/remapping': 2.3.5 - picomatch: 4.0.5 + picomatch: 4.0.7 webpack-virtual-modules: 0.6.2 optionalDependencies: - rolldown: 1.1.5 - vite: 8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0) + rolldown: 1.2.8 + vite: 8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0) update-browserslist-db@1.2.3(browserslist@4.28.4): dependencies: @@ -5001,24 +5245,24 @@ snapshots: dependencies: punycode: 2.3.1 - use-callback-ref@1.3.3(@types/react@19.2.17)(react@19.2.7): + use-callback-ref@1.3.3(@types/react@19.3.0)(react@19.3.0): dependencies: - react: 19.2.7 + react: 19.3.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.7): + use-sidecar@1.1.3(@types/react@19.3.0)(react@19.3.0): dependencies: detect-node-es: 1.1.0 - react: 19.2.7 + react: 19.3.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.17 + '@types/react': 19.3.0 - use-sync-external-store@1.6.0(react@19.2.7): + use-sync-external-store@1.7.0(react@19.3.0): dependencies: - react: 19.2.7 + react: 19.3.0 victory-vendor@37.3.6: dependencies: @@ -5026,7 +5270,7 @@ snapshots: '@types/d3-ease': 3.0.2 '@types/d3-interpolate': 3.0.4 '@types/d3-scale': 4.0.9 - '@types/d3-shape': 3.1.8 + '@types/d3-shape': 3.2.0 '@types/d3-time': 3.0.4 '@types/d3-timer': 3.0.2 d3-array: 3.2.4 @@ -5037,15 +5281,15 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.1.4(@types/node@25.9.5)(jiti@2.7.0)(yaml@2.9.0): + vite@8.3.0(@types/node@25.9.6)(jiti@2.7.0)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.5 - postcss: 8.5.16 - rolldown: 1.1.5 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.28 + rolldown: 1.2.8 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 25.9.5 + '@types/node': 25.9.6 fsevents: 2.3.3 jiti: 2.7.0 yaml: 2.9.0 @@ -5066,15 +5310,15 @@ snapshots: yocto-queue@0.1.0: {} - zod-validation-error@4.0.2(zod@4.4.3): + zod-validation-error@4.0.2(zod@4.6.1): dependencies: - zod: 4.4.3 + zod: 4.6.1 - zod@4.4.3: {} + zod@4.6.1: {} - zustand@5.0.14(@types/react@19.2.17)(immer@11.1.11)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)): + zustand@5.0.15(@types/react@19.3.0)(immer@11.1.18)(react@19.3.0)(use-sync-external-store@1.7.0(react@19.3.0)): optionalDependencies: - '@types/react': 19.2.17 - immer: 11.1.11 - react: 19.2.7 - use-sync-external-store: 1.6.0(react@19.2.7) + '@types/react': 19.3.0 + immer: 11.1.18 + react: 19.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) From 822e77f79c30c061df4ad195e99fb53a09f40bf4 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 21:58:07 +0800 Subject: [PATCH 15/18] perf: logs printer --- api/middleware/log_middleware.go | 77 ++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/api/middleware/log_middleware.go b/api/middleware/log_middleware.go index ddeaed8..56e7988 100644 --- a/api/middleware/log_middleware.go +++ b/api/middleware/log_middleware.go @@ -4,13 +4,15 @@ import ( "bytes" "fmt" "io" - "log" "strings" "time" "github.com/gin-gonic/gin" ) +// maxLogBodyLen 日志中请求/响应体的最大展示长度,超出则截断 +const maxLogBodyLen = 1000 + // LogMiddleware 请求和响应日志中间件 func LogMiddleware() gin.HandlerFunc { return func(c *gin.Context) { @@ -28,58 +30,65 @@ func LogMiddleware() gin.HandlerFunc { w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer} c.Writer = w - // 构建请求日志信息 - var logLines []string - logLines = append(logLines, fmt.Sprintf("> 📥 REQUEST: %s %s", c.Request.Method, c.Request.URL.Path)) - logLines = append(logLines, "┌─────────────────────────────────────────────────────────────") + // 执行请求 + c.Next() + + duration := time.Since(start) + statusCode := c.Writer.Status() + statusEmoji := getStatusEmoji(statusCode) + responseBody := w.body.String() + + // 组装日志:标题行(Result 合并进首行)+ 缩进详情,无边框 + var lines []string - if len(c.Request.URL.RawQuery) > 0 { - logLines = append(logLines, fmt.Sprintf("│ 🔍 Query: %s", c.Request.URL.RawQuery)) + target := c.Request.URL.Path + if c.Request.URL.RawQuery != "" { + target += "?" + c.Request.URL.RawQuery } + result := fmt.Sprintf("[%d] %s %s", statusCode, statusEmoji, duration) + + // ▶ 图标按状态码着色:2xx 绿、4xx/5xx 红,其余无色 + icon := "▶" + switch { + case statusCode >= 200 && statusCode < 300: + icon = "\x1b[32m▶\x1b[0m" + case statusCode >= 400: + icon = "\x1b[31m▶\x1b[0m" + } + lines = append(lines, fmt.Sprintf("%s %s %s %s", icon, c.Request.Method, target, result)) - // 只显示重要的请求头 + // 只显示重要的请求头(Authorization 脱敏) importantHeaders := []string{"Content-Type", "Authorization", "Accept"} for _, header := range importantHeaders { if value := c.Request.Header.Get(header); value != "" { - // 对Authorization进行脱敏处理 if header == "Authorization" && len(value) > 20 { value = value[:20] + "..." } - logLines = append(logLines, fmt.Sprintf("│ 📋 %s: %s", header, value)) + lines = append(lines, fmt.Sprintf(" Header : %s: %s", header, value)) } } + // 请求内容(请求体),仅在存在时输出,置于 Resp 之前 if len(requestBody) > 0 { - logLines = append(logLines, fmt.Sprintf("│ 📦 Body: %s", string(requestBody))) + lines = append(lines, fmt.Sprintf(" Request : %s", truncateLog(requestBody))) } - // 执行请求 - c.Next() - - // 计算请求耗时 - duration := time.Since(start) - - // 获取状态码颜色 - statusCode := c.Writer.Status() - statusEmoji := getStatusEmoji(statusCode) - - // 添加响应信息到日志 - responseBody := w.body.String() - logLines = append(logLines, fmt.Sprintf("│ %s RESPONSE: [%d] - %s", statusEmoji, statusCode, duration)) - if len(responseBody) > 0 { - // 限制响应体长度以提高可读性 - if len(responseBody) > 5000 { - logLines = append(logLines, fmt.Sprintf("│ 📤 %s... (truncated)", responseBody[:500])) - } else { - logLines = append(logLines, fmt.Sprintf("│ 📤 %s", responseBody)) - } + lines = append(lines, fmt.Sprintf(" Resp : %s", truncateLog([]byte(responseBody)))) } - logLines = append(logLines, "└─────────────────────────────────────────────────────────────") - // 一次性打印完整日志,避免中断 - log.Print(strings.Join(logLines, "\n")) + // 末尾空一行,便于在连续请求之间区分 + lines = append(lines, "") + fmt.Print(strings.Join(lines, "\n")) + } +} + +// truncateLog 截断超长内容,并标注原始长度 +func truncateLog(data []byte) string { + if len(data) <= maxLogBodyLen { + return string(data) } + return fmt.Sprintf("%s... (truncated, %d chars)", string(data[:maxLogBodyLen]), len(data)) } // responseBodyWriter 用于捕获响应体 From 1ff0359d3f1515f9953cc458ce9f505f2444fb8f Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 21:58:40 +0800 Subject: [PATCH 16/18] feat: add test --- internal/casbin/manager.go | 24 ++- internal/casbin/manager_test.go | 288 ++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 7 deletions(-) create mode 100644 internal/casbin/manager_test.go diff --git a/internal/casbin/manager.go b/internal/casbin/manager.go index 48d5525..669813a 100644 --- a/internal/casbin/manager.go +++ b/internal/casbin/manager.go @@ -61,21 +61,31 @@ func NewCasManager(adapter any) Manager { } } -// initializeCasbin 初始化Casbin组件 -func initializeCasbin(adapter any) error { +// newEnforcer 构建一个独立的 enforcer。生产路径经 initializeCasbin 赋值给包级 +// 单例;测试用它构造彼此隔离的实例,避免共享状态相互污染。 +func newEnforcer(adapter any) (*casbin.Enforcer, error) { m, err := model.NewModelFromString(ModelConf) if err != nil { - return err + return nil, err } - enforcer, err = casbin.NewEnforcer(m, adapter) + e, err := casbin.NewEnforcer(m, adapter) if err != nil { - return err + return nil, err } - enforcer.EnableAutoSave(true) + e.EnableAutoSave(true) + e.SetLogger(newCasbinLogger()) + return e, nil +} - enforcer.SetLogger(newCasbinLogger()) +// initializeCasbin 初始化Casbin组件 +func initializeCasbin(adapter any) error { + e, err := newEnforcer(adapter) + if err != nil { + return err + } + enforcer = e return nil } diff --git a/internal/casbin/manager_test.go b/internal/casbin/manager_test.go new file mode 100644 index 0000000..d3d5ab7 --- /dev/null +++ b/internal/casbin/manager_test.go @@ -0,0 +1,288 @@ +package casbin + +import ( + "sort" + "strings" + "testing" + + "github.com/casbin/casbin/v3/model" +) + +// memAdapter 是测试用的最小适配器:enforcer 的策略状态完全在内存中, +// 适配器只用来满足 casbin.NewEnforcer 的接口要求,不承载任何断言。 +type memAdapter struct{} + +func (a *memAdapter) LoadPolicy(model.Model) error { return nil } +func (a *memAdapter) SavePolicy(model.Model) error { return nil } +func (a *memAdapter) AddPolicy(string, string, []string) error { return nil } +func (a *memAdapter) RemovePolicy(string, string, []string) error { return nil } +func (a *memAdapter) RemoveFilteredPolicy(string, string, int, ...string) error { return nil } + +// testManager 为每个用例构建独立的 enforcer,用例之间互不污染, +// 因此夹具无需命名空间前缀,也支持 -shuffle / -count 重复运行。 +func testManager(tb testing.TB) Manager { + tb.Helper() + e, err := newEnforcer(&memAdapter{}) + if err != nil { + tb.Fatalf("newEnforcer: %v", err) + } + return &CasManager{enforcer: e} +} + +func mustAddPolicy(t *testing.T, m Manager, role, obj, act string) { + t.Helper() + ok, err := m.AddPolicy(role, obj, act) + if err != nil { + t.Fatalf("AddPolicy(%q, %q, %q): %v", role, obj, act, err) + } + if !ok { + t.Fatalf("AddPolicy(%q, %q, %q): ok=false, want true", role, obj, act) + } +} + +func mustRemovePolicy(t *testing.T, m Manager, role, obj, act string) { + t.Helper() + ok, err := m.RemovePolicy(role, obj, act) + if err != nil { + t.Fatalf("RemovePolicy(%q, %q, %q): %v", role, obj, act, err) + } + if !ok { + t.Fatalf("RemovePolicy(%q, %q, %q): ok=false, want true", role, obj, act) + } +} + +func mustRemoveFilteredPolicy(t *testing.T, m Manager, fieldIndex int, values ...string) { + t.Helper() + ok, err := m.RemoveFilteredPolicy(fieldIndex, values...) + if err != nil { + t.Fatalf("RemoveFilteredPolicy(%d, %v): %v", fieldIndex, values, err) + } + if !ok { + t.Fatalf("RemoveFilteredPolicy(%d, %v): ok=false, want true", fieldIndex, values) + } +} + +func mustAddRoleForUser(t *testing.T, m Manager, user, role string) { + t.Helper() + ok, err := m.AddRoleForUser(user, role) + if err != nil { + t.Fatalf("AddRoleForUser(%q, %q): %v", user, role, err) + } + if !ok { + t.Fatalf("AddRoleForUser(%q, %q): ok=false, want true", user, role) + } +} + +func mustDeleteRolesForUser(t *testing.T, m Manager, user string) { + t.Helper() + ok, err := m.DeleteRolesForUser(user) + if err != nil { + t.Fatalf("DeleteRolesForUser(%q): %v", user, err) + } + if !ok { + t.Fatalf("DeleteRolesForUser(%q): ok=false, want true", user) + } +} + +func assertPermission(t *testing.T, m Manager, userID, obj, act string, want bool) { + t.Helper() + got, err := m.CheckPermission(userID, obj, act) + if err != nil { + t.Fatalf("CheckPermission(%q, %q, %q): %v", userID, obj, act, err) + } + if got != want { + t.Fatalf("CheckPermission(%q, %q, %q) = %v, want %v", userID, obj, act, got, want) + } +} + +func TestCheckPermission(t *testing.T) { + const ( + roleExact = "role-exact" + roleWild = "role-wild" + userNormal = "user-normal" + userWild = "user-wild" + ) + objExact := "/api/v1/res/allowed" + objOther := "/api/v1/res/other" + + m := testManager(t) + mustAddPolicy(t, m, roleExact, objExact, "GET") + mustAddPolicy(t, m, roleExact, "/api/v1/res/:id", "POST") + mustAddPolicy(t, m, roleWild, "*", "*") + mustAddRoleForUser(t, m, userNormal, roleExact) + mustAddRoleForUser(t, m, userWild, roleWild) + + cases := []struct { + name string + userID, obj, act string + want bool + }{ + {"exact path and method", userNormal, objExact, "GET", true}, + {"keyMatch2 path", userNormal, "/api/v1/res/42", "POST", true}, + {"wrong method", userNormal, objExact, "DELETE", false}, + {"unrelated path", userNormal, objOther, "GET", false}, + {"wildcard role", userWild, objOther, "DELETE", true}, + {"user without roles", "user-nobody", objExact, "GET", false}, + {"empty user", "", objExact, "GET", false}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + assertPermission(t, m, tc.userID, tc.obj, tc.act, tc.want) + }) + } +} + +// 当前实现无结果缓存;下面四个用例锁定"策略变更立即生效", +// 并在将来引入结果缓存时守住失效逻辑。 +func TestCheckPermission_PolicyChangeTakesEffect_OnGrant(t *testing.T) { + const ( + role = "role" + user = "user" + ) + obj := "/api/v1/res" + + m := testManager(t) + mustAddRoleForUser(t, m, user, role) + + // 先确认一个 deny 结果 + assertPermission(t, m, user, obj, "GET", false) + + mustAddPolicy(t, m, role, obj, "GET") + + assertPermission(t, m, user, obj, "GET", true) +} + +// 撤权后若仍放行即为安全漏洞。 +func TestCheckPermission_PolicyChangeTakesEffect_OnRevoke(t *testing.T) { + const ( + role = "role" + user = "user" + ) + obj := "/api/v1/res" + + m := testManager(t) + mustAddRoleForUser(t, m, user, role) + mustAddPolicy(t, m, role, obj, "GET") + + // 先确认一个 allow 结果 + assertPermission(t, m, user, obj, "GET", true) + + mustRemovePolicy(t, m, role, obj, "GET") + + assertPermission(t, m, user, obj, "GET", false) +} + +// RemoveFilteredPolicy 是"删除某角色所有策略"的批量入口。 +func TestCheckPermission_PolicyChangeTakesEffect_OnRemoveFilteredPolicy(t *testing.T) { + const ( + role = "role" + user = "user" + ) + obj := "/api/v1/res" + + m := testManager(t) + mustAddRoleForUser(t, m, user, role) + mustAddPolicy(t, m, role, obj, "GET") + assertPermission(t, m, user, obj, "GET", true) + + mustRemoveFilteredPolicy(t, m, 0, role) + + assertPermission(t, m, user, obj, "GET", false) +} + +func TestCheckPermission_PolicyChangeTakesEffect_OnDeleteRolesForUser(t *testing.T) { + const ( + role = "role" + user = "user" + ) + obj := "/api/v1/res" + + m := testManager(t) + mustAddRoleForUser(t, m, user, role) + mustAddPolicy(t, m, role, obj, "GET") + assertPermission(t, m, user, obj, "GET", true) + + mustDeleteRolesForUser(t, m, user) + + assertPermission(t, m, user, obj, "GET", false) +} + +func TestCheckPermission_StableAcrossRepeatedCalls(t *testing.T) { + const ( + role = "role" + user = "user" + ) + obj := "/api/v1/res" + + m := testManager(t) + mustAddRoleForUser(t, m, user, role) + mustAddPolicy(t, m, role, obj, "GET") + + for i := range 200 { + got, err := m.CheckPermission(user, obj, "GET") + if err != nil { + t.Fatalf("call %d: %v", i, err) + } + if !got { + t.Fatalf("call %d: got deny, want allow", i) + } + } +} + +func TestManagerGetAllPolicies(t *testing.T) { + m := testManager(t) + + mustAddPolicy(t, m, "role-a", "/api/v1/a", "GET") + mustAddPolicy(t, m, "role-a", "/api/v1/b", "POST") + mustAddPolicy(t, m, "role-b", "/api/v1/a", "GET") + + want := map[string]bool{ + "role-a,/api/v1/a,GET": true, + "role-a,/api/v1/b,POST": true, + "role-b,/api/v1/a,GET": true, + } + + got := m.GetAllPolicies() + if len(got) != len(want) { + t.Fatalf("GetAllPolicies: got %d policies, want %d", len(got), len(want)) + } + for _, p := range got { + if !want[strings.Join(p, ",")] { + t.Errorf("GetAllPolicies: unexpected policy %v", p) + } + } +} + +func TestManagerRoleMappingReadback(t *testing.T) { + m := testManager(t) + + mustAddRoleForUser(t, m, "alice", "admin") + mustAddRoleForUser(t, m, "alice", "ops") + mustAddRoleForUser(t, m, "bob", "viewer") + + // casbin 返回角色顺序不稳定(内部 map 迭代),断言前先排序 + roles := m.GetRolesForUser("alice") + sort.Strings(roles) + if got := strings.Join(roles, ","); got != "admin,ops" { + t.Errorf("GetRolesForUser(alice) = %q, want %q", got, "admin,ops") + } + if got := m.GetRolesForUser("nobody"); len(got) != 0 { + t.Errorf("GetRolesForUser(nobody) = %v, want empty", got) + } + + want := map[string]bool{ + "alice,admin": true, + "alice,ops": true, + "bob,viewer": true, + } + got := m.GetAllRoles() + if len(got) != len(want) { + t.Fatalf("GetAllRoles: got %d mappings, want %d", len(got), len(want)) + } + for _, r := range got { + if len(r) != 2 || !want[strings.Join(r, ",")] { + t.Errorf("GetAllRoles: unexpected mapping %v", r) + } + } +} From 349ac2a45cd92f1cfdb40654c1fbfbc02c3cad71 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 21:59:44 +0800 Subject: [PATCH 17/18] feat: add test --- api/middleware/casbin_middleware.go | 2 +- api/middleware/casbin_middleware_test.go | 93 +++++ api/middleware/jwt_auth_middleware_test.go | 192 +++++++++ frontend/src/routeTree.gen.ts | 440 ++++++++++----------- internal/casbin/manager_bench_test.go | 110 ++++++ internal/tokenutil/tokenutil_bench_test.go | 18 + internal/tokenutil/tokenutil_test.go | 212 ++++++++++ usecase/user_usecase.go | 1 - 8 files changed, 846 insertions(+), 222 deletions(-) create mode 100644 api/middleware/casbin_middleware_test.go create mode 100644 api/middleware/jwt_auth_middleware_test.go create mode 100644 internal/casbin/manager_bench_test.go create mode 100644 internal/tokenutil/tokenutil_bench_test.go create mode 100644 internal/tokenutil/tokenutil_test.go diff --git a/api/middleware/casbin_middleware.go b/api/middleware/casbin_middleware.go index 2ad0cfd..acc991a 100644 --- a/api/middleware/casbin_middleware.go +++ b/api/middleware/casbin_middleware.go @@ -35,7 +35,7 @@ func (m *CasbinMiddleware) CheckAPIPermission() gin.HandlerFunc { path := c.Request.URL.Path method := c.Request.Method - fmt.Printf("🔍 user= %s method=%s path=%s\n", userID, method, path) + fmt.Printf("🔍 user=%s method=%s path=%s\n", userID, method, path) // 跳过不需要权限校验的API if m.shouldSkipPermissionCheck(path) { diff --git a/api/middleware/casbin_middleware_test.go b/api/middleware/casbin_middleware_test.go new file mode 100644 index 0000000..5e25806 --- /dev/null +++ b/api/middleware/casbin_middleware_test.go @@ -0,0 +1,93 @@ +package middleware + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + + "shadmin/internal/casbin" + "shadmin/internal/constants" + + "github.com/gin-gonic/gin" +) + +// fakeManager 只实现 CheckPermission:中间件测试只关心网关行为 +// (状态码、userID 提取、跳过清单),权限判定本身由 internal/casbin 的单测覆盖。 +type fakeManager struct { + casbin.Manager // 嵌入真实接口,未触发的方法不调用 + allow bool + err error +} + +func (f fakeManager) CheckPermission(string, string, string) (bool, error) { + return f.allow, f.err +} + +// newCasbinTestRouter 构造三条约目的路由: +// /api/v1/probe 带用户 alice; +// /api/v1/anon 匿名(userID 为空); +// /api/v1/profile 属于 BasicProtectedAPIPaths,应跳过权限校验。 +func newCasbinTestRouter(m casbin.Manager) *gin.Engine { + gin.SetMode(gin.TestMode) + r := gin.New() + + ok := func(c *gin.Context) { c.Status(http.StatusOK) } + withUser := func(userID string) gin.HandlerFunc { + return func(c *gin.Context) { + c.Set(constants.UserID, userID) + c.Next() + } + } + + r.GET("/api/v1/probe", withUser("alice"), NewCasbinMiddleware(m).CheckAPIPermission(), ok) + r.GET("/api/v1/anon", withUser(""), NewCasbinMiddleware(m).CheckAPIPermission(), ok) + r.GET("/api/v1/profile", NewCasbinMiddleware(m).CheckAPIPermission(), ok) + return r +} + +func casbinProbe(t *testing.T, r *gin.Engine, path string) *httptest.ResponseRecorder { + t.Helper() + req := httptest.NewRequest(http.MethodGet, path, nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + return w +} + +func TestCheckAPIPermission_AllowsAuthorizedUser(t *testing.T) { + r := newCasbinTestRouter(fakeManager{allow: true}) + + if w := casbinProbe(t, r, "/api/v1/probe"); w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200", w.Code) + } +} + +func TestCheckAPIPermission_DeniesWithoutPermission(t *testing.T) { + r := newCasbinTestRouter(fakeManager{allow: false}) + + // 带用户但无权限 + if w := casbinProbe(t, r, "/api/v1/probe"); w.Code != http.StatusForbidden { + t.Fatalf("unauthorized user status = %d, want 403", w.Code) + } + // 匿名(userID 为空)不放过 + if w := casbinProbe(t, r, "/api/v1/anon"); w.Code != http.StatusForbidden { + t.Fatalf("anonymous status = %d, want 403", w.Code) + } +} + +// 跳过路径来自 constants.GetAPIPathsToSkipPermissionCheck,用例锁定这份清单仍生效。 +func TestCheckAPIPermission_SkipsBasicProtectedPaths(t *testing.T) { + r := newCasbinTestRouter(fakeManager{allow: false}) + + if w := casbinProbe(t, r, "/api/v1/profile"); w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200 (skip paths must bypass permission check)", w.Code) + } +} + +func TestCheckAPIPermission_Returns500OnManagerError(t *testing.T) { + r := newCasbinTestRouter(fakeManager{err: errors.New("boom")}) + + if w := casbinProbe(t, r, "/api/v1/probe"); w.Code != http.StatusInternalServerError { + t.Fatalf("status = %d, want 500", w.Code) + } +} diff --git a/api/middleware/jwt_auth_middleware_test.go b/api/middleware/jwt_auth_middleware_test.go new file mode 100644 index 0000000..af5c3e4 --- /dev/null +++ b/api/middleware/jwt_auth_middleware_test.go @@ -0,0 +1,192 @@ +package middleware + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + "time" + + "shadmin/domain" + "shadmin/internal/auth" + "shadmin/internal/cacher" + "shadmin/internal/constants" + "shadmin/internal/tokenutil" + + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" +) + +const testSecret = "0123456789abcdef0123456789abcdef" + +func newBlacklist(t *testing.T) auth.JWTBlacklist { + t.Helper() + return auth.NewTokenBlacklist(cacher.NewMemoryCache(cacher.MemoryConfig{CleanupInterval: time.Minute})) +} + +func newProbeRouter(secret string, blacklist auth.JWTBlacklist) *gin.Engine { + gin.SetMode(gin.TestMode) + r := gin.New() + r.GET("/probe", JwtAuthMiddleware(secret, blacklist), func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"user_id": c.GetString(constants.UserID)}) + }) + return r +} + +func probe(t *testing.T, r *gin.Engine, authorization string) *httptest.ResponseRecorder { + t.Helper() + req := httptest.NewRequest(http.MethodGet, "/probe", nil) + if authorization != "" { + req.Header.Set("Authorization", authorization) + } + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + return w +} + +func newToken(t *testing.T) string { + t.Helper() + user := &domain.User{ID: "u-1", Username: "alice", Email: "alice@example.com", Roles: []string{"admin"}} + token, err := tokenutil.CreateAccessToken(user, testSecret, 60) + if err != nil { + t.Fatalf("CreateAccessToken: %v", err) + } + return token +} + +// 合法令牌必须带 jti 透传到下游 +func TestJwtAuthMiddleware_AcceptsValidToken(t *testing.T) { + w := probe(t, newProbeRouter(testSecret, newBlacklist(t)), "Bearer "+newToken(t)) + + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200 (body=%s)", w.Code, w.Body.String()) + } + var got struct { + UserID string `json:"user_id"` + } + if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil { + t.Fatalf("decode body %q: %v", w.Body.String(), err) + } + if got.UserID != "u-1" { + t.Errorf("user_id = %q, want %q", got.UserID, "u-1") + } +} + +// 未配置黑名单时不校验 jti +func TestJwtAuthMiddleware_AcceptsValidTokenWithoutBlacklist(t *testing.T) { + w := probe(t, newProbeRouter(testSecret, nil), "Bearer "+newToken(t)) + + if w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200 (body=%s)", w.Code, w.Body.String()) + } +} + +// 无 jti 的令牌无法吊销,配置了黑名单时必须拒绝 +func TestJwtAuthMiddleware_RejectsTokenWithoutJTI(t *testing.T) { + claims := &domain.JwtCustomClaims{ + ID: "u-1", + Name: "alice", + Email: "alice@example.com", + Issuer: "shadmin", + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), + } + token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(testSecret)) + if err != nil { + t.Fatalf("sign: %v", err) + } + + w := probe(t, newProbeRouter(testSecret, newBlacklist(t)), "Bearer "+token) + + if w.Code != http.StatusUnauthorized { + t.Fatalf("status = %d, want 401", w.Code) + } +} + +func TestJwtAuthMiddleware_RejectsRevokedToken(t *testing.T) { + blacklist := newBlacklist(t) + token := newToken(t) + + claims, err := tokenutil.ParseAccessClaims(token, testSecret) + if err != nil { + t.Fatalf("ParseAccessClaims: %v", err) + } + if err := blacklist.Add(context.Background(), claims.JTI(), time.Now().Add(time.Hour)); err != nil { + t.Fatalf("blacklist.Add: %v", err) + } + + w := probe(t, newProbeRouter(testSecret, blacklist), "Bearer "+token) + + if w.Code != http.StatusUnauthorized { + t.Fatalf("status = %d, want 401", w.Code) + } +} + +// 黑名单必须以 jti 为键。曾因字段遮蔽把用户 ID 误当成 jti, +// 导致写入键与查询键不一致、登出完全失效。 +func TestJwtAuthMiddleware_BlacklistIsKeyedByJTI(t *testing.T) { + blacklist := newBlacklist(t) + token := newToken(t) + + claims, err := tokenutil.ParseAccessClaims(token, testSecret) + if err != nil { + t.Fatalf("ParseAccessClaims: %v", err) + } + if claims.JTI() == claims.ID { + t.Fatalf("jti and user id are both %q; the fixture cannot detect a mix-up", claims.JTI()) + } + + r := newProbeRouter(testSecret, blacklist) + + if err := blacklist.Add(context.Background(), claims.ID, time.Now().Add(time.Hour)); err != nil { + t.Fatalf("blacklist.Add(user id): %v", err) + } + if w := probe(t, r, "Bearer "+token); w.Code != http.StatusOK { + t.Fatalf("status = %d, want 200: blacklisting the user id must not revoke the token", w.Code) + } + + if err := blacklist.Add(context.Background(), claims.JTI(), time.Now().Add(time.Hour)); err != nil { + t.Fatalf("blacklist.Add(jti): %v", err) + } + if w := probe(t, r, "Bearer "+token); w.Code != http.StatusUnauthorized { + t.Fatalf("status = %d, want 401: blacklisting the jti must revoke the token", w.Code) + } +} + +func TestJwtAuthMiddleware_RejectsBadAuthorizationHeader(t *testing.T) { + token := newToken(t) + + cases := []struct { + name string + header string + }{ + {"missing header", ""}, + {"no scheme", token}, + {"wrong scheme", "Basic " + token}, + {"empty token", "Bearer "}, + {"extra segment", "Bearer " + token + " x"}, + } + + r := newProbeRouter(testSecret, newBlacklist(t)) + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if w := probe(t, r, tc.header); w.Code != http.StatusUnauthorized { + t.Fatalf("status = %d, want 401", w.Code) + } + }) + } +} + +func TestJwtAuthMiddleware_RejectsTokenSignedWithAnotherSecret(t *testing.T) { + user := &domain.User{ID: "u-1", Username: "alice"} + token, err := tokenutil.CreateAccessToken(user, "another-secret-another-secret-32", 60) + if err != nil { + t.Fatalf("CreateAccessToken: %v", err) + } + + w := probe(t, newProbeRouter(testSecret, newBlacklist(t)), "Bearer "+token) + + if w.Code != http.StatusUnauthorized { + t.Fatalf("status = %d, want 401", w.Code) + } +} diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index 21cedcc..1a0a2e5 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -10,59 +10,59 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as AuthenticatedRouteRouteImport } from './routes/_authenticated/route' -import { Route as AuthenticatedIndexRouteImport } from './routes/_authenticated/index' -import { Route as errors503RouteImport } from './routes/(errors)/503' -import { Route as errors500RouteImport } from './routes/(errors)/500' -import { Route as errors404RouteImport } from './routes/(errors)/404' -import { Route as errors403RouteImport } from './routes/(errors)/403' -import { Route as errors401RouteImport } from './routes/(errors)/401' -import { Route as authSignUpRouteImport } from './routes/(auth)/sign-up' -import { Route as authSignInRouteImport } from './routes/(auth)/sign-in' -import { Route as authOtpRouteImport } from './routes/(auth)/otp' -import { Route as authOauthCallbackRouteImport } from './routes/(auth)/oauth-callback' import { Route as authForgotPasswordRouteImport } from './routes/(auth)/forgot-password' +import { Route as authOauthCallbackRouteImport } from './routes/(auth)/oauth-callback' +import { Route as authOtpRouteImport } from './routes/(auth)/otp' +import { Route as authSignInRouteImport } from './routes/(auth)/sign-in' +import { Route as authSignUpRouteImport } from './routes/(auth)/sign-up' +import { Route as errors401RouteImport } from './routes/(errors)/401' +import { Route as errors403RouteImport } from './routes/(errors)/403' +import { Route as errors404RouteImport } from './routes/(errors)/404' +import { Route as errors500RouteImport } from './routes/(errors)/500' +import { Route as errors503RouteImport } from './routes/(errors)/503' +import { Route as AuthenticatedIndexRouteImport } from './routes/_authenticated/index' import { Route as AuthenticatedSettingsRouteRouteImport } from './routes/_authenticated/settings/route' -import { Route as AuthenticatedSettingsIndexRouteImport } from './routes/_authenticated/settings/index' +import { Route as AuthenticatedAuthDeviceRouteImport } from './routes/_authenticated/auth/device' +import { Route as AuthenticatedErrorsErrorRouteImport } from './routes/_authenticated/errors/$error' import { Route as AuthenticatedHelpCenterIndexRouteImport } from './routes/_authenticated/help-center/index' -import { Route as AuthenticatedSystemUserRouteImport } from './routes/_authenticated/system/user' -import { Route as AuthenticatedSystemRoleRouteImport } from './routes/_authenticated/system/role' -import { Route as AuthenticatedSystemMenuRouteImport } from './routes/_authenticated/system/menu' -import { Route as AuthenticatedSystemLoginLogsRouteImport } from './routes/_authenticated/system/login-logs' -import { Route as AuthenticatedSystemDictRouteImport } from './routes/_authenticated/system/dict' -import { Route as AuthenticatedSystemDepartmentsRouteImport } from './routes/_authenticated/system/departments' -import { Route as AuthenticatedSystemApiResourcesRouteImport } from './routes/_authenticated/system/api-resources' -import { Route as AuthenticatedSettingsAppearanceRouteImport } from './routes/_authenticated/settings/appearance' +import { Route as AuthenticatedSettingsIndexRouteImport } from './routes/_authenticated/settings/index' import { Route as AuthenticatedSettingsAccountRouteImport } from './routes/_authenticated/settings/account' -import { Route as AuthenticatedErrorsErrorRouteImport } from './routes/_authenticated/errors/$error' -import { Route as AuthenticatedAuthDeviceRouteImport } from './routes/_authenticated/auth/device' +import { Route as AuthenticatedSettingsAppearanceRouteImport } from './routes/_authenticated/settings/appearance' +import { Route as AuthenticatedSystemApiResourcesRouteImport } from './routes/_authenticated/system/api-resources' +import { Route as AuthenticatedSystemDepartmentsRouteImport } from './routes/_authenticated/system/departments' +import { Route as AuthenticatedSystemDictRouteImport } from './routes/_authenticated/system/dict' +import { Route as AuthenticatedSystemLoginLogsRouteImport } from './routes/_authenticated/system/login-logs' +import { Route as AuthenticatedSystemMenuRouteImport } from './routes/_authenticated/system/menu' +import { Route as AuthenticatedSystemRoleRouteImport } from './routes/_authenticated/system/role' +import { Route as AuthenticatedSystemUserRouteImport } from './routes/_authenticated/system/user' const AuthenticatedRouteRoute = AuthenticatedRouteRouteImport.update({ id: '/_authenticated', getParentRoute: () => rootRouteImport, } as any) -const AuthenticatedIndexRoute = AuthenticatedIndexRouteImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedRouteRoute, +const authForgotPasswordRoute = authForgotPasswordRouteImport.update({ + id: '/(auth)/forgot-password', + path: '/forgot-password', + getParentRoute: () => rootRouteImport, } as any) -const errors503Route = errors503RouteImport.update({ - id: '/(errors)/503', - path: '/503', +const authOauthCallbackRoute = authOauthCallbackRouteImport.update({ + id: '/(auth)/oauth-callback', + path: '/oauth-callback', getParentRoute: () => rootRouteImport, } as any) -const errors500Route = errors500RouteImport.update({ - id: '/(errors)/500', - path: '/500', +const authOtpRoute = authOtpRouteImport.update({ + id: '/(auth)/otp', + path: '/otp', getParentRoute: () => rootRouteImport, } as any) -const errors404Route = errors404RouteImport.update({ - id: '/(errors)/404', - path: '/404', +const authSignInRoute = authSignInRouteImport.update({ + id: '/(auth)/sign-in', + path: '/sign-in', getParentRoute: () => rootRouteImport, } as any) -const errors403Route = errors403RouteImport.update({ - id: '/(errors)/403', - path: '/403', +const authSignUpRoute = authSignUpRouteImport.update({ + id: '/(auth)/sign-up', + path: '/sign-up', getParentRoute: () => rootRouteImport, } as any) const errors401Route = errors401RouteImport.update({ @@ -70,30 +70,30 @@ const errors401Route = errors401RouteImport.update({ path: '/401', getParentRoute: () => rootRouteImport, } as any) -const authSignUpRoute = authSignUpRouteImport.update({ - id: '/(auth)/sign-up', - path: '/sign-up', +const errors403Route = errors403RouteImport.update({ + id: '/(errors)/403', + path: '/403', getParentRoute: () => rootRouteImport, } as any) -const authSignInRoute = authSignInRouteImport.update({ - id: '/(auth)/sign-in', - path: '/sign-in', +const errors404Route = errors404RouteImport.update({ + id: '/(errors)/404', + path: '/404', getParentRoute: () => rootRouteImport, } as any) -const authOtpRoute = authOtpRouteImport.update({ - id: '/(auth)/otp', - path: '/otp', +const errors500Route = errors500RouteImport.update({ + id: '/(errors)/500', + path: '/500', getParentRoute: () => rootRouteImport, } as any) -const authOauthCallbackRoute = authOauthCallbackRouteImport.update({ - id: '/(auth)/oauth-callback', - path: '/oauth-callback', +const errors503Route = errors503RouteImport.update({ + id: '/(errors)/503', + path: '/503', getParentRoute: () => rootRouteImport, } as any) -const authForgotPasswordRoute = authForgotPasswordRouteImport.update({ - id: '/(auth)/forgot-password', - path: '/forgot-password', - getParentRoute: () => rootRouteImport, +const AuthenticatedIndexRoute = AuthenticatedIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => AuthenticatedRouteRoute, } as any) const AuthenticatedSettingsRouteRoute = AuthenticatedSettingsRouteRouteImport.update({ @@ -101,11 +101,16 @@ const AuthenticatedSettingsRouteRoute = path: '/settings', getParentRoute: () => AuthenticatedRouteRoute, } as any) -const AuthenticatedSettingsIndexRoute = - AuthenticatedSettingsIndexRouteImport.update({ - id: '/', - path: '/', - getParentRoute: () => AuthenticatedSettingsRouteRoute, +const AuthenticatedAuthDeviceRoute = AuthenticatedAuthDeviceRouteImport.update({ + id: '/auth/device', + path: '/auth/device', + getParentRoute: () => AuthenticatedRouteRoute, +} as any) +const AuthenticatedErrorsErrorRoute = + AuthenticatedErrorsErrorRouteImport.update({ + id: '/errors/$error', + path: '/errors/$error', + getParentRoute: () => AuthenticatedRouteRoute, } as any) const AuthenticatedHelpCenterIndexRoute = AuthenticatedHelpCenterIndexRouteImport.update({ @@ -113,43 +118,17 @@ const AuthenticatedHelpCenterIndexRoute = path: '/help-center/', getParentRoute: () => AuthenticatedRouteRoute, } as any) -const AuthenticatedSystemUserRoute = AuthenticatedSystemUserRouteImport.update({ - id: '/system/user', - path: '/system/user', - getParentRoute: () => AuthenticatedRouteRoute, -} as any) -const AuthenticatedSystemRoleRoute = AuthenticatedSystemRoleRouteImport.update({ - id: '/system/role', - path: '/system/role', - getParentRoute: () => AuthenticatedRouteRoute, -} as any) -const AuthenticatedSystemMenuRoute = AuthenticatedSystemMenuRouteImport.update({ - id: '/system/menu', - path: '/system/menu', - getParentRoute: () => AuthenticatedRouteRoute, -} as any) -const AuthenticatedSystemLoginLogsRoute = - AuthenticatedSystemLoginLogsRouteImport.update({ - id: '/system/login-logs', - path: '/system/login-logs', - getParentRoute: () => AuthenticatedRouteRoute, - } as any) -const AuthenticatedSystemDictRoute = AuthenticatedSystemDictRouteImport.update({ - id: '/system/dict', - path: '/system/dict', - getParentRoute: () => AuthenticatedRouteRoute, -} as any) -const AuthenticatedSystemDepartmentsRoute = - AuthenticatedSystemDepartmentsRouteImport.update({ - id: '/system/departments', - path: '/system/departments', - getParentRoute: () => AuthenticatedRouteRoute, +const AuthenticatedSettingsIndexRoute = + AuthenticatedSettingsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => AuthenticatedSettingsRouteRoute, } as any) -const AuthenticatedSystemApiResourcesRoute = - AuthenticatedSystemApiResourcesRouteImport.update({ - id: '/system/api-resources', - path: '/system/api-resources', - getParentRoute: () => AuthenticatedRouteRoute, +const AuthenticatedSettingsAccountRoute = + AuthenticatedSettingsAccountRouteImport.update({ + id: '/account', + path: '/account', + getParentRoute: () => AuthenticatedSettingsRouteRoute, } as any) const AuthenticatedSettingsAppearanceRoute = AuthenticatedSettingsAppearanceRouteImport.update({ @@ -157,21 +136,42 @@ const AuthenticatedSettingsAppearanceRoute = path: '/appearance', getParentRoute: () => AuthenticatedSettingsRouteRoute, } as any) -const AuthenticatedSettingsAccountRoute = - AuthenticatedSettingsAccountRouteImport.update({ - id: '/account', - path: '/account', - getParentRoute: () => AuthenticatedSettingsRouteRoute, +const AuthenticatedSystemApiResourcesRoute = + AuthenticatedSystemApiResourcesRouteImport.update({ + id: '/system/api-resources', + path: '/system/api-resources', + getParentRoute: () => AuthenticatedRouteRoute, } as any) -const AuthenticatedErrorsErrorRoute = - AuthenticatedErrorsErrorRouteImport.update({ - id: '/errors/$error', - path: '/errors/$error', +const AuthenticatedSystemDepartmentsRoute = + AuthenticatedSystemDepartmentsRouteImport.update({ + id: '/system/departments', + path: '/system/departments', getParentRoute: () => AuthenticatedRouteRoute, } as any) -const AuthenticatedAuthDeviceRoute = AuthenticatedAuthDeviceRouteImport.update({ - id: '/auth/device', - path: '/auth/device', +const AuthenticatedSystemDictRoute = AuthenticatedSystemDictRouteImport.update({ + id: '/system/dict', + path: '/system/dict', + getParentRoute: () => AuthenticatedRouteRoute, +} as any) +const AuthenticatedSystemLoginLogsRoute = + AuthenticatedSystemLoginLogsRouteImport.update({ + id: '/system/login-logs', + path: '/system/login-logs', + getParentRoute: () => AuthenticatedRouteRoute, + } as any) +const AuthenticatedSystemMenuRoute = AuthenticatedSystemMenuRouteImport.update({ + id: '/system/menu', + path: '/system/menu', + getParentRoute: () => AuthenticatedRouteRoute, +} as any) +const AuthenticatedSystemRoleRoute = AuthenticatedSystemRoleRouteImport.update({ + id: '/system/role', + path: '/system/role', + getParentRoute: () => AuthenticatedRouteRoute, +} as any) +const AuthenticatedSystemUserRoute = AuthenticatedSystemUserRouteImport.update({ + id: '/system/user', + path: '/system/user', getParentRoute: () => AuthenticatedRouteRoute, } as any) @@ -364,39 +364,39 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedRouteRouteImport parentRoute: typeof rootRouteImport } - '/_authenticated/': { - id: '/_authenticated/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof AuthenticatedIndexRouteImport - parentRoute: typeof AuthenticatedRouteRoute + '/(auth)/forgot-password': { + id: '/(auth)/forgot-password' + path: '/forgot-password' + fullPath: '/forgot-password' + preLoaderRoute: typeof authForgotPasswordRouteImport + parentRoute: typeof rootRouteImport } - '/(errors)/503': { - id: '/(errors)/503' - path: '/503' - fullPath: '/503' - preLoaderRoute: typeof errors503RouteImport + '/(auth)/oauth-callback': { + id: '/(auth)/oauth-callback' + path: '/oauth-callback' + fullPath: '/oauth-callback' + preLoaderRoute: typeof authOauthCallbackRouteImport parentRoute: typeof rootRouteImport } - '/(errors)/500': { - id: '/(errors)/500' - path: '/500' - fullPath: '/500' - preLoaderRoute: typeof errors500RouteImport + '/(auth)/otp': { + id: '/(auth)/otp' + path: '/otp' + fullPath: '/otp' + preLoaderRoute: typeof authOtpRouteImport parentRoute: typeof rootRouteImport } - '/(errors)/404': { - id: '/(errors)/404' - path: '/404' - fullPath: '/404' - preLoaderRoute: typeof errors404RouteImport + '/(auth)/sign-in': { + id: '/(auth)/sign-in' + path: '/sign-in' + fullPath: '/sign-in' + preLoaderRoute: typeof authSignInRouteImport parentRoute: typeof rootRouteImport } - '/(errors)/403': { - id: '/(errors)/403' - path: '/403' - fullPath: '/403' - preLoaderRoute: typeof errors403RouteImport + '/(auth)/sign-up': { + id: '/(auth)/sign-up' + path: '/sign-up' + fullPath: '/sign-up' + preLoaderRoute: typeof authSignUpRouteImport parentRoute: typeof rootRouteImport } '/(errors)/401': { @@ -406,40 +406,40 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof errors401RouteImport parentRoute: typeof rootRouteImport } - '/(auth)/sign-up': { - id: '/(auth)/sign-up' - path: '/sign-up' - fullPath: '/sign-up' - preLoaderRoute: typeof authSignUpRouteImport + '/(errors)/403': { + id: '/(errors)/403' + path: '/403' + fullPath: '/403' + preLoaderRoute: typeof errors403RouteImport parentRoute: typeof rootRouteImport } - '/(auth)/sign-in': { - id: '/(auth)/sign-in' - path: '/sign-in' - fullPath: '/sign-in' - preLoaderRoute: typeof authSignInRouteImport + '/(errors)/404': { + id: '/(errors)/404' + path: '/404' + fullPath: '/404' + preLoaderRoute: typeof errors404RouteImport parentRoute: typeof rootRouteImport } - '/(auth)/otp': { - id: '/(auth)/otp' - path: '/otp' - fullPath: '/otp' - preLoaderRoute: typeof authOtpRouteImport + '/(errors)/500': { + id: '/(errors)/500' + path: '/500' + fullPath: '/500' + preLoaderRoute: typeof errors500RouteImport parentRoute: typeof rootRouteImport } - '/(auth)/oauth-callback': { - id: '/(auth)/oauth-callback' - path: '/oauth-callback' - fullPath: '/oauth-callback' - preLoaderRoute: typeof authOauthCallbackRouteImport + '/(errors)/503': { + id: '/(errors)/503' + path: '/503' + fullPath: '/503' + preLoaderRoute: typeof errors503RouteImport parentRoute: typeof rootRouteImport } - '/(auth)/forgot-password': { - id: '/(auth)/forgot-password' - path: '/forgot-password' - fullPath: '/forgot-password' - preLoaderRoute: typeof authForgotPasswordRouteImport - parentRoute: typeof rootRouteImport + '/_authenticated/': { + id: '/_authenticated/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof AuthenticatedIndexRouteImport + parentRoute: typeof AuthenticatedRouteRoute } '/_authenticated/settings': { id: '/_authenticated/settings' @@ -448,12 +448,19 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedSettingsRouteRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/settings/': { - id: '/_authenticated/settings/' - path: '/' - fullPath: '/settings/' - preLoaderRoute: typeof AuthenticatedSettingsIndexRouteImport - parentRoute: typeof AuthenticatedSettingsRouteRoute + '/_authenticated/auth/device': { + id: '/_authenticated/auth/device' + path: '/auth/device' + fullPath: '/auth/device' + preLoaderRoute: typeof AuthenticatedAuthDeviceRouteImport + parentRoute: typeof AuthenticatedRouteRoute + } + '/_authenticated/errors/$error': { + id: '/_authenticated/errors/$error' + path: '/errors/$error' + fullPath: '/errors/$error' + preLoaderRoute: typeof AuthenticatedErrorsErrorRouteImport + parentRoute: typeof AuthenticatedRouteRoute } '/_authenticated/help-center/': { id: '/_authenticated/help-center/' @@ -462,32 +469,39 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedHelpCenterIndexRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/system/user': { - id: '/_authenticated/system/user' - path: '/system/user' - fullPath: '/system/user' - preLoaderRoute: typeof AuthenticatedSystemUserRouteImport - parentRoute: typeof AuthenticatedRouteRoute + '/_authenticated/settings/': { + id: '/_authenticated/settings/' + path: '/' + fullPath: '/settings/' + preLoaderRoute: typeof AuthenticatedSettingsIndexRouteImport + parentRoute: typeof AuthenticatedSettingsRouteRoute } - '/_authenticated/system/role': { - id: '/_authenticated/system/role' - path: '/system/role' - fullPath: '/system/role' - preLoaderRoute: typeof AuthenticatedSystemRoleRouteImport - parentRoute: typeof AuthenticatedRouteRoute + '/_authenticated/settings/account': { + id: '/_authenticated/settings/account' + path: '/account' + fullPath: '/settings/account' + preLoaderRoute: typeof AuthenticatedSettingsAccountRouteImport + parentRoute: typeof AuthenticatedSettingsRouteRoute } - '/_authenticated/system/menu': { - id: '/_authenticated/system/menu' - path: '/system/menu' - fullPath: '/system/menu' - preLoaderRoute: typeof AuthenticatedSystemMenuRouteImport + '/_authenticated/settings/appearance': { + id: '/_authenticated/settings/appearance' + path: '/appearance' + fullPath: '/settings/appearance' + preLoaderRoute: typeof AuthenticatedSettingsAppearanceRouteImport + parentRoute: typeof AuthenticatedSettingsRouteRoute + } + '/_authenticated/system/api-resources': { + id: '/_authenticated/system/api-resources' + path: '/system/api-resources' + fullPath: '/system/api-resources' + preLoaderRoute: typeof AuthenticatedSystemApiResourcesRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/system/login-logs': { - id: '/_authenticated/system/login-logs' - path: '/system/login-logs' - fullPath: '/system/login-logs' - preLoaderRoute: typeof AuthenticatedSystemLoginLogsRouteImport + '/_authenticated/system/departments': { + id: '/_authenticated/system/departments' + path: '/system/departments' + fullPath: '/system/departments' + preLoaderRoute: typeof AuthenticatedSystemDepartmentsRouteImport parentRoute: typeof AuthenticatedRouteRoute } '/_authenticated/system/dict': { @@ -497,46 +511,32 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedSystemDictRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/system/departments': { - id: '/_authenticated/system/departments' - path: '/system/departments' - fullPath: '/system/departments' - preLoaderRoute: typeof AuthenticatedSystemDepartmentsRouteImport + '/_authenticated/system/login-logs': { + id: '/_authenticated/system/login-logs' + path: '/system/login-logs' + fullPath: '/system/login-logs' + preLoaderRoute: typeof AuthenticatedSystemLoginLogsRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/system/api-resources': { - id: '/_authenticated/system/api-resources' - path: '/system/api-resources' - fullPath: '/system/api-resources' - preLoaderRoute: typeof AuthenticatedSystemApiResourcesRouteImport + '/_authenticated/system/menu': { + id: '/_authenticated/system/menu' + path: '/system/menu' + fullPath: '/system/menu' + preLoaderRoute: typeof AuthenticatedSystemMenuRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/settings/appearance': { - id: '/_authenticated/settings/appearance' - path: '/appearance' - fullPath: '/settings/appearance' - preLoaderRoute: typeof AuthenticatedSettingsAppearanceRouteImport - parentRoute: typeof AuthenticatedSettingsRouteRoute - } - '/_authenticated/settings/account': { - id: '/_authenticated/settings/account' - path: '/account' - fullPath: '/settings/account' - preLoaderRoute: typeof AuthenticatedSettingsAccountRouteImport - parentRoute: typeof AuthenticatedSettingsRouteRoute - } - '/_authenticated/errors/$error': { - id: '/_authenticated/errors/$error' - path: '/errors/$error' - fullPath: '/errors/$error' - preLoaderRoute: typeof AuthenticatedErrorsErrorRouteImport + '/_authenticated/system/role': { + id: '/_authenticated/system/role' + path: '/system/role' + fullPath: '/system/role' + preLoaderRoute: typeof AuthenticatedSystemRoleRouteImport parentRoute: typeof AuthenticatedRouteRoute } - '/_authenticated/auth/device': { - id: '/_authenticated/auth/device' - path: '/auth/device' - fullPath: '/auth/device' - preLoaderRoute: typeof AuthenticatedAuthDeviceRouteImport + '/_authenticated/system/user': { + id: '/_authenticated/system/user' + path: '/system/user' + fullPath: '/system/user' + preLoaderRoute: typeof AuthenticatedSystemUserRouteImport parentRoute: typeof AuthenticatedRouteRoute } } diff --git a/internal/casbin/manager_bench_test.go b/internal/casbin/manager_bench_test.go new file mode 100644 index 0000000..a464501 --- /dev/null +++ b/internal/casbin/manager_bench_test.go @@ -0,0 +1,110 @@ +package casbin + +import ( + "fmt" + "testing" + + casbinlog "github.com/casbin/casbin/v3/log" +) + +// silentLogger 抑制 casbin 的 deny 告警日志,避免 benchmark 输出刷屏。 +// 只用在本文件;单测保持生产 logger 不动。 +type silentLogger struct{} + +func (silentLogger) SetEventTypes([]casbinlog.EventType) error { return nil } +func (silentLogger) OnBeforeEvent(*casbinlog.LogEntry) error { return nil } +func (silentLogger) OnAfterEvent(*casbinlog.LogEntry) error { return nil } +func (silentLogger) SetLogCallback(func(*casbinlog.LogEntry) error) error { return nil } + +// 模拟中等规模的 RBAC 策略集:8 个角色 × 120 个接口 × 2 个方法。 +var benchRoles = []string{"bench-admin", "bench-ops", "bench-auditor", "bench-viewer", "bench-developer", "bench-support", "bench-finance", "bench-guest"} + +const benchUser = "bench-user" +const benchObj = "/api/v1/system/bench-res119/:id" + +// setupBenchPolicy 为每个 benchmark 构建独立的策略集并预热一次, +// 排除首查的表达式编译开销。 +func setupBenchPolicy(tb testing.TB) Manager { + tb.Helper() + m := testManager(tb) + + for _, role := range benchRoles { + for i := range 120 { + obj := fmt.Sprintf("/api/v1/system/bench-res%03d/:id", i) + if _, err := m.AddPolicy(role, obj, "GET"); err != nil { + tb.Fatalf("AddPolicy: %v", err) + } + if _, err := m.AddPolicy(role, obj, "POST"); err != nil { + tb.Fatalf("AddPolicy: %v", err) + } + } + } + if _, err := m.AddPolicy("bench-role-wild", "*", "*"); err != nil { + tb.Fatalf("AddPolicy: %v", err) + } + if _, err := m.AddRoleForUser(benchUser, "bench-admin"); err != nil { + tb.Fatalf("AddRoleForUser: %v", err) + } + if _, err := m.AddRoleForUser(benchUser, "bench-role-wild"); err != nil { + tb.Fatalf("AddRoleForUser: %v", err) + } + + if allowed, err := m.CheckPermission(benchUser, benchObj, "GET"); err != nil || !allowed { + tb.Fatalf("warmup CheckPermission: allowed=%v err=%v", allowed, err) + } + return m +} + +func BenchmarkCheckPermission_AllowAssignedRole(b *testing.B) { + m := setupBenchPolicy(b) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + allowed, err := m.CheckPermission(benchUser, benchObj, "GET") + if err != nil { + b.Fatalf("err=%v", err) + } + if !allowed { + b.Fatal("allowed=false, want true") + } + } +} + +func BenchmarkCheckPermission_AllowAssignedRoleParallel(b *testing.B) { + m := setupBenchPolicy(b) + b.ReportAllocs() + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + allowed, err := m.CheckPermission(benchUser, benchObj, "GET") + if err != nil { + b.Errorf("err=%v", err) + return + } + if !allowed { + b.Errorf("allowed=false, want true") + return + } + } + }) +} + +// 直接调用 Enforce 绕开 CheckPermission 的角色查询,且该 subject 无任何策略, +// 必须扫完整个策略集才能得出 deny —— 这是权限结果缓存要消除的开销。 +func BenchmarkEnforce_DenyNoMatchingSubject(b *testing.B) { + m := setupBenchPolicy(b) + e := m.GetEnforcer() + e.SetLogger(silentLogger{}) // deny 路径每迭代打一条告警日志,静默后才可比 + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + allowed, err := e.Enforce("bench-user-without-any-policy", benchObj, "GET") + if err != nil { + b.Fatal(err) + } + if allowed { + b.Fatal("expected deny") + } + } +} diff --git a/internal/tokenutil/tokenutil_bench_test.go b/internal/tokenutil/tokenutil_bench_test.go new file mode 100644 index 0000000..ff6503f --- /dev/null +++ b/internal/tokenutil/tokenutil_bench_test.go @@ -0,0 +1,18 @@ +package tokenutil + +import "testing" + +func BenchmarkParseAccessClaims(b *testing.B) { + token, err := CreateAccessToken(newTestUser(), testSecret, 60) + if err != nil { + b.Fatalf("CreateAccessToken: %v", err) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := ParseAccessClaims(token, testSecret); err != nil { + b.Fatal(err) + } + } +} diff --git a/internal/tokenutil/tokenutil_test.go b/internal/tokenutil/tokenutil_test.go new file mode 100644 index 0000000..5a5a9e9 --- /dev/null +++ b/internal/tokenutil/tokenutil_test.go @@ -0,0 +1,212 @@ +package tokenutil + +import ( + "strings" + "testing" + "time" + + "shadmin/domain" + + "github.com/golang-jwt/jwt/v5" +) + +const ( + testSecret = "0123456789abcdef0123456789abcdef" + otherSecret = "ffffffffffffffffffffffffffffffff" +) + +func newTestUser() *domain.User { + return &domain.User{ + ID: "9m4e2mr0ui3e8a215n4g", + Username: "alice", + Email: "alice@example.com", + IsAdmin: true, + Roles: []string{"admin", "ops"}, + } +} + +func TestParseAccessClaims_AllFields(t *testing.T) { + user := newTestUser() + token, err := CreateAccessToken(user, testSecret, 60) + if err != nil { + t.Fatalf("CreateAccessToken: %v", err) + } + + claims, err := ParseAccessClaims(token, testSecret) + if err != nil { + t.Fatalf("ParseAccessClaims: %v", err) + } + + if claims.ID != user.ID { + t.Errorf("ID = %q, want %q", claims.ID, user.ID) + } + if claims.JTI() == claims.ID { + t.Error("JTI() returns the user id; the embedded RegisteredClaims.ID is shadowed") + } + if claims.Name != user.Username { + t.Errorf("Name = %q, want %q", claims.Name, user.Username) + } + if claims.Email != user.Email { + t.Errorf("Email = %q, want %q", claims.Email, user.Email) + } + if !claims.IsAdmin { + t.Error("IsAdmin = false, want true") + } + if strings.Join(claims.Roles, ",") != strings.Join(user.Roles, ",") { + t.Errorf("Roles = %v, want %v", claims.Roles, user.Roles) + } + if want := "shadmin:" + user.ID; claims.Subject != want { + t.Errorf("Subject = %q, want %q", claims.Subject, want) + } + if claims.Issuer != "shadmin" { + t.Errorf("Issuer = %q, want %q", claims.Issuer, "shadmin") + } + // jti 是登出黑名单的键,必须存在且不能等同于用户 ID + if claims.JTI() == "" { + t.Error("jti is empty, but the logout blacklist depends on it") + } + if claims.ExpiresAt == nil || !claims.ExpiresAt.After(time.Now()) { + t.Errorf("ExpiresAt = %v, want a future time", claims.ExpiresAt) + } +} + +func TestParseRefreshClaims_AllFields(t *testing.T) { + user := newTestUser() + token, err := CreateRefreshToken(user, testSecret, 60) + if err != nil { + t.Fatalf("CreateRefreshToken: %v", err) + } + + claims, err := ParseRefreshClaims(token, testSecret) + if err != nil { + t.Fatalf("ParseRefreshClaims: %v", err) + } + + if claims.ID != user.ID { + t.Errorf("ID = %q, want %q", claims.ID, user.ID) + } + if claims.JTI() == "" { + t.Error("jti is empty, but the logout blacklist depends on it") + } + if claims.JTI() == claims.ID { + t.Error("JTI() returns the user id; the embedded RegisteredClaims.ID is shadowed") + } + if claims.ExpiresAt == nil || !claims.ExpiresAt.After(time.Now()) { + t.Errorf("ExpiresAt = %v, want a future time", claims.ExpiresAt) + } +} + +func TestParseClaims_RejectsInvalidTokens(t *testing.T) { + valid, err := CreateAccessToken(newTestUser(), testSecret, 60) + if err != nil { + t.Fatalf("CreateAccessToken: %v", err) + } + expired, err := CreateAccessToken(newTestUser(), testSecret, -1) + if err != nil { + t.Fatalf("CreateAccessToken(expired): %v", err) + } + + parts := strings.Split(valid, ".") + if len(parts) != 3 { + t.Fatalf("unexpected token format with %d parts", len(parts)) + } + tampered := parts[0] + "." + parts[1] + "." + strings.Repeat("A", len(parts[2])) + + // alg=none 伪造令牌(算法混淆攻击) + noneToken, err := jwt.NewWithClaims(jwt.SigningMethodNone, &domain.JwtCustomClaims{ + ID: "attacker", + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), + }).SignedString(jwt.UnsafeAllowNoneSignatureType) + if err != nil { + t.Fatalf("build alg=none token: %v", err) + } + + cases := []struct { + name string + token string + secret string + }{ + {"wrong secret", valid, otherSecret}, + {"expired", expired, testSecret}, + {"tampered signature", tampered, testSecret}, + {"alg=none", noneToken, testSecret}, + {"garbage", "not-a-jwt", testSecret}, + {"empty", "", testSecret}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if _, err := ParseAccessClaims(tc.token, tc.secret); err == nil { + t.Fatal("ParseAccessClaims returned nil error, want rejection") + } + if _, err := ParseRefreshClaims(tc.token, tc.secret); err == nil { + t.Fatal("ParseRefreshClaims returned nil error, want rejection") + } + }) + } +} + +// 签发端只用 HS256,因此三个解析入口都只接受 HS256。 +func TestParseClaims_OnlyAcceptsHS256(t *testing.T) { + claims := &domain.JwtCustomClaims{ + ID: "u-1", + Name: "alice", + Email: "alice@example.com", + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), + ID: "jti-hmac", + }, + } + + raw, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(testSecret)) + if err != nil { + t.Fatalf("sign with HS256: %v", err) + } + if _, err := ParseAccessClaims(raw, testSecret); err != nil { + t.Fatalf("ParseAccessClaims rejected HS256: %v", err) + } + if _, _, ok := ExtractJTIAndExpiry(raw, testSecret); !ok { + t.Fatal("ExtractJTIAndExpiry rejected HS256") + } + + for _, method := range []jwt.SigningMethod{jwt.SigningMethodHS384, jwt.SigningMethodHS512} { + t.Run(method.Alg(), func(t *testing.T) { + raw, err := jwt.NewWithClaims(method, claims).SignedString([]byte(testSecret)) + if err != nil { + t.Fatalf("sign with %s: %v", method.Alg(), err) + } + if _, err := ParseAccessClaims(raw, testSecret); err == nil { + t.Fatalf("ParseAccessClaims accepted %s, want rejection", method.Alg()) + } + if _, err := ParseRefreshClaims(raw, testSecret); err == nil { + t.Fatalf("ParseRefreshClaims accepted %s, want rejection", method.Alg()) + } + if _, _, ok := ExtractJTIAndExpiry(raw, testSecret); ok { + t.Fatalf("ExtractJTIAndExpiry accepted %s, want rejection", method.Alg()) + } + }) + } +} + +func TestExtractJTIAndExpiry(t *testing.T) { + user := newTestUser() + token, err := CreateRefreshToken(user, testSecret, 60) + if err != nil { + t.Fatalf("CreateRefreshToken: %v", err) + } + + jti, exp, ok := ExtractJTIAndExpiry(token, testSecret) + if !ok { + t.Fatal("ok = false, want true") + } + if jti == "" { + t.Error("jti is empty, but the logout blacklist depends on it") + } + if exp.Before(time.Now()) { + t.Errorf("exp = %v, want a future time", exp) + } + + if _, _, ok := ExtractJTIAndExpiry(token, otherSecret); ok { + t.Error("ok = true for a token signed with another secret, want false") + } +} diff --git a/usecase/user_usecase.go b/usecase/user_usecase.go index 70ce630..0d09e37 100644 --- a/usecase/user_usecase.go +++ b/usecase/user_usecase.go @@ -273,7 +273,6 @@ func (uu *userUsecase) GetUserRoles(c context.Context, userID string) ([]string, return nil, err } - log.Printf("DEBUG: GetUserRoles - userID: %s, roles: %v", userID, roleIDs) return roleIDs, nil } From ee4468846b021afb8a0ab814e0434b6e8ff49768 Mon Sep 17 00:00:00 2001 From: ahaodev <52927295@qq.com> Date: Fri, 11 Sep 2026 22:04:21 +0800 Subject: [PATCH 18/18] fix: code style --- frontend/src/constants/user-source.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/constants/user-source.ts b/frontend/src/constants/user-source.ts index 271f005..3850794 100644 --- a/frontend/src/constants/user-source.ts +++ b/frontend/src/constants/user-source.ts @@ -1,4 +1,3 @@ - export const USER_SOURCE_LOCAL = 'shadmin' const USER_SOURCE_LABELS: Record = {