Compare commits

..

9 Commits

Author SHA1 Message Date
Amir Raminfar 463fea4634 chore: release v9.0.3 2026-01-26 07:54:41 -08:00
MirzaSamadAhmedBaig 58caca2d68 fix: Avoid fatal on invalid container filters in auth (#4379)
Signed-off-by: Mirza-Samad-Ahmed-Baig <Mirzasamadahmedbaig@gmail.com>
2026-01-26 07:50:37 -08:00
Amir Raminfar 620e59aa24 fix: fixes incorrect user scope for agent.find 2026-01-25 15:03:38 -08:00
Amir Raminfar 8599b602dc chore: release v9.0.2 2026-01-19 10:05:41 -08:00
Amir Raminfar 4b3e44fcdc fix: fixes cpu limit not working correctly (#4356) 2026-01-18 06:12:40 -08:00
Amir Raminfar 51fce48137 feat: shows net stats on mobile (#4357) 2026-01-17 16:17:23 +00:00
Amir Raminfar c1432c33a2 chore: updates deps 2026-01-16 06:53:21 -08:00
renovate[bot] 22d659f509 fix(deps): update dependency unplugin-auto-import to v21 (#4352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 06:52:26 -08:00
renovate[bot] 9c529af633 fix(deps): update all non-major dependencies (#4351)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 14:48:07 +00:00
23 changed files with 331 additions and 976 deletions
+5 -5
View File
@@ -14,12 +14,12 @@ jobs:
- uses: actions/setup-node@v6
name: Install Node
with:
node-version: 24.12.0
node-version: 24.13.0
- run: corepack enable
- run: pnpm --version
- uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
@@ -33,7 +33,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: 1.25.5
go-version: 1.25.6
check-latest: true
- name: Checkout code
uses: actions/checkout@v6
@@ -56,12 +56,12 @@ jobs:
- uses: actions/setup-node@v6
name: Install Node
with:
node-version: 24.12.0
node-version: 24.13.0
- run: corepack enable
- run: pnpm --version
- uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: pnpm # or pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v5
+7 -7
View File
@@ -17,12 +17,12 @@ jobs:
- uses: actions/setup-node@v6
name: Install Node
with:
node-version: 24.12.0
node-version: 24.13.0
- run: corepack enable
- run: pnpm --version
- uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
@@ -40,7 +40,7 @@ jobs:
- run: pnpm --version
- uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
@@ -54,7 +54,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: "1.25.5"
go-version: "1.25.6"
check-latest: true
- name: Checkout code
uses: actions/checkout@v6
@@ -77,7 +77,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: "1.25.5"
go-version: "1.25.6"
check-latest: true
- name: Generate dependencies
run: make fake_assets shared_key.pem shared_cert.pem
@@ -96,12 +96,12 @@ jobs:
- uses: actions/setup-node@v6
name: Install Node
with:
node-version: 24.12.0
node-version: 24.13.0
- run: corepack enable
- run: pnpm --version
- uses: actions/setup-node@v6
with:
node-version: 24.12.0
node-version: 24.13.0
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
+1 -1
View File
@@ -1,5 +1,5 @@
# Build assets
FROM --platform=$BUILDPLATFORM node:24.12.0-alpine AS node
FROM --platform=$BUILDPLATFORM node:24.13.0-alpine AS node
RUN corepack enable
@@ -1,6 +1,8 @@
<template>
<div class="flex gap-1 md:gap-4">
<div class="grid min-w-15 grid-cols-[auto_1fr] items-center gap-0.5 text-xs leading-none max-md:hidden">
<div
class="grid min-w-15 grid-cols-[auto_1fr_auto_1fr] items-center gap-0.5 text-xs leading-none md:grid-cols-[auto_1fr]"
>
<PhArrowUp class="text-primary" />
<span class="tabular-nums">{{ formatBytes(networkRate.tx, { short: true, decimals: 1 }) }}/s</span>
<PhArrowDown class="text-secondary" />
@@ -115,7 +117,7 @@ const limits = computed(() => {
totalCpu += hostTotalCpu;
} else {
// All containers have limits, sum them up (capped at host total)
const sumCpu = hostContainers.reduce((sum, c) => sum + 1, 0);
const sumCpu = hostContainers.reduce((sum, c) => sum + (c.cpuLimit || 0), 0);
totalCpu += Math.min(sumCpu, hostTotalCpu);
}
+8 -9
View File
@@ -17,24 +17,24 @@ require (
github.com/spf13/afero v1.15.0
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.11.1
golang.org/x/net v0.47.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.40.0 // indirect
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/PuerkitoBio/goquery v1.11.0
github.com/andybalholm/brotli v1.2.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/chi/v5 v5.2.4
github.com/go-chi/jwtauth/v5 v5.3.3
github.com/go-faker/faker/v4 v4.7.0
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/puzpuzpuz/xsync/v4 v4.2.0
github.com/puzpuzpuz/xsync/v4 v4.3.0
github.com/rs/zerolog v1.34.0
github.com/samber/lo v1.52.0
github.com/wk8/go-ordered-map/v2 v2.1.8
github.com/yuin/goldmark v1.7.16
golang.org/x/crypto v0.46.0
golang.org/x/crypto v0.47.0
golang.org/x/sync v0.19.0
google.golang.org/grpc v1.78.0
google.golang.org/protobuf v1.36.11
@@ -57,7 +57,6 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/expr-lang/expr v1.17.7 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
@@ -103,8 +102,8 @@ require (
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/term v0.38.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.10.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
@@ -120,4 +119,4 @@ require (
sigs.k8s.io/yaml v1.6.0 // indirect
)
go 1.25.5
go 1.25.6
+14 -2
View File
@@ -78,8 +78,6 @@ github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtz
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8=
github.com/expr-lang/expr v1.17.7/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
@@ -92,6 +90,8 @@ 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.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/jwtauth/v5 v5.3.3 h1:50Uzmacu35/ZP9ER2Ht6SazwPsnLQ9LRJy6zTZJpHEo=
github.com/go-chi/jwtauth/v5 v5.3.3/go.mod h1:O4QvPRuZLZghl9WvfVaON+ARfGzpD2PBX/QY5vUz7aQ=
github.com/go-faker/faker/v4 v4.6.0 h1:6aOPzNptRiDwD14HuAnEtlTa+D1IfFuEHO8+vEFwjTs=
@@ -225,6 +225,8 @@ github.com/puzpuzpuz/xsync/v4 v4.1.0 h1:x9eHRl4QhZFIPJ17yl4KKW9xLyVWbb3/Yq4SXpjF
github.com/puzpuzpuz/xsync/v4 v4.1.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
github.com/puzpuzpuz/xsync/v4 v4.2.0 h1:dlxm77dZj2c3rxq0/XNvvUKISAmovoXF4a4qM6Wvkr0=
github.com/puzpuzpuz/xsync/v4 v4.2.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
github.com/puzpuzpuz/xsync/v4 v4.3.0 h1:w/bWkEJdYuRNYhHn5eXnIT8LzDM1O629X1I9MJSkD7Q=
github.com/puzpuzpuz/xsync/v4 v4.3.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
@@ -368,6 +370,8 @@ golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -402,6 +406,8 @@ golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
@@ -467,6 +473,8 @@ golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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=
@@ -492,6 +500,8 @@ golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -519,6 +529,8 @@ golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+11 -2
View File
@@ -274,8 +274,17 @@ func (c *Client) StreamNewContainers(ctx context.Context, containers chan<- cont
}
}
func (c *Client) FindContainer(ctx context.Context, containerID string) (container.Container, error) {
response, err := c.client.FindContainer(ctx, &pb.FindContainerRequest{ContainerId: containerID})
func (c *Client) FindContainer(ctx context.Context, containerID string, labels container.ContainerLabels) (container.Container, error) {
in := &pb.FindContainerRequest{ContainerId: containerID}
if labels != nil {
in.Filter = make(map[string]*pb.RepeatedString)
for k, v := range labels {
in.Filter[k] = &pb.RepeatedString{Values: v}
}
}
response, err := c.client.FindContainer(ctx, in)
if err != nil {
return container.Container{}, err
}
+1 -1
View File
@@ -138,7 +138,7 @@ func TestFindContainer(t *testing.T) {
t.Fatal(err)
}
c, _ := rpc.FindContainer(context.Background(), "123456")
c, _ := rpc.FindContainer(context.Background(), "123456", container.ContainerLabels{})
assert.Equal(t, wantedContainer, c)
}
+3 -1
View File
@@ -46,7 +46,9 @@ func (p *proxyAuthContext) AuthMiddleware(next http.Handler) http.Handler {
if r.Header.Get(p.headerUser) != "" {
containerFilter, err := container.ParseContainerFilter(r.Header.Get(p.headerFilter))
if err != nil {
log.Fatal().Str("filter", r.Header.Get(p.headerFilter)).Msg("Failed to parse container filter")
log.Warn().Err(err).Str("filter", r.Header.Get(p.headerFilter)).Msg("Failed to parse container filter")
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
userRoles := All
if strings.TrimSpace(r.Header.Get(p.headerRoles)) != "" {
+56
View File
@@ -0,0 +1,56 @@
package auth
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/jwtauth/v5"
"github.com/stretchr/testify/require"
)
func TestForwardProxyAuthRejectsInvalidFilter(t *testing.T) {
auth := NewForwardProxyAuth("Remote-User", "Remote-Email", "Remote-Name", "Remote-Filter", "Remote-Roles")
called := false
handler := auth.AuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
w.WriteHeader(http.StatusOK)
}))
req := httptest.NewRequest(http.MethodGet, "/", nil)
req.Header.Set("Remote-User", "alice")
req.Header.Set("Remote-Filter", "invalid-filter")
resp := httptest.NewRecorder()
handler.ServeHTTP(resp, req)
require.Equal(t, http.StatusBadRequest, resp.Code)
require.False(t, called)
}
func TestUserFromContextInvalidFilterReturnsNil(t *testing.T) {
tokenAuth := jwtauth.New("HS256", []byte("secret"), nil)
_, tokenString, err := tokenAuth.Encode(map[string]interface{}{
"username": "alice",
"email": "alice@example.com",
"name": "Alice",
"filter": "invalid-filter",
})
require.NoError(t, err)
handler := jwtauth.Verifier(tokenAuth)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if UserFromContext(r.Context()) == nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
}))
req := httptest.NewRequest(http.MethodGet, "/", nil)
req.Header.Set("Authorization", "Bearer "+tokenString)
resp := httptest.NewRecorder()
handler.ServeHTTP(resp, req)
require.Equal(t, http.StatusUnauthorized, resp.Code)
}
+2 -1
View File
@@ -212,7 +212,8 @@ func UserFromContext(ctx context.Context) *User {
if filter, ok := claims["filter"].(string); ok {
containerFilter, err = container.ParseContainerFilter(filter)
if err != nil {
log.Fatal().Err(err).Str("filter", filter).Msg("Failed to parse container filter")
log.Warn().Err(err).Str("filter", filter).Msg("Failed to parse container filter")
return nil
}
}
roles := None
-325
View File
@@ -1,325 +0,0 @@
package notification
import (
"context"
"fmt"
"sync"
"time"
"github.com/amir20/dozzle/internal/container"
container_support "github.com/amir20/dozzle/internal/support/container"
"github.com/expr-lang/expr"
"github.com/expr-lang/expr/vm"
"github.com/rs/zerolog/log"
)
// Manager handles notification subscriptions and matching
type Manager struct {
subscriptions []*compiledSubscription
mu sync.RWMutex
activeStreams map[string]*activeStream // containerID -> stream info
containerCache map[string]Container // containerID -> notification.Container
containerService ContainerService
dispatcher Dispatcher
}
// activeStream tracks a single log stream and all subscriptions watching it
type activeStream struct {
container Container // notification.Container
subscriptions []*compiledSubscription // All subscriptions watching this container
cancel context.CancelFunc // Cancel function for the stream
}
// compiledSubscription wraps a Subscription with compiled expr programs
type compiledSubscription struct {
subscription *Subscription
containerProgram *vm.Program // Always non-nil
logProgram *vm.Program // Always non-nil
}
// ContainerService provides access to containers and log streaming
type ContainerService interface {
ListAllContainers(labels container.ContainerLabels) ([]container.Container, []error)
FindContainer(host, id string, labels container.ContainerLabels) (*container_support.ContainerService, error)
SubscribeContainersStarted(ctx context.Context, containers chan<- container.Container, filter container_support.ContainerFilter)
}
// NewManager creates a new notification manager
func NewManager(containerService ContainerService, dispatcher Dispatcher) *Manager {
return &Manager{
subscriptions: make([]*compiledSubscription, 0),
activeStreams: make(map[string]*activeStream),
containerCache: make(map[string]Container),
containerService: containerService,
dispatcher: dispatcher,
}
}
// LoadSubscriptions loads and compiles multiple subscriptions (replaces existing)
func (m *Manager) LoadSubscriptions(subs []*Subscription) error {
m.mu.Lock()
m.subscriptions = make([]*compiledSubscription, 0, len(subs))
m.mu.Unlock()
for _, sub := range subs {
if err := m.AddSubscription(sub); err != nil {
return err
}
}
log.Info().Int("count", len(subs)).Msg("loaded notification subscriptions")
return nil
}
// AddSubscription adds a single subscription
func (m *Manager) AddSubscription(sub *Subscription) error {
cs, err := m.compileSubscription(sub)
if err != nil {
return err
}
m.mu.Lock()
m.subscriptions = append(m.subscriptions, cs)
m.mu.Unlock()
log.Info().Str("subscription", sub.Name).Msg("added notification subscription")
return nil
}
// compileSubscription compiles expr programs for a subscription
func (m *Manager) compileSubscription(sub *Subscription) (*compiledSubscription, error) {
if sub.ContainerFilter == "" {
return nil, fmt.Errorf("container_filter is required for subscription %q", sub.Name)
}
if sub.LogFilter == "" {
return nil, fmt.Errorf("log_filter is required for subscription %q", sub.Name)
}
cs := &compiledSubscription{
subscription: sub,
}
// Compile container filter (required)
containerProgram, err := expr.Compile(sub.ContainerFilter, expr.Env(Container{}))
if err != nil {
log.Error().Err(err).Str("subscription", sub.Name).Msg("failed to compile container filter")
return nil, fmt.Errorf("failed to compile container_filter for %q: %w", sub.Name, err)
}
cs.containerProgram = containerProgram
// Compile log filter (required)
logProgram, err := expr.Compile(sub.LogFilter, expr.Env(Log{}))
if err != nil {
log.Error().Err(err).Str("subscription", sub.Name).Msg("failed to compile log filter")
return nil, fmt.Errorf("failed to compile log_filter for %q: %w", sub.Name, err)
}
cs.logProgram = logProgram
return cs, nil
}
// Start begins monitoring containers and streaming logs for matching subscriptions
// Only starts if there are subscriptions configured
func (m *Manager) Start(ctx context.Context) error {
m.mu.RLock()
hasSubscriptions := len(m.subscriptions) > 0
m.mu.RUnlock()
if !hasSubscriptions {
log.Debug().Msg("no subscriptions configured, skipping notification manager start")
return nil
}
// Subscribe to new containers that match our filters
newContainers := make(chan container.Container)
m.containerService.SubscribeContainersStarted(ctx, newContainers, func(c *container.Container) bool {
matchingSubs := m.getMatchingSubscriptions(c)
return len(matchingSubs) > 0
})
// Handle new containers in background
go func() {
for c := range newContainers {
m.startContainerStream(ctx, &c)
}
}()
// Get all existing containers and start streaming matching ones
containers, errs := m.containerService.ListAllContainers(nil)
for _, err := range errs {
log.Warn().Err(err).Msg("error listing containers for notifications")
}
// Check each container and start streaming only if it matches any subscription
for _, c := range containers {
if c.State == "running" {
matchingSubs := m.getMatchingSubscriptions(&c)
if len(matchingSubs) > 0 {
m.startContainerStream(ctx, &c)
}
}
}
return nil
}
// startContainerStream starts a single log stream for a container
// All matching subscriptions will receive logs from this one stream
func (m *Manager) startContainerStream(ctx context.Context, c *container.Container) {
// Check if already streaming
m.mu.RLock()
_, exists := m.activeStreams[c.ID]
m.mu.RUnlock()
if exists {
return
}
// Find which subscriptions match this container
matchingSubs := m.getMatchingSubscriptions(c)
if len(matchingSubs) == 0 {
return
}
log.Debug().
Str("container", c.Name).
Int("subscriptions", len(matchingSubs)).
Msg("starting log stream for notification subscriptions")
// Convert to notification.Container and cache it
notifContainer := NewContainer(c)
m.mu.Lock()
m.containerCache[c.ID] = notifContainer
m.mu.Unlock()
streamCtx, cancel := context.WithCancel(ctx)
stream := &activeStream{
container: notifContainer,
subscriptions: matchingSubs,
cancel: cancel,
}
m.mu.Lock()
m.activeStreams[c.ID] = stream
m.mu.Unlock()
go func() {
defer func() {
m.mu.Lock()
delete(m.activeStreams, c.ID)
m.mu.Unlock()
}()
logs := make(chan *container.LogEvent)
// Stream logs in separate goroutine
go func() {
containerService, err := m.containerService.FindContainer(c.Host, c.ID, nil)
if err != nil {
log.Error().Err(err).Msg("error finding container for notification streaming")
return
}
err = containerService.StreamLogs(streamCtx, time.Now(), container.STDOUT|container.STDERR, logs)
if err != nil && err != context.Canceled {
log.Error().Err(err).Msg("error streaming logs for notification")
}
close(logs)
}()
// Process logs - check against all matching subscriptions
for logEvent := range logs {
for _, cs := range matchingSubs {
m.processLogEvent(logEvent, c.ID, cs)
}
}
}()
}
// getMatchingSubscriptions returns subscriptions that match a container
func (m *Manager) getMatchingSubscriptions(c *container.Container) []*compiledSubscription {
m.mu.RLock()
defer m.mu.RUnlock()
containerCtx := NewContainer(c)
matching := make([]*compiledSubscription, 0)
for _, cs := range m.subscriptions {
if m.matchesContainer(cs.containerProgram, containerCtx) {
matching = append(matching, cs)
}
}
return matching
}
// matchesContainer evaluates the container filter expression
func (m *Manager) matchesContainer(program *vm.Program, containerCtx Container) bool {
result, err := expr.Run(program, containerCtx)
if err != nil {
log.Error().Err(err).Msg("error evaluating container filter")
return false
}
match, ok := result.(bool)
if !ok {
log.Error().Msg("container filter did not return boolean")
return false
}
return match
}
// processLogEvent evaluates a log event against the subscription's log filter
func (m *Manager) processLogEvent(logEvent *container.LogEvent, containerID string, cs *compiledSubscription) {
// Lookup notification.Container from cache
m.mu.RLock()
notifContainer, ok := m.containerCache[containerID]
m.mu.RUnlock()
if !ok {
log.Warn().Str("container", containerID).Msg("container not in cache")
return
}
logCtx := NewLog(logEvent, notifContainer)
// Evaluate log filter (program is never nil)
if m.matchesLog(cs.logProgram, logCtx) {
m.triggerWebhook(cs.subscription, logCtx)
}
}
// matchesLog evaluates the log filter expression
func (m *Manager) matchesLog(program *vm.Program, logCtx Log) bool {
result, err := expr.Run(program, logCtx)
if err != nil {
log.Error().Err(err).Msg("error evaluating log filter")
return false
}
match, ok := result.(bool)
if !ok {
log.Error().Msg("log filter did not return boolean")
return false
}
return match
}
// triggerWebhook sends the notification
func (m *Manager) triggerWebhook(sub *Subscription, logCtx Log) {
payload := WebhookPayload{
SubscriptionName: sub.Name,
Timestamp: time.Now(),
Container: logCtx.Container,
Log: LogEvent{
Message: logCtx.Message,
Level: logCtx.Level,
Timestamp: logCtx.Timestamp,
},
}
m.dispatcher.Dispatch(sub, payload)
}
-87
View File
@@ -1,87 +0,0 @@
package notification
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// Config represents the YAML configuration structure
type Config struct {
Dispatcher DispatcherConfig `yaml:"dispatcher"`
Subscriptions []*Subscription `yaml:"subscriptions"`
}
// LoadFromFile loads config and returns a fully configured Manager
func LoadFromFile(path string, containerService ContainerService) (*Manager, error) {
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil // No config file is fine, return nil
}
return nil, fmt.Errorf("failed to read notifications config: %w", err)
}
var config Config
if err := yaml.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse notifications config: %w", err)
}
// Validate dispatcher config
if config.Dispatcher.Type == "" {
config.Dispatcher.Type = "simple" // Default to simple
}
if config.Dispatcher.URL == "" {
return nil, fmt.Errorf("dispatcher.url is required")
}
// Validate subscriptions
for _, sub := range config.Subscriptions {
if sub.Name == "" {
return nil, fmt.Errorf("subscription missing name")
}
if sub.ContainerFilter == "" {
return nil, fmt.Errorf("subscription %q missing container_filter", sub.Name)
}
if sub.LogFilter == "" {
return nil, fmt.Errorf("subscription %q missing log_filter", sub.Name)
}
}
// Create dispatcher based on type
var dispatcher Dispatcher
switch config.Dispatcher.Type {
case "simple":
dispatcher = NewWebhookDispatcher(&config.Dispatcher)
default:
return nil, fmt.Errorf("unsupported dispatcher type: %s", config.Dispatcher.Type)
}
// Create and configure manager
manager := NewManager(containerService, dispatcher)
if err := manager.LoadSubscriptions(config.Subscriptions); err != nil {
return nil, err
}
return manager, nil
}
// SaveToFile saves dispatcher config and subscriptions to a YAML file
func SaveToFile(path string, dispatcher *DispatcherConfig, subs []*Subscription) error {
config := Config{
Dispatcher: *dispatcher,
Subscriptions: subs,
}
data, err := yaml.Marshal(&config)
if err != nil {
return fmt.Errorf("failed to marshal notifications config: %w", err)
}
if err := os.WriteFile(path, data, 0644); err != nil {
return fmt.Errorf("failed to write notifications config: %w", err)
}
return nil
}
-104
View File
@@ -1,104 +0,0 @@
package notification
import (
"strings"
"time"
"github.com/amir20/dozzle/internal/container"
)
// DispatcherConfig represents global dispatcher configuration
type DispatcherConfig struct {
// Type determines the dispatcher type (webhook, dozzle-service, etc.)
Type string `yaml:"type"` // "webhook" is default
// URL is the endpoint for the dispatcher service
URL string `yaml:"url"`
// APIKey for authenticating with the dispatcher service
APIKey string `yaml:"api_key,omitempty"`
// Headers to include in all requests
Headers map[string]string `yaml:"headers,omitempty"`
}
// Subscription represents a notification rule
type Subscription struct {
// Name is a human-readable name for this subscription
Name string `yaml:"name"`
// ContainerFilter is an expr expression to match containers (REQUIRED)
// Expression receives a Container object with: Name, Labels, Host, State
// Example: Name == "nginx" || Labels["app"] == "web"
ContainerFilter string `yaml:"container_filter"`
// LogFilter is an expr expression to match log events (REQUIRED)
// Expression receives a Log object with: Message, Level, Timestamp, Container
// Example: Level == "error" || Message contains "panic"
LogFilter string `yaml:"log_filter"`
}
// Container represents container information for expr evaluation (internal type)
type Container struct {
Name string `expr:"Name"`
Labels map[string]string `expr:"Labels"`
Host string `expr:"Host"`
State string `expr:"State"`
}
// Log represents log event information for expr evaluation
type Log struct {
Message any `expr:"Message"`
Level string `expr:"Level"`
Timestamp time.Time `expr:"Timestamp"`
Container Container `expr:"Container"`
}
// WebhookPayload is the structure sent to webhook endpoints
type WebhookPayload struct {
SubscriptionName string `json:"subscription_name"`
Timestamp time.Time `json:"timestamp"`
Container Container `json:"container"`
Log LogEvent `json:"log"`
}
// LogEvent represents the log in the webhook payload
type LogEvent struct {
Message any `json:"message"`
Level string `json:"level"`
Timestamp time.Time `json:"timestamp"`
}
// NewContainer converts container.Container to notification.Container
func NewContainer(c *container.Container) Container {
return Container{
Name: c.Name,
Labels: c.Labels,
Host: c.Host,
State: c.State,
}
}
// NewLog creates a Log from container.LogEvent and notification.Container
func NewLog(logEvent *container.LogEvent, notifContainer Container) Log {
timestamp := time.Unix(0, logEvent.Timestamp)
// Extract message - keep as any type for expr flexibility
var message any = logEvent.Message
// For grouped logs, join fragments into single string for easier matching
if fragments, ok := logEvent.Message.([]container.LogFragment); ok {
parts := make([]string, len(fragments))
for i, frag := range fragments {
parts[i] = frag.Message
}
message = strings.Join(parts, "\n")
}
return Log{
Message: message,
Level: logEvent.Level,
Timestamp: timestamp,
Container: notifContainer,
}
}
-83
View File
@@ -1,83 +0,0 @@
package notification
import (
"bytes"
"encoding/json"
"net/http"
"time"
"github.com/rs/zerolog/log"
)
// Dispatcher is the interface for sending notifications
type Dispatcher interface {
Dispatch(subscription *Subscription, payload WebhookPayload)
}
// WebhookDispatcher handles async webhook delivery
type WebhookDispatcher struct {
client *http.Client
config *DispatcherConfig
}
// NewWebhookDispatcher creates a new webhook dispatcher
func NewWebhookDispatcher(config *DispatcherConfig) *WebhookDispatcher {
return &WebhookDispatcher{
client: &http.Client{
Timeout: 10 * time.Second,
},
config: config,
}
}
// Dispatch sends a webhook payload asynchronously
func (d *WebhookDispatcher) Dispatch(subscription *Subscription, payload WebhookPayload) {
url := d.config.URL
go func() {
body, err := json.Marshal(payload)
if err != nil {
log.Error().Err(err).Str("url", url).Msg("failed to marshal webhook payload")
return
}
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
if err != nil {
log.Error().Err(err).Str("url", url).Msg("failed to create webhook request")
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Dozzle-Notifications/1.0")
// Add API key if configured
if d.config.APIKey != "" {
req.Header.Set("Authorization", "Bearer "+d.config.APIKey)
}
// Add custom headers
for key, value := range d.config.Headers {
req.Header.Set(key, value)
}
resp, err := d.client.Do(req)
if err != nil {
log.Error().Err(err).Str("url", url).Msg("failed to send webhook")
return
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
log.Warn().
Int("status", resp.StatusCode).
Str("url", url).
Str("subscription", payload.SubscriptionName).
Msg("webhook returned error status")
} else {
log.Debug().
Int("status", resp.StatusCode).
Str("url", url).
Str("subscription", payload.SubscriptionName).
Msg("webhook delivered successfully")
}
}()
}
+1 -1
View File
@@ -26,7 +26,7 @@ func NewAgentService(client *agent.Client) ClientService {
}
func (a *agentService) FindContainer(ctx context.Context, id string, labels container.ContainerLabels) (container.Container, error) {
return a.client.FindContainer(ctx, id)
return a.client.FindContainer(ctx, id, labels)
}
func (a *agentService) RawLogs(ctx context.Context, container container.Container, from time.Time, to time.Time, stdTypes container.StdType) (io.ReadCloser, error) {
@@ -122,12 +122,6 @@ func (m *MultiHostService) SubscribeEventsAndStats(ctx context.Context, events c
}
}
func (m *MultiHostService) SubscribeEvents(ctx context.Context, events chan<- container.ContainerEvent) {
for _, client := range m.manager.List() {
client.SubscribeEvents(ctx, events)
}
}
func (m *MultiHostService) SubscribeContainersStarted(ctx context.Context, containers chan<- container.Container, filter container_support.ContainerFilter) {
newContainers := make(chan container.Container)
for _, client := range m.manager.List() {
@@ -96,10 +96,6 @@ func (m *K8sClusterService) SubscribeEventsAndStats(ctx context.Context, events
m.client.SubscribeStats(ctx, stats)
}
func (m *K8sClusterService) SubscribeEvents(ctx context.Context, events chan<- container.ContainerEvent) {
m.client.SubscribeEvents(ctx, events)
}
func (m *K8sClusterService) SubscribeContainersStarted(ctx context.Context, containers chan<- container.Container, filter container_support.ContainerFilter) {
newContainers := make(chan container.Container)
m.client.SubscribeContainersStarted(ctx, newContainers)
+13 -15
View File
@@ -10,7 +10,6 @@ import (
"github.com/amir20/dozzle/internal/auth"
"github.com/amir20/dozzle/internal/container"
"github.com/amir20/dozzle/internal/notification"
container_support "github.com/amir20/dozzle/internal/support/container"
"github.com/go-chi/chi/v5"
@@ -35,20 +34,19 @@ const (
// Config is a struct for configuring the web service
type Config struct {
Base string
Addr string
Version string
Hostname string
NoAnalytics bool
Dev bool
Mode string
Authorization Authorization
EnableActions bool
EnableShell bool
DisableAvatars bool
ReleaseCheckMode ReleaseCheckMode
Labels container.ContainerLabels
NotificationManager *notification.Manager
Base string
Addr string
Version string
Hostname string
NoAnalytics bool
Dev bool
Mode string
Authorization Authorization
EnableActions bool
EnableShell bool
DisableAvatars bool
ReleaseCheckMode ReleaseCheckMode
Labels container.ContainerLabels
}
type Authorization struct {
+35 -64
View File
@@ -17,7 +17,6 @@ import (
"github.com/amir20/dozzle/internal/auth"
"github.com/amir20/dozzle/internal/docker"
"github.com/amir20/dozzle/internal/k8s"
"github.com/amir20/dozzle/internal/notification"
"github.com/amir20/dozzle/internal/support/cli"
docker_support "github.com/amir20/dozzle/internal/support/docker"
k8s_support "github.com/amir20/dozzle/internal/support/k8s"
@@ -109,18 +108,15 @@ func main() {
log.Fatal().Str("mode", args.Mode).Msg("Invalid mode")
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
notificationManager := initializeNotifications(ctx, hostService)
srv := createServer(args, hostService, notificationManager)
srv := createServer(args, hostService)
go func() {
log.Info().Msgf("Accepting connections on %s", args.Addr)
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
log.Fatal().Err(err).Msg("failed to listen")
}
}()
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
<-ctx.Done()
stop()
@@ -141,56 +137,7 @@ func fileExists(filename string) bool {
return err == nil
}
func initializeSimpleAuth(authTTL string) web.Authorizer {
log.Debug().Msg("Using simple authentication")
userFilePath := "./data/users.yml"
if !fileExists(userFilePath) {
userFilePath = "./data/users.yaml"
if !fileExists(userFilePath) {
log.Fatal().Msg("No users.yaml or users.yml file found.")
}
}
log.Debug().Msgf("Reading %s file", filepath.Base(userFilePath))
db, err := auth.ReadUsersFromFile(userFilePath)
if err != nil {
log.Fatal().Err(err).Msgf("Could not read users file: %s", userFilePath)
}
log.Debug().Int("users", len(db.Users)).Msg("Loaded users")
ttl := time.Duration(0)
if authTTL != "session" {
ttl, err = time.ParseDuration(authTTL)
if err != nil {
log.Fatal().Err(err).Msg("Could not parse auth ttl")
}
}
return auth.NewSimpleAuth(db, ttl)
}
func initializeNotifications(ctx context.Context, hostService web.HostService) *notification.Manager {
notificationsPath := "./data/notifications.yml"
manager, err := notification.LoadFromFile(notificationsPath, hostService)
if err != nil {
log.Error().Err(err).Msg("failed to load notifications config")
return nil
}
if manager == nil {
return nil // No config file
}
if err := manager.Start(ctx); err != nil {
log.Error().Err(err).Msg("failed to start notification manager")
return nil
}
return manager
}
func createServer(args cli.Args, hostService web.HostService, notificationManager *notification.Manager) *http.Server {
func createServer(args cli.Args, hostService web.HostService) *http.Server {
_, dev := os.LookupEnv("DEV")
var releaseCheckMode web.ReleaseCheckMode = web.Automatic
@@ -211,8 +158,33 @@ func createServer(args cli.Args, hostService web.HostService, notificationManage
provider = web.FORWARD_PROXY
authorizer = auth.NewForwardProxyAuth(args.AuthHeaderUser, args.AuthHeaderEmail, args.AuthHeaderName, args.AuthHeaderFilter, args.AuthHeaderRoles)
} else if args.AuthProvider == "simple" {
log.Debug().Msg("Using simple authentication")
provider = web.SIMPLE
authorizer = initializeSimpleAuth(args.AuthTTL)
userFilePath := "./data/users.yml"
if !fileExists(userFilePath) {
userFilePath = "./data/users.yaml"
if !fileExists(userFilePath) {
log.Fatal().Msg("No users.yaml or users.yml file found.")
}
}
log.Debug().Msgf("Reading %s file", filepath.Base(userFilePath))
db, err := auth.ReadUsersFromFile(userFilePath)
if err != nil {
log.Fatal().Err(err).Msgf("Could not read users file: %s", userFilePath)
}
log.Debug().Int("users", len(db.Users)).Msg("Loaded users")
ttl := time.Duration(0)
if args.AuthTTL != "session" {
ttl, err = time.ParseDuration(args.AuthTTL)
if err != nil {
log.Fatal().Err(err).Msg("Could not parse auth ttl")
}
}
authorizer = auth.NewSimpleAuth(db, ttl)
}
authTTL := time.Duration(0)
@@ -239,12 +211,11 @@ func createServer(args cli.Args, hostService web.HostService, notificationManage
TTL: authTTL,
LogoutUrl: args.AuthLogoutUrl,
},
EnableActions: args.EnableActions,
EnableShell: args.EnableShell,
DisableAvatars: args.DisableAvatars,
ReleaseCheckMode: releaseCheckMode,
Labels: args.Filter,
NotificationManager: notificationManager,
EnableActions: args.EnableActions,
EnableShell: args.EnableShell,
DisableAvatars: args.DisableAvatars,
ReleaseCheckMode: releaseCheckMode,
Labels: args.Filter,
}
assets, err := fs.Sub(content, "dist")
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "dozzle",
"version": "9.0.1",
"version": "9.0.3",
"description": "Realtime log viewer for docker containers.",
"homepage": "https://github.com/amir20/dozzle#readme",
"bugs": {
@@ -29,14 +29,14 @@
"docs:preview": "vitepress preview docs"
},
"dependencies": {
"@duckdb/duckdb-wasm": "1.33.1-dev16.0",
"@iconify-json/carbon": "^1.2.16",
"@duckdb/duckdb-wasm": "1.33.1-dev18.0",
"@iconify-json/carbon": "^1.2.18",
"@iconify-json/cil": "^1.2.3",
"@iconify-json/ic": "^1.2.4",
"@iconify-json/material-symbols": "^1.2.51",
"@iconify-json/mdi": "^1.2.3",
"@iconify-json/mdi-light": "^1.2.2",
"@iconify-json/octicon": "^1.2.19",
"@iconify-json/octicon": "^1.2.20",
"@iconify-json/ph": "^1.2.2",
"@intlify/unplugin-vue-i18n": "^11.0.3",
"@tailwindcss/typography": "^0.5.19",
@@ -58,9 +58,9 @@
"splitpanes": "^4.0.4",
"strip-ansi": "^7.1.2",
"tailwindcss": "4.1.18",
"unplugin-auto-import": "^20.3.0",
"unplugin-icons": "^22.5.0",
"unplugin-vue-components": "^30.0.0",
"unplugin-auto-import": "^21.0.0",
"unplugin-icons": "^23.0.1",
"unplugin-vue-components": "^31.0.0",
"unplugin-vue-macros": "^2.14.5",
"unplugin-vue-router": "^0.19.2",
"vite": "7.3.1",
@@ -79,22 +79,22 @@
"@pinia/testing": "^1.0.3",
"@playwright/test": "^1.57.0",
"@types/lodash.debounce": "^4.0.9",
"@types/node": "^25.0.6",
"@types/node": "^25.0.9",
"@vitejs/plugin-vue": "6.0.3",
"@vue/compiler-sfc": "^3.5.26",
"@vue/test-utils": "^2.4.6",
"bumpp": "^10.3.2",
"bumpp": "^10.4.0",
"c8": "^10.1.3",
"concurrently": "^9.2.1",
"eventsourcemock": "^2.0.0",
"jsdom": "^27.4.0",
"lint-staged": "^16.2.7",
"prettier": "^3.7.4",
"prettier": "^3.8.0",
"prettier-plugin-tailwindcss": "^0.7.2",
"simple-git-hooks": "^2.13.1",
"ts-node": "^10.9.2",
"typescript": "^5.9.3",
"vitest": "^4.0.16",
"vitest": "^4.0.17",
"vue-component-type-helpers": "3.2.2",
"vue-tsc": "3.2.2"
},
+158 -244
View File
@@ -12,11 +12,11 @@ importers:
.:
dependencies:
'@duckdb/duckdb-wasm':
specifier: 1.33.1-dev16.0
version: 1.33.1-dev16.0
specifier: 1.33.1-dev18.0
version: 1.33.1-dev18.0
'@iconify-json/carbon':
specifier: ^1.2.16
version: 1.2.16
specifier: ^1.2.18
version: 1.2.18
'@iconify-json/cil':
specifier: ^1.2.3
version: 1.2.3
@@ -33,8 +33,8 @@ importers:
specifier: ^1.2.2
version: 1.2.2
'@iconify-json/octicon':
specifier: ^1.2.19
version: 1.2.19
specifier: ^1.2.20
version: 1.2.20
'@iconify-json/ph':
specifier: ^1.2.2
version: 1.2.2
@@ -46,7 +46,7 @@ importers:
version: 0.5.19(tailwindcss@4.1.18)
'@tailwindcss/vite':
specifier: 4.1.18
version: 4.1.18(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
version: 4.1.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
'@vueuse/components':
specifier: ^14.1.0
version: 14.1.0(vue@3.5.26(typescript@5.9.3))
@@ -99,32 +99,32 @@ importers:
specifier: 4.1.18
version: 4.1.18
unplugin-auto-import:
specifier: ^20.3.0
version: 20.3.0(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))
specifier: ^21.0.0
version: 21.0.0(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))
unplugin-icons:
specifier: ^22.5.0
version: 22.5.0(@vue/compiler-sfc@3.5.26)
specifier: ^23.0.1
version: 23.0.1(@vue/compiler-sfc@3.5.26)
unplugin-vue-components:
specifier: ^30.0.0
version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.26(typescript@5.9.3))
specifier: ^31.0.0
version: 31.0.0(vue@3.5.26(typescript@5.9.3))
unplugin-vue-macros:
specifier: ^2.14.5
version: 2.14.5(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))(esbuild@0.27.1)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-tsc@3.2.2(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
version: 2.14.5(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))(esbuild@0.27.1)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-tsc@3.2.2(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
unplugin-vue-router:
specifier: ^0.19.2
version: 0.19.2(@vue/compiler-sfc@3.5.26)(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3))
vite:
specifier: 7.3.1
version: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
version: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite-plugin-vue-layouts:
specifier: ^0.11.0
version: 0.11.0(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3))
version: 0.11.0(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3))
vite-svg-loader:
specifier: ^5.1.0
version: 5.1.0(vue@3.5.26(typescript@5.9.3))
vitepress:
specifier: 1.6.4
version: 1.6.4(@algolia/client-search@5.23.4)(@types/node@25.0.6)(fuse.js@7.1.0)(lightningcss@1.30.2)(postcss@8.5.6)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.39.0)(typescript@5.9.3)
version: 1.6.4(@algolia/client-search@5.23.4)(@types/node@25.0.9)(fuse.js@7.1.0)(lightningcss@1.30.2)(postcss@8.5.6)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.39.0)(typescript@5.9.3)
vue:
specifier: ^3.5.26
version: 3.5.26(typescript@5.9.3)
@@ -157,11 +157,11 @@ importers:
specifier: ^4.0.9
version: 4.0.9
'@types/node':
specifier: ^25.0.6
version: 25.0.6
specifier: ^25.0.9
version: 25.0.9
'@vitejs/plugin-vue':
specifier: 6.0.3
version: 6.0.3(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))
version: 6.0.3(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))
'@vue/compiler-sfc':
specifier: ^3.5.26
version: 3.5.26
@@ -169,8 +169,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
bumpp:
specifier: ^10.3.2
version: 10.3.2
specifier: ^10.4.0
version: 10.4.0
c8:
specifier: ^10.1.3
version: 10.1.3
@@ -187,23 +187,23 @@ importers:
specifier: ^16.2.7
version: 16.2.7
prettier:
specifier: ^3.7.4
version: 3.7.4
specifier: ^3.8.0
version: 3.8.0
prettier-plugin-tailwindcss:
specifier: ^0.7.2
version: 0.7.2(prettier@3.7.4)
version: 0.7.2(prettier@3.8.0)
simple-git-hooks:
specifier: ^2.13.1
version: 2.13.1
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@25.0.6)(typescript@5.9.3)
version: 10.9.2(@types/node@25.0.9)(typescript@5.9.3)
typescript:
specifier: ^5.9.3
version: 5.9.3
vitest:
specifier: ^4.0.16
version: 4.0.16(@types/node@25.0.6)(jiti@2.6.1)(jsdom@27.4.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
specifier: ^4.0.17
version: 4.0.17(@types/node@25.0.9)(jiti@2.6.1)(jsdom@27.4.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vue-component-type-helpers:
specifier: 3.2.2
version: 3.2.2
@@ -291,9 +291,6 @@ packages:
'@antfu/install-pkg@1.1.0':
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
'@antfu/utils@9.2.0':
resolution: {integrity: sha512-Oq1d9BGZakE/FyoEtcNeSwM7MpDO2vUBi11RWBZXf75zPsbUVWmUs03EqkRFrcgbXyKTas0BdZWC1wcuSoqSAw==}
'@apache-arrow/esnext-esm@21.1.0':
resolution: {integrity: sha512-ZMlUJKmoout0U6PvHFMqYhXD5V7UAOdxUyf3cZQQwAJisz9HL2t449J6POjo+Na1M4HhHXtuHWuOakYi7n4SlQ==}
hasBin: true
@@ -393,8 +390,8 @@ packages:
search-insights:
optional: true
'@duckdb/duckdb-wasm@1.33.1-dev16.0':
resolution: {integrity: sha512-+RPsd/9EWxjVyED9O7sAGGi2b+B+rZNMaZNc3ycbYGmJX25Ng4S1Akmy/uqBxPyuZPdmJDCopfusDAh0CMjvtg==}
'@duckdb/duckdb-wasm@1.33.1-dev18.0':
resolution: {integrity: sha512-BVF+CYmOsrMRY8rnJa0USmC5PujPs2eZovQrSEeHs85J/MZ9mSblhzDih9BPu4MgwUxK9dYbYxKkBIJ4jv3EKw==}
'@emnapi/core@1.4.3':
resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
@@ -942,8 +939,8 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
'@iconify-json/carbon@1.2.16':
resolution: {integrity: sha512-R50UiC4NgPdnoSI3OzaZ/PzKYFVHAsAi3tENWgxvTxjYND3WHiUiG0qfJ0dPuaxwIW/l/2TnZwMPbbedd/+qIQ==}
'@iconify-json/carbon@1.2.18':
resolution: {integrity: sha512-Grb13E6r/RqTEV4Sqd/BQR2FUt57U2WLuticJ5H8JbTdHLop1LmdePu3EJJA3Xi8DcWRbD6OnC133hKfOwlgtg==}
'@iconify-json/cil@1.2.3':
resolution: {integrity: sha512-byZH2wJeow6DO/+mYGwjlG5Gm2ZARJ1Rpr7Ryh4EcAFU0rH+AWoKbAUrBZMh1EU7jsVI4bKM95SLSsrWQ44sEw==}
@@ -966,8 +963,8 @@ packages:
'@iconify-json/mdi@1.2.3':
resolution: {integrity: sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==}
'@iconify-json/octicon@1.2.19':
resolution: {integrity: sha512-q1a9fpyg0Cw/Bt9hEfP86eJlgKtMXzNIRQnsbPZi1MBoHlPyi056TdzV72zY/F+oJSJ8b5Ub8njL2fWs/iLJAg==}
'@iconify-json/octicon@1.2.20':
resolution: {integrity: sha512-BCIWoh06jlOKMY3JCDx547g+4a0TOj96cdrtD1N4gz3oNlWF7yXdrK9WbqYN4ykmDl+KdJYRtOYIFP1AvGXgVA==}
'@iconify-json/ph@1.2.2':
resolution: {integrity: sha512-PgkEZNtqa8hBGjHXQa4pMwZa93hmfu8FUSjs/nv4oUU6yLsgv+gh9nu28Kqi8Fz9CCVu4hj1MZs9/60J57IzFw==}
@@ -981,8 +978,8 @@ packages:
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
'@iconify/utils@3.0.2':
resolution: {integrity: sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==}
'@iconify/utils@3.1.0':
resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==}
'@intlify/bundle-utils@11.0.3':
resolution: {integrity: sha512-dURCDz1rQXwAb1+Hv4NDit6aZSRaAt4zUYBPEeaDCe3FSs8dMtdF6kEvgd9JwsYFSTAHcvbTs2CqwBjjt9Ltsw==}
@@ -1601,8 +1598,8 @@ packages:
'@types/node@24.10.3':
resolution: {integrity: sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ==}
'@types/node@25.0.6':
resolution: {integrity: sha512-NNu0sjyNxpoiW3YuVFfNz7mxSQ+S4X2G28uqg2s+CzoqoQjLPsWSbsFFyztIAqt2vb8kfEAsJNepMGPTxFDx3Q==}
'@types/node@25.0.9':
resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==}
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@@ -1657,11 +1654,11 @@ packages:
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
vue: ^3.2.25
'@vitest/expect@4.0.16':
resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==}
'@vitest/expect@4.0.17':
resolution: {integrity: sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==}
'@vitest/mocker@4.0.16':
resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==}
'@vitest/mocker@4.0.17':
resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==}
peerDependencies:
msw: ^2.4.9
vite: ^6.0.0 || ^7.0.0-0
@@ -1671,20 +1668,20 @@ packages:
vite:
optional: true
'@vitest/pretty-format@4.0.16':
resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==}
'@vitest/pretty-format@4.0.17':
resolution: {integrity: sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==}
'@vitest/runner@4.0.16':
resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==}
'@vitest/runner@4.0.17':
resolution: {integrity: sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==}
'@vitest/snapshot@4.0.16':
resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==}
'@vitest/snapshot@4.0.17':
resolution: {integrity: sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==}
'@vitest/spy@4.0.16':
resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==}
'@vitest/spy@4.0.17':
resolution: {integrity: sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==}
'@vitest/utils@4.0.16':
resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==}
'@vitest/utils@4.0.17':
resolution: {integrity: sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==}
'@volar/language-core@2.4.15':
resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==}
@@ -2233,13 +2230,13 @@ packages:
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
bumpp@10.3.2:
resolution: {integrity: sha512-yUUkVx5zpTywLNX97MlrqtpanI7eMMwFwLntWR2EBVDw3/Pm3aRIzCoDEGHATLIiHK9PuJC7xWI4XNWqXItSPg==}
bumpp@10.4.0:
resolution: {integrity: sha512-VzJhB4iyZ04w99HreEvXJY/lxzApnE/PRbcFY4cKnOUSRVbRbAf0AIU0DeavrkffW+mclJlkmnQYn9NdwcBk1g==}
engines: {node: '>=18'}
hasBin: true
c12@3.3.2:
resolution: {integrity: sha512-QkikB2X5voO1okL3QsES0N690Sn/K9WokXqUsDQsWy5SnYb+psYQFGA10iy1bZHj3fjISKsI67Q90gruvWWM3A==}
c12@3.3.3:
resolution: {integrity: sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==}
peerDependencies:
magicast: '*'
peerDependenciesMeta:
@@ -2293,10 +2290,6 @@ packages:
character-entities-legacy@3.0.0:
resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
chokidar@5.0.0:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
@@ -2664,9 +2657,6 @@ packages:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
exsolve@1.0.7:
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
exsolve@1.0.8:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
@@ -2796,10 +2786,6 @@ packages:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
globals@15.15.0:
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -2972,9 +2958,6 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
kolorist@1.8.0:
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -3094,9 +3077,6 @@ packages:
resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==}
engines: {node: '>=20.19.0'}
magic-string@0.30.19:
resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -3253,9 +3233,6 @@ packages:
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-manager-detector@1.3.0:
resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
package-manager-detector@1.6.0:
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
@@ -3401,8 +3378,8 @@ packages:
prettier-plugin-svelte:
optional: true
prettier@3.7.4:
resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==}
prettier@3.8.0:
resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==}
engines: {node: '>=14'}
hasBin: true
@@ -3429,10 +3406,6 @@ packages:
rc9@2.1.2:
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
readdirp@5.0.0:
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
engines: {node: '>= 20.19.0'}
@@ -3498,11 +3471,6 @@ packages:
search-insights@2.17.3:
resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==}
semver@7.7.2:
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
engines: {node: '>=10'}
hasBin: true
semver@7.7.3:
resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
engines: {node: '>=10'}
@@ -3764,8 +3732,8 @@ packages:
resolution: {integrity: sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==}
engines: {node: '>=12.17'}
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
ufo@1.6.3:
resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
unconfig@7.3.1:
resolution: {integrity: sha512-LH5WL+un92tGAzWS87k7LkAfwpMdm7V0IXG2FxEjZz/QxiIW5J5LkcrKQThj0aRz6+h/lFmKI9EUXmK/T0bcrw==}
@@ -3776,8 +3744,8 @@ packages:
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
unimport@5.5.0:
resolution: {integrity: sha512-/JpWMG9s1nBSlXJAQ8EREFTFy3oy6USFd8T6AoBaw1q2GGcF4R9yp3ofg32UODZlYEO5VD0EWE1RpI9XDWyPYg==}
unimport@5.6.0:
resolution: {integrity: sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A==}
engines: {node: '>=18.12.0'}
unist-util-is@6.0.0:
@@ -3795,9 +3763,9 @@ packages:
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
unplugin-auto-import@20.3.0:
resolution: {integrity: sha512-RcSEQiVv7g0mLMMXibYVKk8mpteKxvyffGuDKqZZiFr7Oq3PB1HwgHdK5O7H4AzbhzHoVKG0NnMnsk/1HIVYzQ==}
engines: {node: '>=14'}
unplugin-auto-import@21.0.0:
resolution: {integrity: sha512-vWuC8SwqJmxZFYwPojhOhOXDb5xFhNNcEVb9K/RFkyk/3VnfaOjzitWN7v+8DEKpMjSsY2AEGXNgt6I0yQrhRQ==}
engines: {node: '>=20.19.0'}
peerDependencies:
'@nuxt/kit': ^4.0.0
'@vueuse/core': '*'
@@ -3834,15 +3802,13 @@ packages:
webpack:
optional: true
unplugin-icons@22.5.0:
resolution: {integrity: sha512-MBlMtT5RuMYZy4TZgqUL2OTtOdTUVsS1Mhj6G1pEzMlFJlEnq6mhUfoIt45gBWxHcsOdXJDWLg3pRZ+YmvAVWQ==}
unplugin-icons@23.0.1:
resolution: {integrity: sha512-rv0XEJepajKzDLvRUWASM8K+8+/CCfZn2jtogXqg6RIp7kpatRc/aFrVJn8ANQA09e++lPEEv9yX8cC9enc+QQ==}
peerDependencies:
'@svgr/core': '>=7.0.0'
'@svgx/core': ^1.0.1
'@vue/compiler-sfc': ^3.0.2 || ^2.7.0
'@vue/compiler-sfc': ^3.0.2
svelte: ^3.0.0 || ^4.0.0 || ^5.0.0
vue-template-compiler: ^2.6.12
vue-template-es2015-compiler: ^1.9.0
peerDependenciesMeta:
'@svgr/core':
optional: true
@@ -3852,10 +3818,6 @@ packages:
optional: true
svelte:
optional: true
vue-template-compiler:
optional: true
vue-template-es2015-compiler:
optional: true
unplugin-utils@0.2.4:
resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==}
@@ -3865,16 +3827,13 @@ packages:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
unplugin-vue-components@30.0.0:
resolution: {integrity: sha512-4qVE/lwCgmdPTp6h0qsRN2u642tt4boBQtcpn4wQcWZAsr8TQwq+SPT3NDu/6kBFxzo/sSEK4ioXhOOBrXc3iw==}
engines: {node: '>=14'}
unplugin-vue-components@31.0.0:
resolution: {integrity: sha512-4ULwfTZTLuWJ7+S9P7TrcStYLsSRkk6vy2jt/WTfgUEUb0nW9//xxmrfhyHUEVpZ2UKRRwfRb8Yy15PDbVZf+Q==}
engines: {node: '>=20.19.0'}
peerDependencies:
'@babel/parser': ^7.15.8
'@nuxt/kit': ^3.2.2 || ^4.0.0
vue: 2 || 3
vue: ^3.0.0
peerDependenciesMeta:
'@babel/parser':
optional: true
'@nuxt/kit':
optional: true
@@ -3901,10 +3860,6 @@ packages:
resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==}
engines: {node: '>=14.0.0'}
unplugin@2.3.10:
resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==}
engines: {node: '>=18.12.0'}
unplugin@2.3.11:
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
engines: {node: '>=18.12.0'}
@@ -4023,18 +3978,18 @@ packages:
postcss:
optional: true
vitest@4.0.16:
resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==}
vitest@4.0.17:
resolution: {integrity: sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@opentelemetry/api': ^1.9.0
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
'@vitest/browser-playwright': 4.0.16
'@vitest/browser-preview': 4.0.16
'@vitest/browser-webdriverio': 4.0.16
'@vitest/ui': 4.0.16
'@vitest/browser-playwright': 4.0.17
'@vitest/browser-preview': 4.0.17
'@vitest/browser-webdriverio': 4.0.17
'@vitest/ui': 4.0.17
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -4307,11 +4262,9 @@ snapshots:
'@antfu/install-pkg@1.1.0':
dependencies:
package-manager-detector: 1.3.0
package-manager-detector: 1.6.0
tinyexec: 1.0.2
'@antfu/utils@9.2.0': {}
'@apache-arrow/esnext-esm@21.1.0':
dependencies:
'@swc/helpers': 0.5.17
@@ -4419,7 +4372,7 @@ snapshots:
transitivePeerDependencies:
- '@algolia/client-search'
'@duckdb/duckdb-wasm@1.33.1-dev16.0':
'@duckdb/duckdb-wasm@1.33.1-dev18.0':
dependencies:
apache-arrow: 17.0.0
qs: 6.14.1
@@ -4738,7 +4691,7 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
'@iconify-json/carbon@1.2.16':
'@iconify-json/carbon@1.2.18':
dependencies:
'@iconify/types': 2.0.0
@@ -4770,7 +4723,7 @@ snapshots:
dependencies:
'@iconify/types': 2.0.0
'@iconify-json/octicon@1.2.19':
'@iconify-json/octicon@1.2.20':
dependencies:
'@iconify/types': 2.0.0
@@ -4788,18 +4741,11 @@ snapshots:
'@iconify/types@2.0.0': {}
'@iconify/utils@3.0.2':
'@iconify/utils@3.1.0':
dependencies:
'@antfu/install-pkg': 1.1.0
'@antfu/utils': 9.2.0
'@iconify/types': 2.0.0
debug: 4.4.3
globals: 15.15.0
kolorist: 1.8.0
local-pkg: 1.1.2
mlly: 1.8.0
transitivePeerDependencies:
- supports-color
'@intlify/bundle-utils@11.0.3(vue-i18n@11.2.8(vue@3.5.26(typescript@5.9.3)))':
dependencies:
@@ -5244,12 +5190,12 @@ snapshots:
postcss-selector-parser: 6.0.10
tailwindcss: 4.1.18
'@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
'@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
dependencies:
'@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.1.18
tailwindcss: 4.1.18
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
'@trysound/sax@0.2.0': {}
@@ -5314,7 +5260,7 @@ snapshots:
dependencies:
undici-types: 7.16.0
'@types/node@25.0.6':
'@types/node@25.0.9':
dependencies:
undici-types: 7.16.0
@@ -5365,54 +5311,54 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
'@vitejs/plugin-vue@5.2.4(vite@5.4.21(@types/node@25.0.6)(lightningcss@1.30.2)(terser@5.39.0))(vue@3.5.26(typescript@5.9.3))':
'@vitejs/plugin-vue@5.2.4(vite@5.4.21(@types/node@25.0.9)(lightningcss@1.30.2)(terser@5.39.0))(vue@3.5.26(typescript@5.9.3))':
dependencies:
vite: 5.4.21(@types/node@25.0.6)(lightningcss@1.30.2)(terser@5.39.0)
vite: 5.4.21(@types/node@25.0.9)(lightningcss@1.30.2)(terser@5.39.0)
vue: 3.5.26(typescript@5.9.3)
'@vitejs/plugin-vue@6.0.3(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))':
'@vitejs/plugin-vue@6.0.3(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.53
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vue: 3.5.26(typescript@5.9.3)
'@vitest/expect@4.0.16':
'@vitest/expect@4.0.17':
dependencies:
'@standard-schema/spec': 1.0.0
'@types/chai': 5.2.3
'@vitest/spy': 4.0.16
'@vitest/utils': 4.0.16
'@vitest/spy': 4.0.17
'@vitest/utils': 4.0.17
chai: 6.2.1
tinyrainbow: 3.0.3
'@vitest/mocker@4.0.16(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
'@vitest/mocker@4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
dependencies:
'@vitest/spy': 4.0.16
'@vitest/spy': 4.0.17
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
'@vitest/pretty-format@4.0.16':
'@vitest/pretty-format@4.0.17':
dependencies:
tinyrainbow: 3.0.3
'@vitest/runner@4.0.16':
'@vitest/runner@4.0.17':
dependencies:
'@vitest/utils': 4.0.16
'@vitest/utils': 4.0.17
pathe: 2.0.3
'@vitest/snapshot@4.0.16':
'@vitest/snapshot@4.0.17':
dependencies:
'@vitest/pretty-format': 4.0.16
'@vitest/pretty-format': 4.0.17
magic-string: 0.30.21
pathe: 2.0.3
'@vitest/spy@4.0.16': {}
'@vitest/spy@4.0.17': {}
'@vitest/utils@4.0.16':
'@vitest/utils@4.0.17':
dependencies:
'@vitest/pretty-format': 4.0.16
'@vitest/pretty-format': 4.0.17
tinyrainbow: 3.0.3
'@volar/language-core@2.4.15':
@@ -5547,12 +5493,12 @@ snapshots:
transitivePeerDependencies:
- vue
'@vue-macros/devtools@0.4.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
'@vue-macros/devtools@0.4.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))':
dependencies:
sirv: 3.0.1
vue: 3.5.26(typescript@5.9.3)
optionalDependencies:
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
transitivePeerDependencies:
- typescript
@@ -6048,11 +5994,11 @@ snapshots:
buffer-from@1.1.2:
optional: true
bumpp@10.3.2:
bumpp@10.4.0:
dependencies:
ansis: 4.2.0
args-tokenizer: 0.3.0
c12: 3.3.2
c12: 3.3.3
cac: 6.7.14
escalade: 3.2.0
jsonc-parser: 3.3.1
@@ -6060,13 +6006,13 @@ snapshots:
semver: 7.7.3
tinyexec: 1.0.2
tinyglobby: 0.2.15
yaml: 2.8.1
yaml: 2.8.2
transitivePeerDependencies:
- magicast
c12@3.3.2:
c12@3.3.3:
dependencies:
chokidar: 4.0.3
chokidar: 5.0.0
confbox: 0.2.2
defu: 6.1.4
dotenv: 17.2.3
@@ -6124,10 +6070,6 @@ snapshots:
character-entities-legacy@3.0.0: {}
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
chokidar@5.0.0:
dependencies:
readdirp: 5.0.0
@@ -6336,7 +6278,7 @@ snapshots:
'@one-ini/wasm': 0.1.1
commander: 10.0.1
minimatch: 9.0.1
semver: 7.7.2
semver: 7.7.3
emoji-regex-xs@1.0.0: {}
@@ -6560,8 +6502,6 @@ snapshots:
expect-type@1.3.0: {}
exsolve@1.0.7: {}
exsolve@1.0.8: {}
fast-deep-equal@3.1.3: {}
@@ -6690,8 +6630,6 @@ snapshots:
globals@14.0.0: {}
globals@15.15.0: {}
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
@@ -6872,8 +6810,6 @@ snapshots:
dependencies:
json-buffer: 3.0.1
kolorist@1.8.0: {}
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -6983,17 +6919,13 @@ snapshots:
dependencies:
magic-string: 0.30.21
magic-string@0.30.19:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
make-dir@4.0.0:
dependencies:
semver: 7.7.2
semver: 7.7.3
make-error@1.3.6: {}
@@ -7070,7 +7002,7 @@ snapshots:
acorn: 8.15.0
pathe: 2.0.3
pkg-types: 1.3.1
ufo: 1.6.1
ufo: 1.6.3
mrmime@2.0.1: {}
@@ -7151,8 +7083,6 @@ snapshots:
package-json-from-dist@1.0.1: {}
package-manager-detector@1.3.0: {}
package-manager-detector@1.6.0: {}
parent-module@1.0.1:
@@ -7204,7 +7134,7 @@ snapshots:
pkg-types@2.3.0:
dependencies:
confbox: 0.2.2
exsolve: 1.0.7
exsolve: 1.0.8
pathe: 2.0.3
playwright-core@1.57.0: {}
@@ -7230,11 +7160,11 @@ snapshots:
prelude-ls@1.2.1: {}
prettier-plugin-tailwindcss@0.7.2(prettier@3.7.4):
prettier-plugin-tailwindcss@0.7.2(prettier@3.8.0):
dependencies:
prettier: 3.7.4
prettier: 3.8.0
prettier@3.7.4: {}
prettier@3.8.0: {}
property-information@7.0.0: {}
@@ -7255,8 +7185,6 @@ snapshots:
defu: 6.1.4
destr: 2.0.5
readdirp@4.1.2: {}
readdirp@5.0.0: {}
regex-recursion@6.0.2:
@@ -7359,8 +7287,6 @@ snapshots:
search-insights@2.17.3: {}
semver@7.7.2: {}
semver@7.7.3: {}
shebang-command@2.0.0:
@@ -7593,14 +7519,14 @@ snapshots:
transitivePeerDependencies:
- typescript
ts-node@10.9.2(@types/node@25.0.6)(typescript@5.9.3):
ts-node@10.9.2(@types/node@25.0.9)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 25.0.6
'@types/node': 25.0.9
acorn: 8.14.1
acorn-walk: 8.3.4
arg: 4.1.3
@@ -7631,7 +7557,7 @@ snapshots:
typical@7.3.0: {}
ufo@1.6.1: {}
ufo@1.6.3: {}
unconfig@7.3.1:
dependencies:
@@ -7644,7 +7570,7 @@ snapshots:
undici-types@7.16.0: {}
unimport@5.5.0:
unimport@5.6.0:
dependencies:
acorn: 8.15.0
escape-string-regexp: 5.0.0
@@ -7684,35 +7610,33 @@ snapshots:
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
unplugin-auto-import@20.3.0(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3))):
unplugin-auto-import@21.0.0(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3))):
dependencies:
local-pkg: 1.1.2
magic-string: 0.30.21
picomatch: 4.0.3
unimport: 5.5.0
unimport: 5.6.0
unplugin: 2.3.11
unplugin-utils: 0.3.1
optionalDependencies:
'@vueuse/core': 14.1.0(vue@3.5.26(typescript@5.9.3))
unplugin-combine@1.2.1(esbuild@0.27.1)(rollup@4.53.3)(unplugin@1.16.1)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)):
unplugin-combine@1.2.1(esbuild@0.27.1)(rollup@4.53.3)(unplugin@1.16.1)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)):
optionalDependencies:
esbuild: 0.27.1
rollup: 4.53.3
unplugin: 1.16.1
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
unplugin-icons@22.5.0(@vue/compiler-sfc@3.5.26):
unplugin-icons@23.0.1(@vue/compiler-sfc@3.5.26):
dependencies:
'@antfu/install-pkg': 1.1.0
'@iconify/utils': 3.0.2
debug: 4.4.3
'@iconify/utils': 3.1.0
local-pkg: 1.1.2
unplugin: 2.3.10
obug: 2.1.1
unplugin: 2.3.11
optionalDependencies:
'@vue/compiler-sfc': 3.5.26
transitivePeerDependencies:
- supports-color
unplugin-utils@0.2.4:
dependencies:
@@ -7724,21 +7648,18 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
unplugin-vue-components@30.0.0(@babel/parser@7.28.5)(vue@3.5.26(typescript@5.9.3)):
unplugin-vue-components@31.0.0(vue@3.5.26(typescript@5.9.3)):
dependencies:
chokidar: 4.0.3
debug: 4.4.3
chokidar: 5.0.0
local-pkg: 1.1.2
magic-string: 0.30.19
magic-string: 0.30.21
mlly: 1.8.0
obug: 2.1.1
picomatch: 4.0.3
tinyglobby: 0.2.15
unplugin: 2.3.10
unplugin: 2.3.11
unplugin-utils: 0.3.1
vue: 3.5.26(typescript@5.9.3)
optionalDependencies:
'@babel/parser': 7.28.5
transitivePeerDependencies:
- supports-color
unplugin-vue-define-options@1.5.5(vue@3.5.26(typescript@5.9.3)):
dependencies:
@@ -7748,7 +7669,7 @@ snapshots:
transitivePeerDependencies:
- vue
unplugin-vue-macros@2.14.5(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))(esbuild@0.27.1)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-tsc@3.2.2(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
unplugin-vue-macros@2.14.5(@vueuse/core@14.1.0(vue@3.5.26(typescript@5.9.3)))(esbuild@0.27.1)(rollup@4.53.3)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-tsc@3.2.2(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
dependencies:
'@vue-macros/better-define': 1.11.4(vue@3.5.26(typescript@5.9.3))
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.26(typescript@5.9.3))
@@ -7763,7 +7684,7 @@ snapshots:
'@vue-macros/define-render': 1.6.6(vue@3.5.26(typescript@5.9.3))
'@vue-macros/define-slots': 1.2.6(vue@3.5.26(typescript@5.9.3))
'@vue-macros/define-stylex': 0.2.3(vue@3.5.26(typescript@5.9.3))
'@vue-macros/devtools': 0.4.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
'@vue-macros/devtools': 0.4.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
'@vue-macros/export-expose': 0.3.5(vue@3.5.26(typescript@5.9.3))
'@vue-macros/export-props': 0.6.5(vue@3.5.26(typescript@5.9.3))
'@vue-macros/export-render': 0.3.5(vue@3.5.26(typescript@5.9.3))
@@ -7780,7 +7701,7 @@ snapshots:
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.26(typescript@5.9.3))
'@vue-macros/volar': 0.30.15(typescript@5.9.3)(vue-tsc@3.2.2(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
unplugin: 1.16.1
unplugin-combine: 1.2.1(esbuild@0.27.1)(rollup@4.53.3)(unplugin@1.16.1)(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
unplugin-combine: 1.2.1(esbuild@0.27.1)(rollup@4.53.3)(unplugin@1.16.1)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
unplugin-vue-define-options: 1.5.5(vue@3.5.26(typescript@5.9.3))
vue: 3.5.26(typescript@5.9.3)
transitivePeerDependencies:
@@ -7824,13 +7745,6 @@ snapshots:
acorn: 8.15.0
webpack-virtual-modules: 0.6.2
unplugin@2.3.10:
dependencies:
'@jridgewell/remapping': 2.3.5
acorn: 8.15.0
picomatch: 4.0.3
webpack-virtual-modules: 0.6.2
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -7862,11 +7776,11 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite-plugin-vue-layouts@0.11.0(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3)):
vite-plugin-vue-layouts@0.11.0(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))(vue-router@4.6.4(vue@3.5.26(typescript@5.9.3)))(vue@3.5.26(typescript@5.9.3)):
dependencies:
debug: 4.4.0
fast-glob: 3.3.3
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vue: 3.5.26(typescript@5.9.3)
vue-router: 4.6.4(vue@3.5.26(typescript@5.9.3))
transitivePeerDependencies:
@@ -7877,18 +7791,18 @@ snapshots:
svgo: 3.3.2
vue: 3.5.26(typescript@5.9.3)
vite@5.4.21(@types/node@25.0.6)(lightningcss@1.30.2)(terser@5.39.0):
vite@5.4.21(@types/node@25.0.9)(lightningcss@1.30.2)(terser@5.39.0):
dependencies:
esbuild: 0.25.10
postcss: 8.5.6
rollup: 4.52.4
optionalDependencies:
'@types/node': 25.0.6
'@types/node': 25.0.9
fsevents: 2.3.3
lightningcss: 1.30.2
terser: 5.39.0
vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2):
vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2):
dependencies:
esbuild: 0.27.1
fdir: 6.5.0(picomatch@4.0.3)
@@ -7897,7 +7811,7 @@ snapshots:
rollup: 4.53.3
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 25.0.6
'@types/node': 25.0.9
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.30.2
@@ -7905,7 +7819,7 @@ snapshots:
tsx: 4.19.2
yaml: 2.8.2
vitepress@1.6.4(@algolia/client-search@5.23.4)(@types/node@25.0.6)(fuse.js@7.1.0)(lightningcss@1.30.2)(postcss@8.5.6)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.39.0)(typescript@5.9.3):
vitepress@1.6.4(@algolia/client-search@5.23.4)(@types/node@25.0.9)(fuse.js@7.1.0)(lightningcss@1.30.2)(postcss@8.5.6)(search-insights@2.17.3)(sortablejs@1.15.6)(terser@5.39.0)(typescript@5.9.3):
dependencies:
'@docsearch/css': 3.8.2
'@docsearch/js': 3.8.2(@algolia/client-search@5.23.4)(search-insights@2.17.3)
@@ -7914,7 +7828,7 @@ snapshots:
'@shikijs/transformers': 2.5.0
'@shikijs/types': 2.5.0
'@types/markdown-it': 14.1.2
'@vitejs/plugin-vue': 5.2.4(vite@5.4.21(@types/node@25.0.6)(lightningcss@1.30.2)(terser@5.39.0))(vue@3.5.26(typescript@5.9.3))
'@vitejs/plugin-vue': 5.2.4(vite@5.4.21(@types/node@25.0.9)(lightningcss@1.30.2)(terser@5.39.0))(vue@3.5.26(typescript@5.9.3))
'@vue/devtools-api': 7.7.2
'@vue/shared': 3.5.18
'@vueuse/core': 12.8.2(typescript@5.9.3)
@@ -7923,7 +7837,7 @@ snapshots:
mark.js: 8.11.1
minisearch: 7.1.2
shiki: 2.5.0
vite: 5.4.21(@types/node@25.0.6)(lightningcss@1.30.2)(terser@5.39.0)
vite: 5.4.21(@types/node@25.0.9)(lightningcss@1.30.2)(terser@5.39.0)
vue: 3.5.26(typescript@5.9.3)
optionalDependencies:
postcss: 8.5.6
@@ -7954,15 +7868,15 @@ snapshots:
- typescript
- universal-cookie
vitest@4.0.16(@types/node@25.0.6)(jiti@2.6.1)(jsdom@27.4.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2):
vitest@4.0.17(@types/node@25.0.9)(jiti@2.6.1)(jsdom@27.4.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2):
dependencies:
'@vitest/expect': 4.0.16
'@vitest/mocker': 4.0.16(vite@7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
'@vitest/pretty-format': 4.0.16
'@vitest/runner': 4.0.16
'@vitest/snapshot': 4.0.16
'@vitest/spy': 4.0.16
'@vitest/utils': 4.0.16
'@vitest/expect': 4.0.17
'@vitest/mocker': 4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2))
'@vitest/pretty-format': 4.0.17
'@vitest/runner': 4.0.17
'@vitest/snapshot': 4.0.17
'@vitest/spy': 4.0.17
'@vitest/utils': 4.0.17
es-module-lexer: 1.7.0
expect-type: 1.3.0
magic-string: 0.30.21
@@ -7974,10 +7888,10 @@ snapshots:
tinyexec: 1.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vite: 7.3.1(@types/node@25.0.6)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.0)(tsx@4.19.2)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 25.0.6
'@types/node': 25.0.9
jsdom: 27.4.0(postcss@8.5.6)
transitivePeerDependencies:
- jiti