From ec5dc07078a07d3092ad79fd705011154b9e6284 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Mon, 20 Apr 2026 01:12:14 +0200 Subject: [PATCH 01/51] docs: add CHANGELOG for 1.0.0-rc.1 --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..101fa8c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +## [1.0.0-rc.1] — 2026-04-20 + +First public release candidate of Dashlight — a lightweight, self-hosted CI/CD dashboard for GitHub Actions. + +### Features + +#### Dashboard +- Repository health overview table with expandable workflows, per-repo success rate (last 100 runs), in-progress counts, and latest run cards +- Build activity chart (stacked area, last 30 days) and per-repository trend mini-charts +- Aggregate run statistics: total runs, succeeded, failed, cancelled, total duration + +#### Repositories +- Repository list with search/filter by name, description, language, or topics +- Per-repo language, last push time, last run status, and health score tier (Gold / Silver / Bronze) +- Repository detail page with workflow cards, build trend charts, run history, and a weighted health score across 7 categories (CI/CD, build success rate, security practices, documentation, maintenance, community health, branch protection) + +#### Runs +- Global runs list across all repositories with filter by repo, title, branch, or actor +- Repository-scoped runs list with pagination +- Run detail page with status summary, commit metadata, artifact downloads, re-run and cancel actions +- Job list with per-step status, duration, and runner information +- Job log viewer with step-level breakdown +- Job dependency graph (DAG) visualizing execution order and parallelism + +#### Authentication +- GitHub OAuth 2.0 login with PKCE (RFC 7636) and CSRF state token validation +- HttpOnly signed JWT session cookies — access token never sent to the browser +- Scopes: `repo`, `read:org`, `read:user`, `user:email` (public-only mode supported) + +#### Server & API +- Hono-based proxy server at `/proxy/*` forwarding to GitHub REST API +- ETag-based conditional revalidation (304 Not Modified) to minimize API quota usage +- In-flight request coalescing to prevent thundering herd on cache misses +- Write deduplication for mutating requests +- Smart TTL routing by data type (2 min for active runs → 7 days for completed logs) +- Repository list endpoint supporting explicit repo list, organization scope, or authenticated user repos +- Repository health score endpoint with on-demand refresh +- `/system/health` health check endpoint + +#### Caching +- Four-layer cache architecture: + - **L1** — TanStack Query in-memory cache with per-query stale times + - **L2** — IndexedDB persistence (24 h TTL, survives page reloads) + - **L3** — Server-side per-user LRU cache (configurable size, default 128 MB) + - **L4** — ETag stale store enabling zero-quota revalidation (24 h TTL) +- Auto-refetch intervals: 10 s for active runs, 30 s for run lists, 60 s for dashboard summaries + +#### Infrastructure +- Docker Compose setup with nginx reverse proxy and Node.js server — no external database required +- Environment-based configuration: OAuth credentials, session secret, optional org/repo filtering, proxy and CA certificate support +- CI pipeline: lint, typecheck, unit tests, Docker build on every PR and push to `develop` +- Release pipeline on `main`: automatic version bump, changelog generation, GitHub Release creation (Conventional Commits) From 4bf833de1109431d953de58b1e76e3d4a528c647 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Mon, 20 Apr 2026 01:16:27 +0200 Subject: [PATCH 02/51] fix: remove paths-ignore in release workflow --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 181d6ac..2ff7a88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,8 +3,6 @@ name: Release on: push: branches: [main] - paths-ignore: - - "**.md" workflow_dispatch: # Never cancel a release mid-flight; queue instead. From 957a2b0a9265f00d360fa40692a49f6448b4822f Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Mon, 20 Apr 2026 17:30:20 +0200 Subject: [PATCH 03/51] feat: replace runtime ca cert vars with build-time EXTRA_CA_CERTS_B64 injection --- .gitignore | 3 + README.md | 55 +++-- docker-compose.yml | 17 +- env.example | 37 ++-- packages/server/Dockerfile | 38 +++- packages/server/src/index.ts | 4 +- packages/server/src/lib/certs.test.ts | 221 -------------------- packages/server/src/lib/certs.ts | 60 ------ packages/server/src/lib/github.test.ts | 25 ++- packages/server/src/lib/github.ts | 13 +- packages/server/src/lib/startup-log.test.ts | 109 ++++++++++ packages/server/src/lib/startup-log.ts | 28 +++ packages/server/src/routes/auth.ts | 4 +- packages/web/Dockerfile | 23 +- 14 files changed, 281 insertions(+), 356 deletions(-) delete mode 100644 packages/server/src/lib/certs.test.ts delete mode 100644 packages/server/src/lib/certs.ts create mode 100644 packages/server/src/lib/startup-log.test.ts create mode 100644 packages/server/src/lib/startup-log.ts diff --git a/.gitignore b/.gitignore index 8762805..377ac06 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ Thumbs.db # pnpm pnpm-debug.log + +# Certificate build args — contains base64-encoded PEM data, never commit +.docker-certs.env diff --git a/README.md b/README.md index af79ce0..aa4165e 100644 --- a/README.md +++ b/README.md @@ -118,9 +118,7 @@ All variables are set in `.env` (copy from `env.example`). | `PORT` | `8080` | Internal server listen port (not exposed publicly) | | `LOG_LEVEL` | `info` | Server log verbosity: `debug` \| `info` \| `warn` \| `error` | | `CACHE_MAX_SIZE_MB` | `128` | In-memory LRU cache limit | -| `CA_CERT_HOST_FILE` | — | Host path to a PEM file — Docker Compose mounts it into the server container | -| `CA_CERT_PATH` | — | Path the server reads inside the container (use `/run/secrets/ca.pem` with the mount above) | -| `CA_CERT_BASE64` | — | Base64-encoded PEM — alternative to a file mount | +| `EXTRA_CA_CERTS_B64` | — | Build-time only. Base64-encoded PEM bundle injected into the image during `docker compose build`. See [Corporate CA certificate](#corporate-ca-certificate). | | `HTTPS_PROXY` / `HTTP_PROXY` | — | Corporate HTTP proxy for outbound requests to `api.github.com` | | `NO_PROXY` | — | Comma-separated hosts to bypass the proxy | | `TRUST_PROXY` | `true` | Trust `X-Forwarded-For` from nginx for rate limiting (set by Compose automatically) | @@ -191,34 +189,53 @@ If your reverse proxy terminates TLS and forwards to port 80 of the `web` contai ### Corporate CA certificate -If outbound HTTPS to `api.github.com` requires a custom CA (e.g. corporate TLS inspection), the certificate must be provided to the server container. The CA cert applies to all outbound connections — including the GitHub OAuth token exchange and all GitHub API calls. +If your Docker build environment intercepts outbound TLS (e.g. corporate proxy), you must inject the CA bundle at **build time** so that `pnpm install` and `tsc` can reach the registry. -**Option A — inline base64 (works everywhere)** +The certificate is baked into the image during `docker compose build` — it is not a runtime environment variable and does not need to be passed when starting containers. -The simplest option. Works with Docker Compose, plain `docker run`, Kubernetes, and any other runtime because the cert travels as an environment variable — no volume mount required. +**Single certificate** ```bash -CA_CERT_BASE64=$(base64 < my-ca.pem) # generate the value +# Encode the PEM file +# macOS +base64 < my-ca.pem > /tmp/bundle.b64 + +# Linux (suppress line wrapping — required for Docker build args) +base64 -w0 < my-ca.pem > /tmp/bundle.b64 + +# Write the build-arg env file +echo "EXTRA_CA_CERTS_B64=$(cat /tmp/bundle.b64)" > .docker-certs.env ``` -Set it in `.env`: +**Multiple certificates** -```env -CA_CERT_BASE64= +Concatenate all PEM files into one bundle before encoding — the Dockerfile appends the entire bundle to the system root store, so all CAs in the bundle will be trusted: + +```bash +# Concatenate and encode +# macOS +cat ca-1.pem ca-2.pem ca-3.pem | base64 > /tmp/bundle.b64 + +# Linux +cat ca-1.pem ca-2.pem ca-3.pem | base64 -w0 > /tmp/bundle.b64 + +# Write the build-arg env file +echo "EXTRA_CA_CERTS_B64=$(cat /tmp/bundle.b64)" > .docker-certs.env ``` -**Option B — file mount via Docker Compose** +**Build and run** -Keeps the PEM file on the host rather than embedding it in `.env`. Only works when started with `docker compose` — the mount is defined in `docker-compose.yml` and will not happen with a plain `docker run`. +```bash +# Build only +docker compose --env-file .env --env-file .docker-certs.env build -```env -# Host path (docker-compose.yml reads this to create the volume mount) -CA_CERT_HOST_FILE=./certs/my-ca.pem -# Path the server reads inside the container -CA_CERT_PATH=/run/secrets/ca.pem +# Build + start in one go +docker compose --env-file .env --env-file .docker-certs.env up -d ``` -If you run the container without Compose and set only `CA_CERT_PATH`, the server will warn at startup that the file cannot be read and continue without the custom CA. +> `.docker-certs.env` is gitignored — never commit it. It contains your CA certificates encoded as base64. + +If the build environment does **not** intercept TLS (home network, CI with public access), omit `--env-file .docker-certs.env` entirely — the build proceeds with the base image trust store only. --- @@ -240,7 +257,7 @@ Check `GITHUB_REPOS` and `GITHUB_ORG` in `.env`. If both are unset, all repos th The `web` container waits for the `server` container to pass its health check before starting. If the server exits immediately (missing required env var, bad `SESSION_SECRET`), run `docker compose logs server` to see the startup error. **GitHub API calls fail in a corporate network** -Set `HTTPS_PROXY` (and optionally `HTTP_PROXY`, `NO_PROXY`) in `.env`. These are passed to the server at runtime for all outbound calls to `api.github.com`. If the corporate proxy uses a private CA, also configure the CA cert (see above). +Set `HTTPS_PROXY` (and optionally `HTTP_PROXY`, `NO_PROXY`) in `.env`. These are passed to the server at runtime for all outbound calls to `api.github.com`. If the corporate proxy uses a private CA, inject it at build time via `EXTRA_CA_CERTS_B64` (see [Corporate CA certificate](#corporate-ca-certificate)). --- diff --git a/docker-compose.yml b/docker-compose.yml index 7eb2981..a386292 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,10 @@ services: build: context: . dockerfile: packages/server/Dockerfile + args: + # Build-time CA certificate — base64-encoded PEM bundle (see env.example). + # Pass via: docker compose --env-file .docker-certs.env build + EXTRA_CA_CERTS_B64: ${EXTRA_CA_CERTS_B64:-} # Not exposed publicly — nginx is the only ingress point. # Uncomment the line below to expose the server port for local debugging: # ports: @@ -25,19 +29,14 @@ services: TRUST_PROXY: "true" # Set to "true" only when serving over HTTPS (controls Secure cookie flag) COOKIE_SECURE: ${COOKIE_SECURE:-false} - # CA certificate for outbound HTTPS (e.g. corporate environment) - CA_CERT_PATH: ${CA_CERT_PATH:-} - CA_CERT_BASE64: ${CA_CERT_BASE64:-} - # Corporate HTTP proxy + # Corporate HTTP proxy (optional — picked up automatically by EnvHttpProxyAgent) HTTPS_PROXY: ${HTTPS_PROXY:-} HTTP_PROXY: ${HTTP_PROXY:-} NO_PROXY: ${NO_PROXY:-} LOG_LEVEL: ${LOG_LEVEL:-info} - volumes: - # Mount CA cert file if CA_CERT_HOST_FILE is set; falls back to /dev/null (no-op) - - ${CA_CERT_HOST_FILE:-/dev/null}:/run/secrets/ca.pem:ro healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost:8080/system/health"] + # Uses Node's built-in fetch — no curl dependency in the minimal runtime image. + test: ["CMD", "node", "-e", "fetch('http://localhost:8080/system/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 30s timeout: 5s retries: 3 @@ -50,6 +49,8 @@ services: build: context: . dockerfile: packages/web/Dockerfile + args: + EXTRA_CA_CERTS_B64: ${EXTRA_CA_CERTS_B64:-} ports: - "${WEB_PORT:-5174}:80" depends_on: diff --git a/env.example b/env.example index e416d97..78e8808 100644 --- a/env.example +++ b/env.example @@ -38,30 +38,21 @@ GITHUB_REPOS= # In-memory LRU cache max size in MB CACHE_MAX_SIZE_MB=128 -# ─── CA Certificate (optional) ─────────────────────────────────────────────── -# Use when the server needs to trust a custom CA (e.g. corporate / self-signed). +# ─── CA Certificate (optional, build-time only) ────────────────────────────── +# Use when Docker builds run in a corporate network that intercepts TLS. +# EXTRA_CA_CERTS_B64 is a BUILD ARG, not a runtime env var — the cert bundle is +# baked into the image during `docker compose build` and never passed at runtime. # -# How the three vars work together (Docker Compose workflow): -# 1. CA_CERT_HOST_FILE — path to the PEM file on your Docker *host*. -# docker-compose.yml mounts it into the container at /run/secrets/ca.pem. -# The server never reads this variable directly. -# 2. CA_CERT_PATH — path the server reads *inside the container*. -# Set to /run/secrets/ca.pem to pick up the mounted file from step 1. -# 3. CA_CERT_BASE64 — alternative to steps 1+2: paste the base64-encoded -# PEM directly here (run: base64 < my-ca.pem). No file mount needed. -# Takes precedence over CA_CERT_PATH when both are set. - -# Docker Compose only — host-side path that gets volume-mounted into the container -# e.g. ./certs/my-ca.pem -CA_CERT_HOST_FILE= - -# Server reads this path inside the container -# e.g. /run/secrets/ca.pem -CA_CERT_PATH= - -# Alternative: inline base64-encoded PEM (no file mount required) -# e.g. run: base64 < my-ca.pem -CA_CERT_BASE64= +# Encode your PEM file (or concatenated bundle for multiple CAs): +# base64 < my-ca.pem # macOS / Linux +# base64 -w0 < my-ca.pem # Linux (no line wrapping) +# +# Recommended: write to a separate env file and pass it to docker compose: +# echo "EXTRA_CA_CERTS_B64=$(base64 -w0 < my-ca.pem)" > .docker-certs.env +# docker compose --env-file .env --env-file .docker-certs.env build +# +# Leave empty for standard public TLS only. +EXTRA_CA_CERTS_B64= # ---- Corporate HTTP Proxy (optional) # If outbound HTTPS to api.github.com requires an HTTP proxy. diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 11ceb49..38af02c 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -8,6 +8,25 @@ ENV NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection WORKDIR /app +# ── Build-time CA certificate (optional) ────────────────────────────────────── +# Pass EXTRA_CA_CERTS_B64 (base64-encoded PEM bundle) to inject corporate CA +# trust before any networked build step runs (corepack, pnpm install, tsc). +# If unset the build continues with the base image trust store only. +ARG EXTRA_CA_CERTS_B64 +ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" +ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV SSL_CERT_FILE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV NODE_EXTRA_CA_CERTS="/opt/dashlight/extra-ca-certificates.pem" + +RUN mkdir -p /opt/dashlight && \ + cp /etc/ssl/certs/ca-certificates.crt "$DASHLIGHT_CA_BUNDLE" && \ + if [ -n "$EXTRA_CA_CERTS_B64" ]; then \ + printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > "$DASHLIGHT_EXTRA_CA_FILE" && \ + cat "$DASHLIGHT_EXTRA_CA_FILE" >> "$DASHLIGHT_CA_BUNDLE"; \ + else \ + : > "$DASHLIGHT_EXTRA_CA_FILE"; \ + fi + RUN corepack enable && corepack prepare pnpm@9.15.4 --activate # Copy workspace manifests first for layer caching @@ -27,20 +46,29 @@ RUN pnpm deploy --filter @dashlight/server --prod /standalone # ── Runtime stage ───────────────────────────────────────────────────────────── FROM node:24.3.0-alpine3.22 AS runner -# Upgrade OS packages to patch any CVEs present in the pinned base image, -# then install only what the healthcheck needs. +# Upgrade OS packages to patch any CVEs present in the pinned base image. RUN apk upgrade --no-cache && \ - addgroup -S dashlight && adduser -S dashlight -G dashlight && \ - apk add --no-cache curl + addgroup -S dashlight && adduser -S dashlight -G dashlight + WORKDIR /app +# Copy cert bundle from builder so the runtime Node process inherits build-time trust. +# NODE_EXTRA_CA_CERTS points to the extra-only PEM; SSL_CERT_FILE points to the +# merged bundle (system roots + extra) for non-Node TLS clients. +COPY --from=builder /opt/dashlight/ /opt/dashlight/ +ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" +ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV SSL_CERT_FILE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV NODE_EXTRA_CA_CERTS="/opt/dashlight/extra-ca-certificates.pem" + # pnpm deploy gives us a clean directory: package.json + node_modules + dist COPY --from=builder /standalone ./ USER dashlight EXPOSE 8080 +# Use Node's built-in fetch — no curl dependency required in the minimal runtime image. HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ - CMD curl -fsS http://localhost:8080/system/health || exit 1 + CMD node -e "fetch('http://localhost:8080/system/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["node", "dist/index.js"] diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index a9ffa8d..4c9febb 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -6,7 +6,7 @@ import { accessLog } from "./middleware/access-log.js" import { log } from "./lib/logger.js" import { rateLimitKey } from "./lib/rate-limit-key.js" import { validateSessionSecret } from "./lib/jwt.js" -import { logCertStatus } from "./lib/certs.js" +import { logStartupDiagnostics } from "./lib/startup-log.js" import { securityHeaders } from "./middleware/security.js" import authRoutes from "./routes/auth.js" import proxyRoutes from "./routes/proxy.js" @@ -28,7 +28,7 @@ for (const key of requiredEnv) { } } -logCertStatus() +logStartupDiagnostics() // ── App setup ───────────────────────────────────────────────────────────────── const app = new Hono() diff --git a/packages/server/src/lib/certs.test.ts b/packages/server/src/lib/certs.test.ts deleted file mode 100644 index 2f75acc..0000000 --- a/packages/server/src/lib/certs.test.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { describe, it, expect, vi, afterEach } from "vitest" - -// ── Mocks ───────────────────────────────────────────────────────────────────── - -vi.mock("./logger.js", () => ({ - log: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }, -})) - -vi.mock("node:fs", () => ({ - readFileSync: vi.fn(), -})) - -vi.mock("node:tls", () => ({ - rootCertificates: [ - "-----BEGIN CERTIFICATE-----\nROOT_A\n-----END CERTIFICATE-----", - "-----BEGIN CERTIFICATE-----\nROOT_B\n-----END CERTIFICATE-----", - ], -})) - -// ── Helpers ─────────────────────────────────────────────────────────────────── - -afterEach(() => { - vi.unstubAllEnvs() - vi.resetModules() - vi.clearAllMocks() -}) - -/** Re-import certs.ts with a clean module registry so module-level code reruns. */ -async function loadCerts() { - vi.resetModules() - const certs = await import("./certs.js") - // Import logger after certs so we get the same cached instance certs.ts uses. - const { log } = await import("./logger.js") - const { readFileSync } = await import("node:fs") - return { ...certs, log, readFileSync } -} - -// ── buildUndiciAgent ────────────────────────────────────────────────────────── - -describe("buildUndiciAgent", () => { - it("returns an EnvHttpProxyAgent", async () => { - const { buildUndiciAgent } = await loadCerts() - const { EnvHttpProxyAgent } = await import("undici") - expect(buildUndiciAgent()).toBeInstanceOf(EnvHttpProxyAgent) - }) - - it("returns an EnvHttpProxyAgent even when HTTPS_PROXY is set (NO_PROXY is handled internally)", async () => { - vi.stubEnv("HTTPS_PROXY", "http://proxy.example.com:8080") - const { buildUndiciAgent } = await loadCerts() - const { EnvHttpProxyAgent } = await import("undici") - expect(buildUndiciAgent()).toBeInstanceOf(EnvHttpProxyAgent) - }) - - it("returns an EnvHttpProxyAgent even when no proxy env vars are set", async () => { - vi.unstubAllEnvs() - delete process.env["HTTPS_PROXY"] - delete process.env["HTTP_PROXY"] - delete process.env["NO_PROXY"] - const { buildUndiciAgent } = await loadCerts() - const { EnvHttpProxyAgent } = await import("undici") - expect(buildUndiciAgent()).toBeInstanceOf(EnvHttpProxyAgent) - }) -}) - -// ── buildCaChain ────────────────────────────────────────────────────────────── - -describe("buildCaChain", () => { - it("returns an array containing the Node.js root certificates", async () => { - const { buildCaChain } = await loadCerts() - const chain = buildCaChain("custom-cert") - expect(chain).toContain("-----BEGIN CERTIFICATE-----\nROOT_A\n-----END CERTIFICATE-----") - expect(chain).toContain("-----BEGIN CERTIFICATE-----\nROOT_B\n-----END CERTIFICATE-----") - }) - - it("appends the custom cert after the root bundle, not instead of it", async () => { - const { buildCaChain } = await loadCerts() - const customCert = "-----BEGIN CERTIFICATE-----\nCUSTOM\n-----END CERTIFICATE-----" - const chain = buildCaChain(customCert) - expect(chain.at(-1)).toBe(customCert) - expect(chain.length).toBe(3) // 2 mocked roots + 1 custom - }) - - it("returns a new array on each call (no shared reference)", async () => { - const { buildCaChain } = await loadCerts() - const a = buildCaChain("cert-a") - const b = buildCaChain("cert-b") - expect(a).not.toBe(b) - }) -}) - -// ── loadCaCert (via caCert export) ─────────────────────────────────────────── - -describe("loadCaCert", () => { - it("decodes CA_CERT_BASE64 into a PEM string", async () => { - const pem = "-----BEGIN CERTIFICATE-----\nMIItest\n-----END CERTIFICATE-----" - vi.stubEnv("CA_CERT_BASE64", Buffer.from(pem).toString("base64")) - const { caCert } = await loadCerts() - expect(caCert).toBe(pem) - }) - - it("reads the file at CA_CERT_PATH when no base64 var is set", async () => { - vi.stubEnv("CA_CERT_PATH", "/etc/ssl/custom.crt") - vi.resetModules() - // Set up the readFileSync mock before importing certs - const { readFileSync } = await import("node:fs") - vi.mocked(readFileSync).mockReturnValue("file-cert-content") - const { caCert } = await import("./certs.js") - expect(caCert).toBe("file-cert-content") - }) - - it("prefers CA_CERT_BASE64 over CA_CERT_PATH when both are set", async () => { - const pem = "base64-cert" - vi.stubEnv("CA_CERT_BASE64", Buffer.from(pem).toString("base64")) - vi.stubEnv("CA_CERT_PATH", "/etc/ssl/custom.crt") - vi.resetModules() - const { readFileSync } = await import("node:fs") - vi.mocked(readFileSync).mockReturnValue("file-cert-content") - const { caCert } = await import("./certs.js") - expect(caCert).toBe(pem) - expect(vi.mocked(readFileSync)).not.toHaveBeenCalled() - }) - - it("warns and returns undefined when CA_CERT_PATH file cannot be read", async () => { - vi.stubEnv("CA_CERT_PATH", "/bad/path.crt") - vi.resetModules() - const { readFileSync } = await import("node:fs") - vi.mocked(readFileSync).mockImplementation(() => { throw new Error("ENOENT") }) - const { caCert } = await import("./certs.js") - const { log } = await import("./logger.js") - expect(caCert).toBeUndefined() - expect(vi.mocked(log.warn)).toHaveBeenCalledWith( - "Could not read CA_CERT_PATH", - { path: "/bad/path.crt" } - ) - }) - - it("returns undefined when neither CA_CERT_BASE64 nor CA_CERT_PATH is set", async () => { - delete process.env["CA_CERT_BASE64"] - delete process.env["CA_CERT_PATH"] - const { caCert } = await loadCerts() - expect(caCert).toBeUndefined() - }) -}) - -// ── logCertStatus ───────────────────────────────────────────────────────────── - -describe("logCertStatus", () => { - it("logs proxy URL and noProxy when HTTPS_PROXY is set", async () => { - vi.stubEnv("HTTPS_PROXY", "http://proxy.corp:8080") - vi.stubEnv("NO_PROXY", "localhost,127.0.0.1") - const { logCertStatus, log } = await loadCerts() - logCertStatus() - expect(vi.mocked(log.info)).toHaveBeenCalledWith("Outbound proxy configured", { - proxyUrl: "http://proxy.corp:8080", - noProxy: "localhost,127.0.0.1", - }) - }) - - it("falls back to HTTP_PROXY when HTTPS_PROXY is absent", async () => { - vi.stubEnv("HTTP_PROXY", "http://fallback:3128") - const { logCertStatus, log } = await loadCerts() - logCertStatus() - expect(vi.mocked(log.info)).toHaveBeenCalledWith("Outbound proxy configured", { - proxyUrl: "http://fallback:3128", - noProxy: "(none)", - }) - }) - - it("reports noProxy as '(none)' when NO_PROXY is not set", async () => { - vi.stubEnv("HTTPS_PROXY", "http://proxy:8080") - delete process.env["NO_PROXY"] - const { logCertStatus, log } = await loadCerts() - logCertStatus() - const call = vi.mocked(log.info).mock.calls.find((c) => c[0] === "Outbound proxy configured") - expect(call?.[1]?.noProxy).toBe("(none)") - }) - - it("does not log proxy info when no proxy env vars are set", async () => { - delete process.env["HTTPS_PROXY"] - delete process.env["HTTP_PROXY"] - const { logCertStatus, log } = await loadCerts() - logCertStatus() - const proxyCalls = vi.mocked(log.info).mock.calls.filter( - (c) => c[0] === "Outbound proxy configured" - ) - expect(proxyCalls).toHaveLength(0) - }) - - it("logs CA cert source as CA_CERT_BASE64 when that var is set", async () => { - vi.stubEnv("CA_CERT_BASE64", Buffer.from("cert").toString("base64")) - const { logCertStatus, log } = await loadCerts() - logCertStatus() - expect(vi.mocked(log.info)).toHaveBeenCalledWith("Custom CA certificate loaded", { - source: "CA_CERT_BASE64", - }) - }) - - it("logs CA cert source with path when CA_CERT_PATH is set", async () => { - vi.stubEnv("CA_CERT_PATH", "/etc/ssl/custom.crt") - vi.resetModules() - const { readFileSync } = await import("node:fs") - vi.mocked(readFileSync).mockReturnValue("cert-content") - const { logCertStatus } = await import("./certs.js") - const { log } = await import("./logger.js") - logCertStatus() - expect(vi.mocked(log.info)).toHaveBeenCalledWith("Custom CA certificate loaded", { - source: "CA_CERT_PATH (/etc/ssl/custom.crt)", - }) - }) - - it("does not log CA cert info when no cert vars are set", async () => { - delete process.env["CA_CERT_BASE64"] - delete process.env["CA_CERT_PATH"] - const { logCertStatus, log } = await loadCerts() - logCertStatus() - const certCalls = vi.mocked(log.info).mock.calls.filter( - (c) => c[0] === "Custom CA certificate loaded" - ) - expect(certCalls).toHaveLength(0) - }) -}) diff --git a/packages/server/src/lib/certs.ts b/packages/server/src/lib/certs.ts deleted file mode 100644 index 5828592..0000000 --- a/packages/server/src/lib/certs.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { readFileSync } from "node:fs" -import { rootCertificates } from "node:tls" -import { EnvHttpProxyAgent } from "undici" -import { log } from "./logger.js" - -function loadCaCert(): string | undefined { - if (process.env["CA_CERT_BASE64"]) { - return Buffer.from(process.env["CA_CERT_BASE64"], "base64").toString("utf8") - } - if (process.env["CA_CERT_PATH"]) { - try { - return readFileSync(process.env["CA_CERT_PATH"], "utf8") - } catch { - log.warn("Could not read CA_CERT_PATH", { path: process.env["CA_CERT_PATH"] }) - } - } - return undefined -} - -export const caCert = loadCaCert() - -/** - * Builds the full CA chain used for TLS verification. - * - * The custom cert is appended to Node.js's built-in Mozilla root bundle so - * that standard HTTPS connections (GitHub API, etc.) continue to work while - * the corporate CA is also trusted. Passing only the custom cert would - * discard the entire root bundle and break all other TLS connections. - */ -export function buildCaChain(customCert: string): string[] { - return [...rootCertificates, customCert] -} - -/** - * Returns an EnvHttpProxyAgent that automatically reads HTTP_PROXY, HTTPS_PROXY, - * and NO_PROXY from environment variables, bypassing the proxy for hosts listed - * in NO_PROXY. A custom CA certificate is applied when caCert is set. - */ -export function buildUndiciAgent(): EnvHttpProxyAgent { - return new EnvHttpProxyAgent( - caCert ? { connect: { ca: buildCaChain(caCert) } } : {} - ) -} - -export function logCertStatus(): void { - if (caCert) { - const source = process.env["CA_CERT_BASE64"] - ? "CA_CERT_BASE64" - : `CA_CERT_PATH (${process.env["CA_CERT_PATH"]})` - log.info("Custom CA certificate loaded", { source }) - } - - const proxyUrl = process.env["HTTPS_PROXY"] ?? process.env["HTTP_PROXY"] - if (proxyUrl) { - log.info("Outbound proxy configured", { - proxyUrl, - noProxy: process.env["NO_PROXY"] ?? "(none)", - }) - } -} diff --git a/packages/server/src/lib/github.test.ts b/packages/server/src/lib/github.test.ts index d27ba8c..ba87989 100644 --- a/packages/server/src/lib/github.test.ts +++ b/packages/server/src/lib/github.test.ts @@ -1,7 +1,8 @@ import { describe, it, expect, vi, beforeEach } from "vitest" -import { githubFetch, GitHubApiError, GitHubNotFoundError, GitHubRateLimitError } from "./github.js" +import { githubFetch, GitHubApiError, GitHubNotFoundError, GitHubRateLimitError, agent } from "./github.js" -// Mock undici at the module level +// Mock undici — spread actual so EnvHttpProxyAgent is the real class (needed for instanceof +// check on agent), override only request to intercept network calls in tests. vi.mock("undici", async (importOriginal) => { const actual = await importOriginal() return { @@ -10,14 +11,7 @@ vi.mock("undici", async (importOriginal) => { } }) -// Mock certs so no real network/file access happens -vi.mock("./certs.js", () => ({ - buildUndiciAgent: () => ({}), - caCert: undefined, - logCertStatus: () => {}, -})) - -import { request } from "undici" +import { request, EnvHttpProxyAgent } from "undici" const mockRequest = vi.mocked(request) @@ -39,6 +33,17 @@ beforeEach(() => { vi.clearAllMocks() }) +// ── agent ───────────────────────────────────────────────────────────────────── + +describe("agent", () => { + it("is an EnvHttpProxyAgent instance", () => { + // EnvHttpProxyAgent reads HTTPS_PROXY, HTTP_PROXY, and NO_PROXY automatically. + // NODE_EXTRA_CA_CERTS (baked in at build time) is inherited via Node's default + // TLS context — no explicit ca option is needed on the agent. + expect(agent).toBeInstanceOf(EnvHttpProxyAgent) + }) +}) + describe("githubFetch", () => { it("returns parsed JSON data on 200", async () => { mockRequest.mockResolvedValueOnce(makeResponse(200, { id: 1, name: "repo" }) as never) diff --git a/packages/server/src/lib/github.ts b/packages/server/src/lib/github.ts index 05ef675..f13d0ed 100644 --- a/packages/server/src/lib/github.ts +++ b/packages/server/src/lib/github.ts @@ -1,12 +1,15 @@ -import { request } from "undici" -import { buildUndiciAgent } from "./certs.js" +import { request, EnvHttpProxyAgent } from "undici" import { log } from "./logger.js" const GITHUB_API_BASE = "https://api.github.com" -// Single shared agent — carries the custom CA cert and proxy config for all -// outbound HTTPS. Exported so auth.ts can use it for the token exchange too. -export const agent = buildUndiciAgent() +// Single shared agent for all outbound HTTPS — exported so auth.ts can reuse it. +// +// NOTE: NODE_EXTRA_CA_CERTS is baked into the image at build time via EXTRA_CA_CERTS_B64. +// Node.js loads it into its default TLS context at process startup; EnvHttpProxyAgent +// inherits that context automatically — no explicit ca option is needed here. +// Proxy env vars (HTTPS_PROXY, HTTP_PROXY, NO_PROXY) are also picked up automatically. +export const agent = new EnvHttpProxyAgent() const RETRY_DELAYS_MS = [500, 1000, 2000] // 429 is intentionally excluded: rate-limit windows are hourly, short retries are useless diff --git a/packages/server/src/lib/startup-log.test.ts b/packages/server/src/lib/startup-log.test.ts new file mode 100644 index 0000000..ce150f0 --- /dev/null +++ b/packages/server/src/lib/startup-log.test.ts @@ -0,0 +1,109 @@ +import { describe, it, expect, vi, afterEach } from "vitest" + +vi.mock("./logger.js", () => ({ + log: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }, +})) + +afterEach(() => { + vi.unstubAllEnvs() + vi.resetModules() + vi.clearAllMocks() +}) + +async function load() { + vi.resetModules() + const mod = await import("./startup-log.js") + const { log } = await import("./logger.js") + return { ...mod, log } +} + +// ── CA bundle logging ───────────────────────────────────────────────────────── + +describe("logStartupDiagnostics — CA bundle", () => { + it("logs path when NODE_EXTRA_CA_CERTS is set", async () => { + vi.stubEnv("NODE_EXTRA_CA_CERTS", "/opt/dashlight/extra-ca-certificates.pem") + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + expect(vi.mocked(log.info)).toHaveBeenCalledWith("Build-time CA bundle active", { + path: "/opt/dashlight/extra-ca-certificates.pem", + }) + }) + + it("does not log CA bundle info when NODE_EXTRA_CA_CERTS is not set", async () => { + delete process.env["NODE_EXTRA_CA_CERTS"] + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + const caCalls = vi.mocked(log.info).mock.calls.filter( + (c) => c[0] === "Build-time CA bundle active" + ) + expect(caCalls).toHaveLength(0) + }) + + it("never logs the cert value itself", async () => { + vi.stubEnv("NODE_EXTRA_CA_CERTS", "/opt/dashlight/extra-ca-certificates.pem") + // Simulate a real cert file path — value should never appear in log output + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + const allArgs = JSON.stringify(vi.mocked(log.info).mock.calls) + expect(allArgs).not.toContain("BEGIN CERTIFICATE") + expect(allArgs).not.toContain("END CERTIFICATE") + }) +}) + +// ── Proxy logging ───────────────────────────────────────────────────────────── + +describe("logStartupDiagnostics — proxy", () => { + it("logs proxy URL and noProxy when HTTPS_PROXY is set", async () => { + vi.stubEnv("HTTPS_PROXY", "http://proxy.corp:8080") + vi.stubEnv("NO_PROXY", "localhost,127.0.0.1") + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + expect(vi.mocked(log.info)).toHaveBeenCalledWith("Outbound proxy configured", { + proxyUrl: "http://proxy.corp:8080", + noProxy: "localhost,127.0.0.1", + }) + }) + + it("falls back to HTTP_PROXY when HTTPS_PROXY is absent", async () => { + vi.stubEnv("HTTP_PROXY", "http://fallback:3128") + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + expect(vi.mocked(log.info)).toHaveBeenCalledWith("Outbound proxy configured", { + proxyUrl: "http://fallback:3128", + noProxy: "(none)", + }) + }) + + it("prefers HTTPS_PROXY over HTTP_PROXY when both are set", async () => { + vi.stubEnv("HTTPS_PROXY", "http://primary:8080") + vi.stubEnv("HTTP_PROXY", "http://fallback:3128") + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + const call = vi.mocked(log.info).mock.calls.find( + (c) => c[0] === "Outbound proxy configured" + ) + expect(call?.[1]?.proxyUrl).toBe("http://primary:8080") + }) + + it("reports noProxy as '(none)' when NO_PROXY is not set", async () => { + vi.stubEnv("HTTPS_PROXY", "http://proxy:8080") + delete process.env["NO_PROXY"] + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + const call = vi.mocked(log.info).mock.calls.find( + (c) => c[0] === "Outbound proxy configured" + ) + expect(call?.[1]?.noProxy).toBe("(none)") + }) + + it("does not log proxy info when no proxy env vars are set", async () => { + delete process.env["HTTPS_PROXY"] + delete process.env["HTTP_PROXY"] + const { logStartupDiagnostics, log } = await load() + logStartupDiagnostics() + const proxyCalls = vi.mocked(log.info).mock.calls.filter( + (c) => c[0] === "Outbound proxy configured" + ) + expect(proxyCalls).toHaveLength(0) + }) +}) diff --git a/packages/server/src/lib/startup-log.ts b/packages/server/src/lib/startup-log.ts new file mode 100644 index 0000000..bd1787d --- /dev/null +++ b/packages/server/src/lib/startup-log.ts @@ -0,0 +1,28 @@ +import { log } from "./logger.js" + +/** + * Logs build-time CA bundle status and outbound proxy configuration at startup. + * + * CA trust: + * NODE_EXTRA_CA_CERTS is baked into the image at build time via EXTRA_CA_CERTS_B64. + * Node.js loads it into its default TLS context at process startup; EnvHttpProxyAgent + * in github.ts inherits that context automatically — no explicit ca option needed. + * The cert path is logged for diagnostics; the cert value itself is never logged. + * + * Proxy: + * EnvHttpProxyAgent reads HTTPS_PROXY, HTTP_PROXY, and NO_PROXY automatically. + * This log entry confirms the values active at startup. + */ +export function logStartupDiagnostics(): void { + if (process.env["NODE_EXTRA_CA_CERTS"]) { + log.info("Build-time CA bundle active", { path: process.env["NODE_EXTRA_CA_CERTS"] }) + } + + const proxyUrl = process.env["HTTPS_PROXY"] ?? process.env["HTTP_PROXY"] + if (proxyUrl) { + log.info("Outbound proxy configured", { + proxyUrl, + noProxy: process.env["NO_PROXY"] ?? "(none)", + }) + } +} diff --git a/packages/server/src/routes/auth.ts b/packages/server/src/routes/auth.ts index 1182737..2bc08fa 100644 --- a/packages/server/src/routes/auth.ts +++ b/packages/server/src/routes/auth.ts @@ -102,8 +102,8 @@ auth.get("/callback", async (c) => { c.header("Set-Cookie", `pkce_verifier=; ${clearCookieFlags}`, { append: true }) // Exchange code for token. - // Uses the shared undici agent so the custom CA cert and corporate proxy - // (CA_CERT_BASE64 / CA_CERT_PATH / HTTPS_PROXY) apply here too. + // Uses the shared undici agent — NODE_EXTRA_CA_CERTS (baked in at build time) + // and HTTPS_PROXY / HTTP_PROXY / NO_PROXY are picked up automatically. let tokenData: GitHubTokenResponse try { const tokenRes = await request(GITHUB_OAUTH_TOKEN, { diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index 44c8b7b..e1b2210 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -8,6 +8,25 @@ ENV NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection WORKDIR /app +# ── Build-time CA certificate (optional) ────────────────────────────────────── +# Pass EXTRA_CA_CERTS_B64 (base64-encoded PEM bundle) to inject corporate CA +# trust before any networked build step runs (corepack, pnpm install, vite build). +# If unset the build continues with the base image trust store only. +ARG EXTRA_CA_CERTS_B64 +ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" +ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV SSL_CERT_FILE="/opt/dashlight/ca-certificates-with-extra.pem" +ENV NODE_EXTRA_CA_CERTS="/opt/dashlight/extra-ca-certificates.pem" + +RUN mkdir -p /opt/dashlight && \ + cp /etc/ssl/certs/ca-certificates.crt "$DASHLIGHT_CA_BUNDLE" && \ + if [ -n "$EXTRA_CA_CERTS_B64" ]; then \ + printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > "$DASHLIGHT_EXTRA_CA_FILE" && \ + cat "$DASHLIGHT_EXTRA_CA_FILE" >> "$DASHLIGHT_CA_BUNDLE"; \ + else \ + : > "$DASHLIGHT_EXTRA_CA_FILE"; \ + fi + RUN corepack enable && corepack prepare pnpm@9.15.4 --activate # Copy workspace manifests first for layer caching @@ -23,6 +42,7 @@ COPY packages/web/tsconfig.json packages/web/vite.config.ts ./packages/web/ RUN pnpm --filter @dashlight/web build # ── Runtime stage (Nginx) ───────────────────────────────────────────────────── +# The nginx runner serves only static files — no outbound HTTPS, no cert bundle needed. FROM nginx:1.29.8-alpine AS runner # Upgrade OS packages to patch any CVEs present in the pinned base image. @@ -33,5 +53,6 @@ COPY packages/web/nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 +# wget is available in nginx-alpine; no curl needed. HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ - CMD curl -fsS http://localhost/nginx-health || exit 1 + CMD wget -qO- http://localhost/nginx-health || exit 1 From 4888f47649e7f59aedf1f01d8d2e5749d79ae763 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:00:22 +0200 Subject: [PATCH 04/51] fix: docker ca & npmrc handling, cert env generation, switch from corepack to npm install (#21) --- .gitignore | 1 + README.md | 97 +++- env.example | 18 +- package.json | 3 +- packages/server/Dockerfile | 32 +- packages/server/src/lib/github.ts | 196 +++++--- packages/server/src/routes/auth.test.ts | 462 ++++++++++-------- packages/server/src/routes/auth.ts | 212 ++++---- packages/web/Dockerfile | 25 +- .../generate-docker-certs-env.test.mjs | 98 ++++ scripts/generate-docker-certs-env.mjs | 113 +++++ 11 files changed, 837 insertions(+), 420 deletions(-) create mode 100644 scripts/__tests__/generate-docker-certs-env.test.mjs create mode 100644 scripts/generate-docker-certs-env.mjs diff --git a/.gitignore b/.gitignore index 377ac06..60d06ba 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ dist/ .env .env.local +.npmrc *.local # Build outputs diff --git a/README.md b/README.md index aa4165e..a4e912d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,27 @@ GITHUB_ORG=my-company GITHUB_REPOS=my-company/api,my-company/web ``` +**3b. (Optional) Private npm registry via `.npmrc`** + +If your organization uses a private npm registry (for example Artifactory, Nexus, or GitHub Packages), configure a project-level `.npmrc` in the repository root. + +Use placeholder values like this and replace with your own internal settings: + +```ini +registry=https://registry.example.internal/api/npm/npm-virtual/ +always-auth=true +//registry.example.internal/api/npm/npm-virtual/:_auth= +//registry.example.internal/api/npm/npm-virtual/:email=devnull@example.internal +``` + +Notes: + +- Keep the host/path in auth lines exactly aligned with the `registry=` URL path. +- Prefer a dedicated robot/service account token with least required permissions. +- Do not commit real credentials. Keep real auth values in local-only files or CI secrets. + +If your registry uses a private CA, also follow [Corporate CA certificate](#corporate-ca-certificate) so Docker build stages can trust TLS during `pnpm install`. + **4. Build and start** ```bash @@ -193,46 +214,80 @@ If your Docker build environment intercepts outbound TLS (e.g. corporate proxy), The certificate is baked into the image during `docker compose build` — it is not a runtime environment variable and does not need to be passed when starting containers. -**Single certificate** +Dashlight includes a helper script that normalizes one or more certificate files and writes `.docker-certs.env` for you: ```bash -# Encode the PEM file -# macOS -base64 < my-ca.pem > /tmp/bundle.b64 +pnpm certs:docker-env -- [cert2 ...] +``` + +The script supports both input formats automatically (per file): -# Linux (suppress line wrapping — required for Docker build args) -base64 -w0 < my-ca.pem > /tmp/bundle.b64 +- Real PEM text (`-----BEGIN CERTIFICATE----- ...`) +- Base64-wrapped PEM text (content starts with `LS0t...`) -# Write the build-arg env file -echo "EXTRA_CA_CERTS_B64=$(cat /tmp/bundle.b64)" > .docker-certs.env +It combines all provided certs in memory and writes a single line to `.docker-certs.env`: + +```env +EXTRA_CA_CERTS_B64= +``` + +No intermediate combined certificate file is created. + +**How the Docker TLS env vars are used** + +- `DASHLIGHT_EXTRA_CA_FILE`: file containing only injected custom CA certificates. +- `DASHLIGHT_CA_BUNDLE`: merged CA bundle (system roots + custom certs). +- `SSL_CERT_FILE`: points OpenSSL-based clients to the merged bundle. +- `NODE_EXTRA_CA_CERTS`: tells Node.js to append custom certs to Node's default trust. + +This split keeps trust explicit and debuggable: custom certs stay isolated, while runtime/build tools still retain default public CA trust. + +**Single certificate** + +```bash +pnpm certs:docker-env -- my-ca.pem ``` **Multiple certificates** -Concatenate all PEM files into one bundle before encoding — the Dockerfile appends the entire bundle to the system root store, so all CAs in the bundle will be trusted: +Pass all cert files as arguments. The script normalizes and combines them: + +```bash +pnpm certs:docker-env -- ca-1.pem ca-2.pem ca-3.pem +``` + +**Quick validation (optional)** + +`EXTRA_CA_CERTS_B64` should decode once to PEM and should not require a second decode: ```bash -# Concatenate and encode -# macOS -cat ca-1.pem ca-2.pem ca-3.pem | base64 > /tmp/bundle.b64 +val=$(awk -F= '/^EXTRA_CA_CERTS_B64=/{print substr($0,index($0,"=")+1)}' .docker-certs.env) +printf '%s' "$val" | base64 -d | head -n 2 +``` -# Linux -cat ca-1.pem ca-2.pem ca-3.pem | base64 -w0 > /tmp/bundle.b64 +Expected output starts with: -# Write the build-arg env file -echo "EXTRA_CA_CERTS_B64=$(cat /tmp/bundle.b64)" > .docker-certs.env +```text +-----BEGIN CERTIFICATE----- ``` -**Build and run** +**Build and run (recommended sequence)** ```bash -# Build only -docker compose --env-file .env --env-file .docker-certs.env build +docker compose --env-file .env --env-file .docker-certs.env build --no-cache +docker compose --env-file .env --env-file .docker-certs.env up -d --force-recreate +``` -# Build + start in one go -docker compose --env-file .env --env-file .docker-certs.env up -d +**Verify certificate in the running server container (optional)** + +Use this to quickly confirm that the runtime extra CA file exists and begins with PEM content: + +```bash +docker compose exec -T server sh -lc "head -c 40 /opt/dashlight/extra-ca-certificates.pem && echo" ``` +> `docker compose up` in this environment does not support `--no-cache`. Use `--no-cache` only with `docker compose build`. + > `.docker-certs.env` is gitignored — never commit it. It contains your CA certificates encoded as base64. If the build environment does **not** intercept TLS (home network, CI with public access), omit `--env-file .docker-certs.env` entirely — the build proceeds with the base image trust store only. diff --git a/env.example b/env.example index 78e8808..296356e 100644 --- a/env.example +++ b/env.example @@ -36,23 +36,7 @@ GITHUB_REPOS= # ---- # In-memory LRU cache max size in MB -CACHE_MAX_SIZE_MB=128 - -# ─── CA Certificate (optional, build-time only) ────────────────────────────── -# Use when Docker builds run in a corporate network that intercepts TLS. -# EXTRA_CA_CERTS_B64 is a BUILD ARG, not a runtime env var — the cert bundle is -# baked into the image during `docker compose build` and never passed at runtime. -# -# Encode your PEM file (or concatenated bundle for multiple CAs): -# base64 < my-ca.pem # macOS / Linux -# base64 -w0 < my-ca.pem # Linux (no line wrapping) -# -# Recommended: write to a separate env file and pass it to docker compose: -# echo "EXTRA_CA_CERTS_B64=$(base64 -w0 < my-ca.pem)" > .docker-certs.env -# docker compose --env-file .env --env-file .docker-certs.env build -# -# Leave empty for standard public TLS only. -EXTRA_CA_CERTS_B64= +CACHE_MAX_SIZE_MB=128s # ---- Corporate HTTP Proxy (optional) # If outbound HTTPS to api.github.com requires an HTTP proxy. diff --git a/package.json b/package.json index 4e6a5b9..06708db 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "typecheck": "pnpm -r typecheck", "lint": "pnpm -r lint", "test": "pnpm -r --parallel test", + "certs:docker-env": "node scripts/generate-docker-certs-env.mjs", "test:web": "pnpm --filter @dashlight/web test", "test:server": "pnpm --filter @dashlight/server test", "test:coverage": "pnpm -r --parallel test:coverage", @@ -29,4 +30,4 @@ "typescript": "catalog:", "vitest": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 38af02c..56349e9 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -1,17 +1,15 @@ # ── Build stage ────────────────────────────────────────────────────────────── -# Context: repo root (set in docker-compose.yml) FROM node:24-alpine AS builder # Docker Desktop's build network has no IPv6 routing; force Node.js to prefer -# IPv4 so corepack/pnpm can reach registry.npmjs.org without timing out. +# IPv4 so npm/pnpm can reach registry.npmjs.org without timing out. ENV NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection" WORKDIR /app # ── Build-time CA certificate (optional) ────────────────────────────────────── # Pass EXTRA_CA_CERTS_B64 (base64-encoded PEM bundle) to inject corporate CA -# trust before any networked build step runs (corepack, pnpm install, tsc). -# If unset the build continues with the base image trust store only. +# trust before any networked build step runs (npm install, pnpm install, tsc). ARG EXTRA_CA_CERTS_B64 ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" @@ -21,13 +19,25 @@ ENV NODE_EXTRA_CA_CERTS="/opt/dashlight/extra-ca-certificates.pem" RUN mkdir -p /opt/dashlight && \ cp /etc/ssl/certs/ca-certificates.crt "$DASHLIGHT_CA_BUNDLE" && \ if [ -n "$EXTRA_CA_CERTS_B64" ]; then \ - printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > "$DASHLIGHT_EXTRA_CA_FILE" && \ + printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > /tmp/dashlight-extra-ca-decoded && \ + if grep -q 'BEGIN CERTIFICATE' /tmp/dashlight-extra-ca-decoded; then \ + mv /tmp/dashlight-extra-ca-decoded "$DASHLIGHT_EXTRA_CA_FILE"; \ + else \ + base64 -d /tmp/dashlight-extra-ca-decoded > "$DASHLIGHT_EXTRA_CA_FILE" && \ + rm -f /tmp/dashlight-extra-ca-decoded; \ + fi && \ cat "$DASHLIGHT_EXTRA_CA_FILE" >> "$DASHLIGHT_CA_BUNDLE"; \ else \ : > "$DASHLIGHT_EXTRA_CA_FILE"; \ fi -RUN corepack enable && corepack prepare pnpm@9.15.4 --activate +# Copy .npmrc if present (e.g. for corporate Artifactory proxy credentials). +# Create an empty .npmrc first so the COPY never fails when the file is absent. +RUN touch /root/.npmrc +COPY .npmrc* /root/ + +# Simpler bootstrap path: npm respects /root/.npmrc for registry/auth. +RUN npm install -g pnpm@9.15.4 # Copy workspace manifests first for layer caching COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ @@ -46,16 +56,16 @@ RUN pnpm deploy --filter @dashlight/server --prod /standalone # ── Runtime stage ───────────────────────────────────────────────────────────── FROM node:24.3.0-alpine3.22 AS runner -# Upgrade OS packages to patch any CVEs present in the pinned base image. -RUN apk upgrade --no-cache && \ - addgroup -S dashlight && adduser -S dashlight -G dashlight +# Copy cert bundle from builder for Node/runtime TLS trust. +COPY --from=builder /opt/dashlight/ /opt/dashlight/ + +RUN addgroup -S dashlight && adduser -S dashlight -G dashlight WORKDIR /app -# Copy cert bundle from builder so the runtime Node process inherits build-time trust. +# Runtime Node process inherits build-time trust through environment variables. # NODE_EXTRA_CA_CERTS points to the extra-only PEM; SSL_CERT_FILE points to the # merged bundle (system roots + extra) for non-Node TLS clients. -COPY --from=builder /opt/dashlight/ /opt/dashlight/ ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" ENV SSL_CERT_FILE="/opt/dashlight/ca-certificates-with-extra.pem" diff --git a/packages/server/src/lib/github.ts b/packages/server/src/lib/github.ts index f13d0ed..4d3865e 100644 --- a/packages/server/src/lib/github.ts +++ b/packages/server/src/lib/github.ts @@ -1,60 +1,71 @@ -import { request, EnvHttpProxyAgent } from "undici" -import { log } from "./logger.js" +import { existsSync, readFileSync } from "node:fs"; +import { request, EnvHttpProxyAgent } from "undici"; +import { log } from "./logger.js"; -const GITHUB_API_BASE = "https://api.github.com" +const GITHUB_API_BASE = "https://api.github.com"; // Single shared agent for all outbound HTTPS — exported so auth.ts can reuse it. // -// NOTE: NODE_EXTRA_CA_CERTS is baked into the image at build time via EXTRA_CA_CERTS_B64. -// Node.js loads it into its default TLS context at process startup; EnvHttpProxyAgent -// inherits that context automatically — no explicit ca option is needed here. -// Proxy env vars (HTTPS_PROXY, HTTP_PROXY, NO_PROXY) are also picked up automatically. -export const agent = new EnvHttpProxyAgent() +// In this environment plain Node HTTPS picks up the extra CA bundle, but undici's +// EnvHttpProxyAgent does not reliably inherit it. Load the merged runtime CA bundle +// explicitly so outbound GitHub requests trust the same corporate MITM/root chain. +// Proxy env vars (HTTPS_PROXY, HTTP_PROXY, NO_PROXY) are still picked up automatically. +function loadAgentCa(): string | undefined { + const caPath = process.env["SSL_CERT_FILE"]; + if (!caPath || !existsSync(caPath)) return undefined; + return readFileSync(caPath, "utf8"); +} + +const agentCa = loadAgentCa(); -const RETRY_DELAYS_MS = [500, 1000, 2000] +export const agent = new EnvHttpProxyAgent( + agentCa ? { connect: { ca: agentCa } } : {}, +); + +const RETRY_DELAYS_MS = [500, 1000, 2000]; // 429 is intentionally excluded: rate-limit windows are hourly, short retries are useless // and amplify consumption. GitHubRateLimitError is thrown instead. -const RETRYABLE_STATUS = new Set([502, 503, 504]) +const RETRYABLE_STATUS = new Set([502, 503, 504]); export interface GitHubFetchOptions { - method?: "GET" | "POST" | "PATCH" | "DELETE" - body?: unknown - signal?: AbortSignal + method?: "GET" | "POST" | "PATCH" | "DELETE"; + body?: unknown; + signal?: AbortSignal; /** If provided, sent as If-None-Match for a conditional GET (ETag revalidation). */ - etag?: string + etag?: string; /** * Follow a single HTTP 302 redirect and return the response body as raw text. * Needed for GitHub log endpoints which redirect to signed S3 URLs. */ - followRedirect?: boolean + followRedirect?: boolean; } export interface GitHubFetchResult { - data: T - rateLimitRemaining: number | null - rateLimitReset: number | null - status: number + data: T; + rateLimitRemaining: number | null; + rateLimitReset: number | null; + status: number; /** ETag returned by GitHub, if any. Store alongside cached data for future revalidation. */ - etag: string | null + etag: string | null; /** OAuth scopes granted to this token — present on successful responses. */ - grantedScopes: string | null + grantedScopes: string | null; } export async function githubFetch( token: string, path: string, - options: GitHubFetchOptions = {} + options: GitHubFetchOptions = {}, ): Promise> { - const { method = "GET", body, signal, etag, followRedirect } = options - const effectiveSignal = signal ?? AbortSignal.timeout(30_000) - const url = path.startsWith("http") ? path : `${GITHUB_API_BASE}${path}` + const { method = "GET", body, signal, etag, followRedirect } = options; + const effectiveSignal = signal ?? AbortSignal.timeout(30_000); + const url = path.startsWith("http") ? path : `${GITHUB_API_BASE}${path}`; - let lastError: Error | undefined + let lastError: Error | undefined; for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) { if (attempt > 0) { - const delay = RETRY_DELAYS_MS[attempt - 1] ?? 2000 - await sleep(delay) + const delay = RETRY_DELAYS_MS[attempt - 1] ?? 2000; + await sleep(delay); } try { @@ -71,41 +82,56 @@ export async function githubFetch( body: body !== undefined ? JSON.stringify(body) : null, dispatcher: agent, signal: effectiveSignal, - }) + }); - const status = response.statusCode - const rateLimitRemaining = parseIntHeader(response.headers["x-ratelimit-remaining"]) - const rateLimitReset = parseIntHeader(response.headers["x-ratelimit-reset"]) - const responseEtag = parseStringHeader(response.headers["etag"]) + const status = response.statusCode; + const rateLimitRemaining = parseIntHeader( + response.headers["x-ratelimit-remaining"], + ); + const rateLimitReset = parseIntHeader( + response.headers["x-ratelimit-reset"], + ); + const responseEtag = parseStringHeader(response.headers["etag"]); if (RETRYABLE_STATUS.has(status) && attempt < RETRY_DELAYS_MS.length) { - await response.body.text() // drain before retry - lastError = new Error(`GitHub API returned ${status}`) - continue + await response.body.text(); // drain before retry + lastError = new Error(`GitHub API returned ${status}`); + continue; } // 304 Not Modified: free conditional response (0 quota points), no body if (status === 304) { - await response.body.text() // drain (usually empty) - return { data: null as unknown as T, rateLimitRemaining, rateLimitReset, status: 304, etag: etag ?? null, grantedScopes: null } + await response.body.text(); // drain (usually empty) + return { + data: null as unknown as T, + rateLimitRemaining, + rateLimitReset, + status: 304, + etag: etag ?? null, + grantedScopes: null, + }; } - const text = await response.body.text() + const text = await response.body.text(); // 302 Redirect: follow to get actual content (e.g. log files on signed S3 URLs) if (status === 302) { if (!followRedirect) { - throw new GitHubApiError(`Unexpected redirect for ${path}`, 302) + throw new GitHubApiError(`Unexpected redirect for ${path}`, 302); } - const location = parseStringHeader(response.headers["location"]) - if (!location) throw new GitHubApiError(`302 redirect with no Location for ${path}`, 502) + const location = parseStringHeader(response.headers["location"]); + if (!location) + throw new GitHubApiError( + `302 redirect with no Location for ${path}`, + 502, + ); // Fetch the signed URL directly — no GitHub auth headers; S3 uses query-param sig const redirectResponse = await request(location, { method: "GET", dispatcher: agent, signal: effectiveSignal, - }) - const redirectText = await redirectResponse.body.text() + }); + const redirectText = await redirectResponse.body.text(); return { data: redirectText as unknown as T, rateLimitRemaining, @@ -113,32 +139,45 @@ export async function githubFetch( status: redirectResponse.statusCode, etag: null, grantedScopes: null, - } + }; } // 429 Rate Limited: not retriable with short delays — throw immediately if (status === 429) { - throw new GitHubRateLimitError(rateLimitReset) + throw new GitHubRateLimitError(rateLimitReset); } if (status >= 400) { - let message = `GitHub API error ${status}: ${path}` + let message = `GitHub API error ${status}: ${path}`; try { - const parsed = JSON.parse(text) as { message?: string } - if (parsed.message) message = parsed.message - } catch { /* ignore */ } - const grantedScopes = parseStringHeader(response.headers["x-oauth-scopes"]) - log.error("GitHub API error", { status, path, message, grantedScopes }) - if (status === 404) throw new GitHubNotFoundError(message) - throw new GitHubApiError(message, status) + const parsed = JSON.parse(text) as { message?: string }; + if (parsed.message) message = parsed.message; + } catch { + /* ignore */ + } + const grantedScopes = parseStringHeader( + response.headers["x-oauth-scopes"], + ); + log.error("GitHub API error", { status, path, message, grantedScopes }); + if (status === 404) throw new GitHubNotFoundError(message); + throw new GitHubApiError(message, status); } // 204 No Content if (status === 204 || !text) { - return { data: null as unknown as T, rateLimitRemaining, rateLimitReset, status, etag: null, grantedScopes: null } + return { + data: null as unknown as T, + rateLimitRemaining, + rateLimitReset, + status, + etag: null, + grantedScopes: null, + }; } - const grantedScopes = parseStringHeader(response.headers["x-oauth-scopes"]) + const grantedScopes = parseStringHeader( + response.headers["x-oauth-scopes"], + ); return { data: JSON.parse(text) as T, rateLimitRemaining, @@ -146,51 +185,56 @@ export async function githubFetch( status, etag: responseEtag, grantedScopes, - } + }; } catch (err) { - if (err instanceof GitHubApiError) throw err // includes RateLimit + NotFound - lastError = err instanceof Error ? err : new Error(String(err)) - if (attempt >= RETRY_DELAYS_MS.length) break + if (err instanceof GitHubApiError) throw err; // includes RateLimit + NotFound + lastError = err instanceof Error ? err : new Error(String(err)); + if (attempt >= RETRY_DELAYS_MS.length) break; } } - throw lastError ?? new Error(`githubFetch failed after retries: ${path}`) + throw lastError ?? new Error(`githubFetch failed after retries: ${path}`); } export class GitHubApiError extends Error { - constructor(message: string, public readonly statusCode: number) { - super(message) - this.name = "GitHubApiError" + constructor( + message: string, + public readonly statusCode: number, + ) { + super(message); + this.name = "GitHubApiError"; } } export class GitHubNotFoundError extends GitHubApiError { constructor(message: string) { - super(message, 404) - this.name = "GitHubNotFoundError" + super(message, 404); + this.name = "GitHubNotFoundError"; } } /** Thrown when GitHub returns 429. Not retriable with short backoff — reset is hourly. */ export class GitHubRateLimitError extends GitHubApiError { constructor(public readonly resetAt: number | null) { - super("GitHub API rate limit exceeded", 429) - this.name = "GitHubRateLimitError" + super("GitHub API rate limit exceeded", 429); + this.name = "GitHubRateLimitError"; } } function parseIntHeader(value: string | string[] | undefined): number | null { - if (!value) return null - const str = Array.isArray(value) ? value[0] : value - const n = parseInt(str ?? "", 10) - return isNaN(n) ? null : n + if (!value) return null; + const str = Array.isArray(value) ? value[0] : value; + const n = parseInt(str ?? "", 10); + return isNaN(n) ? null : n; } -function parseStringHeader(value: string | string[] | undefined): string | null { - if (!value) return null - return Array.isArray(value) ? (value[0] ?? null) : value +function parseStringHeader( + value: string | string[] | undefined, +): string | null { + if (!value) return null; + return Array.isArray(value) ? (value[0] ?? null) : value; } function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)) + return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/packages/server/src/routes/auth.test.ts b/packages/server/src/routes/auth.test.ts index 8ada23f..224572a 100644 --- a/packages/server/src/routes/auth.test.ts +++ b/packages/server/src/routes/auth.test.ts @@ -1,58 +1,80 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" -import { Hono } from "hono" +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { Hono } from "hono"; // ── Module mocks (hoisted) ──────────────────────────────────────────────────── vi.mock("undici", () => ({ request: vi.fn(), EnvHttpProxyAgent: class {}, -})) +})); vi.mock("../lib/jwt.js", () => ({ signSession: vi.fn().mockResolvedValue("signed.jwt.token"), verifySession: vi.fn(), -})) +})); vi.mock("../lib/session-store.js", () => ({ sessionCreate: vi.fn().mockReturnValue("session-id-123"), sessionDestroy: vi.fn(), sessionGet: vi.fn(), -})) +})); vi.mock("../lib/github.js", () => ({ githubFetch: vi.fn().mockResolvedValue({ - data: { id: 42, login: "octocat", name: "The Octocat", avatar_url: "https://avatars.githubusercontent.com/u/583231" }, + data: { + id: 42, + login: "octocat", + name: "The Octocat", + avatar_url: "https://avatars.githubusercontent.com/u/583231", + }, grantedScopes: "repo,read:user,user:email,read:org", }), agent: {}, -})) +})); + +vi.mock("../lib/logger.js", () => ({ + log: { + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }, +})); vi.mock("../middleware/auth.js", () => ({ - authMiddleware: vi.fn(async (c: import("hono").Context, next: () => Promise) => { - c.set("session", { sub: "42", login: "octocat", name: "The Octocat", avatarUrl: "https://avatars.githubusercontent.com/u/583231", sessionId: "s1" }) - await next() - }), -})) + authMiddleware: vi.fn( + async (c: import("hono").Context, next: () => Promise) => { + c.set("session", { + sub: "42", + login: "octocat", + name: "The Octocat", + avatarUrl: "https://avatars.githubusercontent.com/u/583231", + sessionId: "s1", + }); + await next(); + }, + ), +})); // Dynamic imports after mocks are hoisted -import { request as undiciRequest } from "undici" -import { signSession, verifySession } from "../lib/jwt.js" -import { sessionCreate, sessionDestroy } from "../lib/session-store.js" -import { getCookie } from "./auth.js" -import authRouter from "./auth.js" - -const _mockSignSession = vi.mocked(signSession) -const mockVerifySession = vi.mocked(verifySession) -const mockSessionCreate = vi.mocked(sessionCreate) -const mockSessionDestroy = vi.mocked(sessionDestroy) -const mockUndiciRequest = vi.mocked(undiciRequest) +import { request as undiciRequest } from "undici"; +import { signSession, verifySession } from "../lib/jwt.js"; +import { sessionCreate, sessionDestroy } from "../lib/session-store.js"; +import { getCookie } from "./auth.js"; +import authRouter from "./auth.js"; + +const _mockSignSession = vi.mocked(signSession); +const mockVerifySession = vi.mocked(verifySession); +const mockSessionCreate = vi.mocked(sessionCreate); +const mockSessionDestroy = vi.mocked(sessionDestroy); +const mockUndiciRequest = vi.mocked(undiciRequest); // ── Test app setup ──────────────────────────────────────────────────────────── function makeApp() { - const app = new Hono() - app.route("/auth", authRouter) - return app + const app = new Hono(); + app.route("/auth", authRouter); + return app; } // Default successful undici response for the GitHub token exchange @@ -60,178 +82,203 @@ function mockTokenExchangeSuccess(accessToken = "gha_token") { mockUndiciRequest.mockResolvedValue({ statusCode: 200, body: { - json: () => Promise.resolve({ access_token: accessToken, token_type: "bearer", scope: "repo" }), + json: () => + Promise.resolve({ + access_token: accessToken, + token_type: "bearer", + scope: "repo", + }), text: () => Promise.resolve(""), }, headers: {}, - } as never) + } as never); } beforeEach(() => { - vi.clearAllMocks() - process.env["GITHUB_CLIENT_ID"] = "test-client-id" - process.env["GITHUB_CLIENT_SECRET"] = "test-client-secret" - process.env["FRONTEND_URL"] = "http://localhost:5174" - delete process.env["GITHUB_SCOPE"] - delete process.env["COOKIE_SECURE"] -}) + vi.clearAllMocks(); + process.env["GITHUB_CLIENT_ID"] = "test-client-id"; + process.env["GITHUB_CLIENT_SECRET"] = "test-client-secret"; + process.env["FRONTEND_URL"] = "http://localhost:5174"; + delete process.env["GITHUB_SCOPE"]; + delete process.env["COOKIE_SECURE"]; +}); afterEach(() => { - delete process.env["GITHUB_CLIENT_ID"] - delete process.env["GITHUB_CLIENT_SECRET"] - delete process.env["FRONTEND_URL"] - delete process.env["GITHUB_SCOPE"] - delete process.env["COOKIE_SECURE"] -}) + delete process.env["GITHUB_CLIENT_ID"]; + delete process.env["GITHUB_CLIENT_SECRET"]; + delete process.env["FRONTEND_URL"]; + delete process.env["GITHUB_SCOPE"]; + delete process.env["COOKIE_SECURE"]; +}); // ── /auth/login ─────────────────────────────────────────────────────────────── describe("GET /auth/login", () => { it("redirects to GitHub OAuth authorize URL", async () => { - const res = await makeApp().request("/auth/login") - expect(res.status).toBe(302) - const location = res.headers.get("location") ?? "" - expect(location).toContain("github.com/login/oauth/authorize") - expect(location).toContain("client_id=test-client-id") - }) + const res = await makeApp().request("/auth/login"); + expect(res.status).toBe(302); + const location = res.headers.get("location") ?? ""; + expect(location).toContain("github.com/login/oauth/authorize"); + expect(location).toContain("client_id=test-client-id"); + }); it("includes state parameter in the redirect URL", async () => { - const res = await makeApp().request("/auth/login") - const location = res.headers.get("location") ?? "" - expect(location).toMatch(/state=[0-9a-f]{64}/) - }) + const res = await makeApp().request("/auth/login"); + const location = res.headers.get("location") ?? ""; + expect(location).toMatch(/state=[0-9a-f]{64}/); + }); it("includes PKCE code_challenge and method=S256 in the redirect URL", async () => { - const res = await makeApp().request("/auth/login") - const location = res.headers.get("location") ?? "" - expect(location).toContain("code_challenge=") - expect(location).toContain("code_challenge_method=S256") - }) + const res = await makeApp().request("/auth/login"); + const location = res.headers.get("location") ?? ""; + expect(location).toContain("code_challenge="); + expect(location).toContain("code_challenge_method=S256"); + }); it("sets HttpOnly oauth_state cookie scoped to /auth/callback", async () => { - const res = await makeApp().request("/auth/login") - const cookies = res.headers.getSetCookie() - const stateCookie = cookies.find((c) => c.startsWith("oauth_state=")) - expect(stateCookie).toBeDefined() - expect(stateCookie).toContain("HttpOnly") - expect(stateCookie).toContain("Path=/auth/callback") - expect(stateCookie).toContain("SameSite=Lax") - }) + const res = await makeApp().request("/auth/login"); + const cookies = res.headers.getSetCookie(); + const stateCookie = cookies.find((c) => c.startsWith("oauth_state=")); + expect(stateCookie).toBeDefined(); + expect(stateCookie).toContain("HttpOnly"); + expect(stateCookie).toContain("Path=/auth/callback"); + expect(stateCookie).toContain("SameSite=Lax"); + }); it("sets HttpOnly pkce_verifier cookie scoped to /auth/callback", async () => { - const res = await makeApp().request("/auth/login") - const cookies = res.headers.getSetCookie() - const pkceCookie = cookies.find((c) => c.startsWith("pkce_verifier=")) - expect(pkceCookie).toBeDefined() - expect(pkceCookie).toContain("HttpOnly") - expect(pkceCookie).toContain("Path=/auth/callback") - }) + const res = await makeApp().request("/auth/login"); + const cookies = res.headers.getSetCookie(); + const pkceCookie = cookies.find((c) => c.startsWith("pkce_verifier=")); + expect(pkceCookie).toBeDefined(); + expect(pkceCookie).toContain("HttpOnly"); + expect(pkceCookie).toContain("Path=/auth/callback"); + }); it("uses GITHUB_SCOPE env var when set", async () => { - process.env["GITHUB_SCOPE"] = "read:user read:org" - const res = await makeApp().request("/auth/login") - const location = res.headers.get("location") ?? "" - expect(location).toContain("scope=read%3Auser+read%3Aorg") - }) + process.env["GITHUB_SCOPE"] = "read:user read:org"; + const res = await makeApp().request("/auth/login"); + const location = res.headers.get("location") ?? ""; + expect(location).toContain("scope=read%3Auser+read%3Aorg"); + }); it("returns 500 when GITHUB_CLIENT_ID is not configured", async () => { - delete process.env["GITHUB_CLIENT_ID"] - const res = await makeApp().request("/auth/login") - expect(res.status).toBe(500) - }) + delete process.env["GITHUB_CLIENT_ID"]; + const res = await makeApp().request("/auth/login"); + expect(res.status).toBe(500); + }); it("does not set Secure flag when COOKIE_SECURE is not set", async () => { - const res = await makeApp().request("/auth/login") - const cookies = res.headers.getSetCookie() + const res = await makeApp().request("/auth/login"); + const cookies = res.headers.getSetCookie(); for (const c of cookies) { - expect(c.toLowerCase()).not.toContain("secure") + expect(c.toLowerCase()).not.toContain("secure"); } - }) + }); it("sets Secure flag when COOKIE_SECURE=true", async () => { - process.env["COOKIE_SECURE"] = "true" - const res = await makeApp().request("/auth/login") - const cookies = res.headers.getSetCookie() + process.env["COOKIE_SECURE"] = "true"; + const res = await makeApp().request("/auth/login"); + const cookies = res.headers.getSetCookie(); for (const c of cookies) { - expect(c).toContain("Secure") + expect(c).toContain("Secure"); } - }) -}) + }); +}); // ── /auth/callback ───────────────────────────────────────────────────────────── -function makeCallbackRequest(overrides: { - state?: string - stateCookie?: string - pkceVerifier?: string - code?: string -} = {}) { - const state = overrides.state ?? "abc123" - const stateCookie = overrides.stateCookie ?? state - const pkceVerifier = overrides.pkceVerifier ?? "my-verifier" - const code = overrides.code ?? "github-code" +function makeCallbackRequest( + overrides: { + state?: string; + stateCookie?: string; + pkceVerifier?: string; + code?: string; + } = {}, +) { + const state = overrides.state ?? "abc123"; + const stateCookie = overrides.stateCookie ?? state; + const pkceVerifier = overrides.pkceVerifier ?? "my-verifier"; + const code = overrides.code ?? "github-code"; const cookieHeader = [ `oauth_state=${stateCookie}`, `pkce_verifier=${pkceVerifier}`, - ].join("; ") + ].join("; "); return makeApp().request(`/auth/callback?code=${code}&state=${state}`, { headers: { cookie: cookieHeader }, - }) + }); } describe("GET /auth/callback", () => { beforeEach(() => { - mockTokenExchangeSuccess() - }) + mockTokenExchangeSuccess(); + }); it("returns 400 when state param is missing", async () => { const res = await makeApp().request("/auth/callback?code=abc", { headers: { cookie: "oauth_state=abc" }, - }) - expect(res.status).toBe(400) - }) + }); + expect(res.status).toBe(400); + }); it("returns 400 when state does not match cookie", async () => { - const res = await makeCallbackRequest({ state: "real", stateCookie: "fake" }) - expect(res.status).toBe(400) - }) + const res = await makeCallbackRequest({ + state: "real", + stateCookie: "fake", + }); + expect(res.status).toBe(400); + }); it("returns 400 when pkce_verifier cookie is missing", async () => { const res = await makeApp().request("/auth/callback?code=abc&state=xyz", { headers: { cookie: "oauth_state=xyz" }, - }) - expect(res.status).toBe(400) - const body = await res.json() as { error: string } - expect(body.error).toContain("PKCE") - }) + }); + expect(res.status).toBe(400); + const body = (await res.json()) as { error: string }; + expect(body.error).toContain("PKCE"); + }); it("clears oauth_state and pkce_verifier cookies on valid request", async () => { - const res = await makeCallbackRequest() - const cookies = res.headers.getSetCookie() - const stateClear = cookies.find((c) => c.startsWith("oauth_state=;")) - const pkceClear = cookies.find((c) => c.startsWith("pkce_verifier=;")) - expect(stateClear).toBeDefined() - expect(pkceClear).toBeDefined() - expect(stateClear).toContain("Max-Age=0") - expect(pkceClear).toContain("Max-Age=0") - }) + const res = await makeCallbackRequest(); + const cookies = res.headers.getSetCookie(); + const stateClear = cookies.find((c) => c.startsWith("oauth_state=;")); + const pkceClear = cookies.find((c) => c.startsWith("pkce_verifier=;")); + expect(stateClear).toBeDefined(); + expect(pkceClear).toBeDefined(); + expect(stateClear).toContain("Max-Age=0"); + expect(pkceClear).toContain("Max-Age=0"); + }); it("sends code_verifier in the token exchange body", async () => { - await makeCallbackRequest({ pkceVerifier: "my-pkce-verifier-value" }) + await makeCallbackRequest({ pkceVerifier: "my-pkce-verifier-value" }); - expect(mockUndiciRequest).toHaveBeenCalled() - const callBody = JSON.parse(mockUndiciRequest.mock.calls[0]![1]!.body as string) - expect(callBody.code_verifier).toBe("my-pkce-verifier-value") - }) + expect(mockUndiciRequest).toHaveBeenCalled(); + const callBody = JSON.parse( + mockUndiciRequest.mock.calls[0]![1]!.body as string, + ); + expect(callBody.code_verifier).toBe("my-pkce-verifier-value"); + }); it("returns 504 when GitHub token exchange times out", async () => { - mockUndiciRequest.mockRejectedValue(Object.assign(new Error("abort"), { name: "AbortError" })) + mockUndiciRequest.mockRejectedValue( + Object.assign(new Error("abort"), { name: "AbortError" }), + ); + + const res = await makeCallbackRequest(); + expect(res.status).toBe(504); + }); + + it("returns 502 when GitHub token exchange fails before a response", async () => { + mockUndiciRequest.mockRejectedValue( + Object.assign(new Error("unable to get local issuer certificate"), { + name: "Error", + }), + ); - const res = await makeCallbackRequest() - expect(res.status).toBe(504) - }) + const res = await makeCallbackRequest(); + expect(res.status).toBe(502); + }); it("returns 502 when GitHub token endpoint returns non-ok status", async () => { mockUndiciRequest.mockResolvedValue({ @@ -241,108 +288,129 @@ describe("GET /auth/callback", () => { text: () => Promise.resolve(""), }, headers: {}, - } as never) - const res = await makeCallbackRequest() - expect(res.status).toBe(502) - }) + } as never); + const res = await makeCallbackRequest(); + expect(res.status).toBe(502); + }); it("returns 400 when GitHub returns an error in the token response", async () => { mockUndiciRequest.mockResolvedValue({ statusCode: 200, body: { - json: () => Promise.resolve({ error: "bad_verification_code", error_description: "The code passed is incorrect" }), + json: () => + Promise.resolve({ + error: "bad_verification_code", + error_description: "The code passed is incorrect", + }), text: () => Promise.resolve(""), }, headers: {}, - } as never) - const res = await makeCallbackRequest() - expect(res.status).toBe(400) - }) + } as never); + const res = await makeCallbackRequest(); + expect(res.status).toBe(400); + }); it("creates a session and sets session cookie directly on success", async () => { - const res = await makeCallbackRequest() - expect(mockSessionCreate).toHaveBeenCalledWith("gha_token", "42") - const cookies = res.headers.getSetCookie() - const sessionCookie = cookies.find((c) => c.startsWith("session=")) - expect(sessionCookie).toBeDefined() - expect(sessionCookie).toContain("HttpOnly") - expect(sessionCookie).toContain("SameSite=Strict") - expect(sessionCookie).toContain("Max-Age=") - }) + const res = await makeCallbackRequest(); + expect(mockSessionCreate).toHaveBeenCalledWith("gha_token", "42"); + const cookies = res.headers.getSetCookie(); + const sessionCookie = cookies.find((c) => c.startsWith("session=")); + expect(sessionCookie).toBeDefined(); + expect(sessionCookie).toContain("HttpOnly"); + expect(sessionCookie).toContain("SameSite=Strict"); + expect(sessionCookie).toContain("Max-Age="); + }); it("redirects to / on success (no relay)", async () => { - const res = await makeCallbackRequest() - expect(res.status).toBe(302) - const location = res.headers.get("location") ?? "" - expect(location).toBe("/") - }) + const res = await makeCallbackRequest(); + expect(res.status).toBe(302); + const location = res.headers.get("location") ?? ""; + expect(location).toBe("/"); + }); it("uses the shared undici agent for the token exchange", async () => { - await makeCallbackRequest() - expect(mockUndiciRequest).toHaveBeenCalled() + await makeCallbackRequest(); + expect(mockUndiciRequest).toHaveBeenCalled(); // The call must include a dispatcher (the shared agent) — not rely on global fetch - const callOptions = mockUndiciRequest.mock.calls[0]![1] - expect(callOptions).toHaveProperty("dispatcher") - }) -}) + const callOptions = mockUndiciRequest.mock.calls[0]![1]; + expect(callOptions).toHaveProperty("dispatcher"); + }); +}); // ── /auth/logout ─────────────────────────────────────────────────────────────── describe("POST /auth/logout", () => { it("clears the session cookie", async () => { mockVerifySession.mockResolvedValueOnce({ - sub: "42", sessionId: "s1", login: "octocat", name: "Octocat", avatarUrl: "https://avatars.githubusercontent.com/u/1" - }) - const res = await makeApp().request("/auth/logout", { method: "POST", headers: { cookie: "session=some.jwt" } }) - const cookies = res.headers.getSetCookie() - const cleared = cookies.find((c) => c.startsWith("session=;")) - expect(cleared).toBeDefined() - expect(cleared).toContain("Max-Age=0") - expect(cleared).toContain("SameSite=Strict") - }) + sub: "42", + sessionId: "s1", + login: "octocat", + name: "Octocat", + avatarUrl: "https://avatars.githubusercontent.com/u/1", + }); + const res = await makeApp().request("/auth/logout", { + method: "POST", + headers: { cookie: "session=some.jwt" }, + }); + const cookies = res.headers.getSetCookie(); + const cleared = cookies.find((c) => c.startsWith("session=;")); + expect(cleared).toBeDefined(); + expect(cleared).toContain("Max-Age=0"); + expect(cleared).toContain("SameSite=Strict"); + }); it("destroys the server-side session", async () => { mockVerifySession.mockResolvedValueOnce({ - sub: "42", sessionId: "sid-to-destroy", login: "octocat", name: "Octocat", avatarUrl: "https://avatars.githubusercontent.com/u/1" - }) - await makeApp().request("/auth/logout", { method: "POST", headers: { cookie: "session=some.jwt" } }) - expect(mockSessionDestroy).toHaveBeenCalledWith("sid-to-destroy") - }) + sub: "42", + sessionId: "sid-to-destroy", + login: "octocat", + name: "Octocat", + avatarUrl: "https://avatars.githubusercontent.com/u/1", + }); + await makeApp().request("/auth/logout", { + method: "POST", + headers: { cookie: "session=some.jwt" }, + }); + expect(mockSessionDestroy).toHaveBeenCalledWith("sid-to-destroy"); + }); it("responds 200 even when session cookie is absent", async () => { - const res = await makeApp().request("/auth/logout", { method: "POST" }) - expect(res.status).toBe(200) - expect(mockSessionDestroy).not.toHaveBeenCalled() - }) + const res = await makeApp().request("/auth/logout", { method: "POST" }); + expect(res.status).toBe(200); + expect(mockSessionDestroy).not.toHaveBeenCalled(); + }); it("responds 200 when JWT verification fails (already expired)", async () => { - mockVerifySession.mockRejectedValueOnce(new Error("jwt expired")) - const res = await makeApp().request("/auth/logout", { method: "POST", headers: { cookie: "session=bad.jwt" } }) - expect(res.status).toBe(200) - expect(mockSessionDestroy).not.toHaveBeenCalled() - }) -}) + mockVerifySession.mockRejectedValueOnce(new Error("jwt expired")); + const res = await makeApp().request("/auth/logout", { + method: "POST", + headers: { cookie: "session=bad.jwt" }, + }); + expect(res.status).toBe(200); + expect(mockSessionDestroy).not.toHaveBeenCalled(); + }); +}); // ── getCookie helper ────────────────────────────────────────────────────────── describe("getCookie", () => { it("returns the value of a named cookie", () => { - expect(getCookie("session=abc; other=xyz", "session")).toBe("abc") - }) + expect(getCookie("session=abc; other=xyz", "session")).toBe("abc"); + }); it("handles cookie values containing =", () => { - expect(getCookie("token=a=b=c; other=1", "token")).toBe("a=b=c") - }) + expect(getCookie("token=a=b=c; other=1", "token")).toBe("a=b=c"); + }); it("returns undefined for missing cookie name", () => { - expect(getCookie("session=abc", "missing")).toBeUndefined() - }) + expect(getCookie("session=abc", "missing")).toBeUndefined(); + }); it("returns undefined for empty cookie header", () => { - expect(getCookie(undefined, "session")).toBeUndefined() - }) + expect(getCookie(undefined, "session")).toBeUndefined(); + }); it("handles whitespace around cookie pairs", () => { - expect(getCookie(" foo=bar ; baz=qux ", "baz")).toBe("qux") - }) -}) + expect(getCookie(" foo=bar ; baz=qux ", "baz")).toBe("qux"); + }); +}); diff --git a/packages/server/src/routes/auth.ts b/packages/server/src/routes/auth.ts index 2bc08fa..658659f 100644 --- a/packages/server/src/routes/auth.ts +++ b/packages/server/src/routes/auth.ts @@ -1,59 +1,63 @@ -import { Hono } from "hono" -import { createHash, randomBytes } from "node:crypto" -import { signSession, verifySession } from "../lib/jwt.js" -import { sessionCreate, sessionDestroy } from "../lib/session-store.js" -import { request } from "undici" -import { githubFetch, agent } from "../lib/github.js" -import { authMiddleware } from "../middleware/auth.js" -import type { AuthEnv } from "../middleware/auth.js" - -const GITHUB_OAUTH_AUTHORIZE = "https://github.com/login/oauth/authorize" -const GITHUB_OAUTH_TOKEN = "https://github.com/login/oauth/access_token" +import { Hono } from "hono"; +import { createHash, randomBytes } from "node:crypto"; +import { signSession, verifySession } from "../lib/jwt.js"; +import { sessionCreate, sessionDestroy } from "../lib/session-store.js"; +import { request } from "undici"; +import { githubFetch, agent } from "../lib/github.js"; +import { log } from "../lib/logger.js"; +import { authMiddleware } from "../middleware/auth.js"; +import type { AuthEnv } from "../middleware/auth.js"; + +const GITHUB_OAUTH_AUTHORIZE = "https://github.com/login/oauth/authorize"; +const GITHUB_OAUTH_TOKEN = "https://github.com/login/oauth/access_token"; // Default OAuth scope. repo is required for private-repo workflow-run access. // Override via GITHUB_SCOPE env var for public-only installations. -const DEFAULT_SCOPE = "read:user,user:email,repo,read:org" +const DEFAULT_SCOPE = "read:user,user:email,repo,read:org"; interface GitHubUser { - id: number - login: string - name: string | null - avatar_url: string + id: number; + login: string; + name: string | null; + avatar_url: string; } interface GitHubTokenResponse { - access_token: string - token_type: string - scope: string - error?: string - error_description?: string + access_token: string; + token_type: string; + scope: string; + error?: string; + error_description?: string; } -const auth = new Hono() +const auth = new Hono(); auth.get("/login", (c) => { - const clientId = process.env["GITHUB_CLIENT_ID"] - if (!clientId) return c.json({ error: "OAuth not configured" }, 500) + const clientId = process.env["GITHUB_CLIENT_ID"]; + if (!clientId) return c.json({ error: "OAuth not configured" }, 500); // Read scope at request time so GITHUB_SCOPE overrides take effect without restart - const scope = process.env["GITHUB_SCOPE"]?.trim() || DEFAULT_SCOPE + const scope = process.env["GITHUB_SCOPE"]?.trim() || DEFAULT_SCOPE; // CSRF protection: random state bound to a short-lived HttpOnly cookie - const state = randomBytes(32).toString("hex") + const state = randomBytes(32).toString("hex"); // PKCE (RFC 7636): code_verifier stored in a short-lived HttpOnly cookie; // code_challenge (S256) sent in the authorization URL. Protects against // authorization-code interception even when the client_secret is also used. - const codeVerifier = randomBytes(32).toString("base64url") - const codeChallenge = createHash("sha256").update(codeVerifier).digest("base64url") + const codeVerifier = randomBytes(32).toString("base64url"); + const codeChallenge = createHash("sha256") + .update(codeVerifier) + .digest("base64url"); // Derive the callback URL from the incoming request so the same OAuth App // works across environments (local dev, Docker, staging, production) without // changing GitHub App settings. Register each environment's URL once in the // OAuth App; GitHub validates redirect_uri against that list. - const proto = c.req.header("x-forwarded-proto") ?? (isSecure() ? "https" : "http") - const host = c.req.header("host") ?? "localhost:5174" - const redirectUri = `${proto}://${host}/auth/callback` + const proto = + c.req.header("x-forwarded-proto") ?? (isSecure() ? "https" : "http"); + const host = c.req.header("host") ?? "localhost:5174"; + const redirectUri = `${proto}://${host}/auth/callback`; const params = new URLSearchParams({ client_id: clientId, @@ -62,49 +66,53 @@ auth.get("/login", (c) => { state, code_challenge: codeChallenge, code_challenge_method: "S256", - }) + }); - const secure = isSecure() - const cookieFlags = `HttpOnly; SameSite=Lax; Max-Age=300; Path=/auth/callback${secure ? "; Secure" : ""}` + const secure = isSecure(); + const cookieFlags = `HttpOnly; SameSite=Lax; Max-Age=300; Path=/auth/callback${secure ? "; Secure" : ""}`; // Both the state and PKCE verifier use Path=/auth/callback so they are only // sent to the one endpoint that needs them. // Use append:true for the second Set-Cookie so it is not replaced by the first. - c.header("Set-Cookie", `oauth_state=${state}; ${cookieFlags}`) - c.header("Set-Cookie", `pkce_verifier=${codeVerifier}; ${cookieFlags}`, { append: true }) + c.header("Set-Cookie", `oauth_state=${state}; ${cookieFlags}`); + c.header("Set-Cookie", `pkce_verifier=${codeVerifier}; ${cookieFlags}`, { + append: true, + }); - return c.redirect(`${GITHUB_OAUTH_AUTHORIZE}?${params.toString()}`) -}) + return c.redirect(`${GITHUB_OAUTH_AUTHORIZE}?${params.toString()}`); +}); auth.get("/callback", async (c) => { - const code = c.req.query("code") - const stateParam = c.req.query("state") + const code = c.req.query("code"); + const stateParam = c.req.query("state"); if (!code || !stateParam) { - return c.json({ error: "Missing code or state" }, 400) + return c.json({ error: "Missing code or state" }, 400); } // Validate state (CSRF check) - const stateCookie = getCookie(c.req.header("cookie"), "oauth_state") + const stateCookie = getCookie(c.req.header("cookie"), "oauth_state"); if (!stateCookie || stateCookie !== stateParam) { - return c.json({ error: "Invalid state — possible CSRF" }, 400) + return c.json({ error: "Invalid state — possible CSRF" }, 400); } // Read PKCE verifier - const codeVerifier = getCookie(c.req.header("cookie"), "pkce_verifier") + const codeVerifier = getCookie(c.req.header("cookie"), "pkce_verifier"); if (!codeVerifier) { - return c.json({ error: "Missing PKCE verifier" }, 400) + return c.json({ error: "Missing PKCE verifier" }, 400); } - const secure = isSecure() - const clearCookieFlags = `HttpOnly; SameSite=Lax; Max-Age=0; Path=/auth/callback${secure ? "; Secure" : ""}` - c.header("Set-Cookie", `oauth_state=; ${clearCookieFlags}`) - c.header("Set-Cookie", `pkce_verifier=; ${clearCookieFlags}`, { append: true }) + const secure = isSecure(); + const clearCookieFlags = `HttpOnly; SameSite=Lax; Max-Age=0; Path=/auth/callback${secure ? "; Secure" : ""}`; + c.header("Set-Cookie", `oauth_state=; ${clearCookieFlags}`); + c.header("Set-Cookie", `pkce_verifier=; ${clearCookieFlags}`, { + append: true, + }); // Exchange code for token. // Uses the shared undici agent — NODE_EXTRA_CA_CERTS (baked in at build time) // and HTTPS_PROXY / HTTP_PROXY / NO_PROXY are picked up automatically. - let tokenData: GitHubTokenResponse + let tokenData: GitHubTokenResponse; try { const tokenRes = await request(GITHUB_OAUTH_TOKEN, { method: "POST", @@ -120,39 +128,61 @@ auth.get("/callback", async (c) => { }), dispatcher: agent, signal: AbortSignal.timeout(10_000), - }) + }); if (tokenRes.statusCode >= 400) { - await tokenRes.body.text() - return c.json({ error: "Token exchange failed" }, 502) + await tokenRes.body.text(); + return c.json({ error: "Token exchange failed" }, 502); } - tokenData = (await tokenRes.body.json()) as GitHubTokenResponse - } catch { - return c.json({ error: "Token exchange timed out" }, 504) + tokenData = (await tokenRes.body.json()) as GitHubTokenResponse; + } catch (error) { + const requestError = error as + | { name?: string; message?: string } + | undefined; + if (requestError?.name === "AbortError") { + return c.json({ error: "Token exchange timed out" }, 504); + } + log.error("GitHub token exchange request failed", { + errorName: requestError?.name, + errorMessage: requestError?.message, + }); + return c.json({ error: "Token exchange failed" }, 502); } if (tokenData.error || !tokenData.access_token) { - return c.json({ error: tokenData.error_description ?? "Token exchange failed" }, 400) + return c.json( + { error: tokenData.error_description ?? "Token exchange failed" }, + 400, + ); } // Fetch user info - const { data: ghUser, grantedScopes } = await githubFetch(tokenData.access_token, "/user") + const { data: ghUser, grantedScopes } = await githubFetch( + tokenData.access_token, + "/user", + ); // Validate that required OAuth scopes were granted. // GitHub does not enforce requested scopes — a user can deny permissions. // A missing scope causes silent API failures downstream, so we fail early. - const REQUIRED_SCOPES = ["repo", "read:user"] + const REQUIRED_SCOPES = ["repo", "read:user"]; if (grantedScopes === null) { - return c.json({ error: "Could not verify OAuth scopes — please try signing in again." }, 403) + return c.json( + { error: "Could not verify OAuth scopes — please try signing in again." }, + 403, + ); } - const granted = new Set(grantedScopes.split(",").map((s) => s.trim())) - const missing = REQUIRED_SCOPES.filter((s) => !granted.has(s)) + const granted = new Set(grantedScopes.split(",").map((s) => s.trim())); + const missing = REQUIRED_SCOPES.filter((s) => !granted.has(s)); if (missing.length > 0) { - return c.json({ - error: `Insufficient permissions. Missing OAuth scopes: ${missing.join(", ")}. Please sign out and re-authorize the application.`, - }, 403) + return c.json( + { + error: `Insufficient permissions. Missing OAuth scopes: ${missing.join(", ")}. Please sign out and re-authorize the application.`, + }, + 403, + ); } // Store token in session map; JWT holds only session ID + user metadata - const sessionId = sessionCreate(tokenData.access_token, String(ghUser.id)) + const sessionId = sessionCreate(tokenData.access_token, String(ghUser.id)); const jwt = await signSession({ sub: String(ghUser.id), @@ -160,59 +190,65 @@ auth.get("/callback", async (c) => { login: ghUser.login, name: ghUser.name ?? ghUser.login, avatarUrl: ghUser.avatar_url, - }) + }); // Both dev (Vite proxy) and Docker (nginx) route /auth through the same origin // as the React app, so we can set the session cookie directly here. c.header( "Set-Cookie", `session=${jwt}; HttpOnly; SameSite=Strict; Max-Age=${7 * 24 * 3600}; Path=/${secure ? "; Secure" : ""}`, - { append: true } - ) + { append: true }, + ); - return c.redirect("/") -}) + return c.redirect("/"); +}); // Logout: await session destruction before responding so the server-side // session entry is guaranteed to be removed when the client receives 200. auth.post("/logout", async (c) => { - const cookie = getCookie(c.req.header("cookie"), "session") + const cookie = getCookie(c.req.header("cookie"), "session"); if (cookie) { try { - const payload = await verifySession(cookie) - sessionDestroy(payload.sessionId) + const payload = await verifySession(cookie); + sessionDestroy(payload.sessionId); } catch { // Ignore invalid or already-expired cookie — session is effectively dead } } - c.header("Set-Cookie", `session=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`) - return c.json({ ok: true }) -}) + c.header( + "Set-Cookie", + `session=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`, + ); + return c.json({ ok: true }); +}); auth.get("/me", authMiddleware, (c) => { - const session = c.get("session") + const session = c.get("session"); return c.json({ login: session.login, name: session.name, avatarUrl: session.avatarUrl, - }) -}) + }); +}); // Secure flag should be set only when the app is served over HTTPS. // NODE_ENV=production does not imply HTTPS (e.g. local Docker over HTTP). // Set COOKIE_SECURE=true explicitly when deploying behind TLS. function isSecure(): boolean { - return process.env["COOKIE_SECURE"] === "true" + return process.env["COOKIE_SECURE"] === "true"; } -function getCookie(cookieHeader: string | undefined, name: string): string | undefined { - if (!cookieHeader) return undefined +function getCookie( + cookieHeader: string | undefined, + name: string, +): string | undefined { + if (!cookieHeader) return undefined; for (const part of cookieHeader.split(";")) { - const [key, ...valueParts] = part.trim().split("=") - if (key?.trim() === name) return valueParts.join("=").trim() + const [key, ...valueParts] = part.trim().split("="); + if (key?.trim() === name) return valueParts.join("=").trim(); } - return undefined + return undefined; } -export { getCookie } -export default auth +export { getCookie }; +export default auth; diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index e1b2210..b153c16 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -1,17 +1,15 @@ # ── Build stage ────────────────────────────────────────────────────────────── -# Context: repo root (set in docker-compose.yml) FROM node:24-alpine AS builder # Docker Desktop's build network has no IPv6 routing; force Node.js to prefer -# IPv4 so corepack/pnpm can reach registry.npmjs.org without timing out. +# IPv4 so npm/pnpm can reach registry.npmjs.org without timing out. ENV NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection" WORKDIR /app # ── Build-time CA certificate (optional) ────────────────────────────────────── # Pass EXTRA_CA_CERTS_B64 (base64-encoded PEM bundle) to inject corporate CA -# trust before any networked build step runs (corepack, pnpm install, vite build). -# If unset the build continues with the base image trust store only. +# trust before any networked build step runs (npm install, pnpm install, vite build). ARG EXTRA_CA_CERTS_B64 ENV DASHLIGHT_EXTRA_CA_FILE="/opt/dashlight/extra-ca-certificates.pem" ENV DASHLIGHT_CA_BUNDLE="/opt/dashlight/ca-certificates-with-extra.pem" @@ -21,13 +19,25 @@ ENV NODE_EXTRA_CA_CERTS="/opt/dashlight/extra-ca-certificates.pem" RUN mkdir -p /opt/dashlight && \ cp /etc/ssl/certs/ca-certificates.crt "$DASHLIGHT_CA_BUNDLE" && \ if [ -n "$EXTRA_CA_CERTS_B64" ]; then \ - printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > "$DASHLIGHT_EXTRA_CA_FILE" && \ + printf '%s' "$EXTRA_CA_CERTS_B64" | base64 -d > /tmp/dashlight-extra-ca-decoded && \ + if grep -q 'BEGIN CERTIFICATE' /tmp/dashlight-extra-ca-decoded; then \ + mv /tmp/dashlight-extra-ca-decoded "$DASHLIGHT_EXTRA_CA_FILE"; \ + else \ + base64 -d /tmp/dashlight-extra-ca-decoded > "$DASHLIGHT_EXTRA_CA_FILE" && \ + rm -f /tmp/dashlight-extra-ca-decoded; \ + fi && \ cat "$DASHLIGHT_EXTRA_CA_FILE" >> "$DASHLIGHT_CA_BUNDLE"; \ else \ : > "$DASHLIGHT_EXTRA_CA_FILE"; \ fi -RUN corepack enable && corepack prepare pnpm@9.15.4 --activate +# Copy .npmrc if present (e.g. for corporate Artifactory proxy credentials). +# Create an empty .npmrc first so the COPY never fails when the file is absent. +RUN touch /root/.npmrc +COPY .npmrc* /root/ + +# Simpler bootstrap path: npm respects /root/.npmrc for registry/auth. +RUN npm install -g pnpm@9.15.4 # Copy workspace manifests first for layer caching COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ @@ -45,9 +55,6 @@ RUN pnpm --filter @dashlight/web build # The nginx runner serves only static files — no outbound HTTPS, no cert bundle needed. FROM nginx:1.29.8-alpine AS runner -# Upgrade OS packages to patch any CVEs present in the pinned base image. -RUN apk upgrade --no-cache - COPY --from=builder /app/packages/web/dist /usr/share/nginx/html COPY packages/web/nginx.conf /etc/nginx/conf.d/default.conf diff --git a/scripts/__tests__/generate-docker-certs-env.test.mjs b/scripts/__tests__/generate-docker-certs-env.test.mjs new file mode 100644 index 0000000..5b4fcf8 --- /dev/null +++ b/scripts/__tests__/generate-docker-certs-env.test.mjs @@ -0,0 +1,98 @@ +import { describe, it, expect } from "vitest"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +import { + buildExtraCaCertsB64, + normalizeCertificateContent, + parseArgs, + writeDockerCertsEnv, +} from "../generate-docker-certs-env.mjs"; + +const PEM_A = [ + "-----BEGIN CERTIFICATE-----", + "MIIBAAAATESTCERTA", + "-----END CERTIFICATE-----", +].join("\n"); + +const PEM_B = [ + "-----BEGIN CERTIFICATE-----", + "MIIBBBBATESTCERTB", + "-----END CERTIFICATE-----", +].join("\n"); + +function decodeEnvValue(line) { + const value = line.split("=")[1] ?? ""; + return Buffer.from(value, "base64").toString("utf8"); +} + +describe("normalizeCertificateContent", () => { + it("returns PEM blocks unchanged when input is PEM", () => { + const blocks = normalizeCertificateContent(PEM_A, "pem-file"); + expect(blocks).toHaveLength(1); + expect(blocks[0]).toContain("BEGIN CERTIFICATE"); + }); + + it("decodes base64-wrapped PEM input", () => { + const b64 = Buffer.from(`${PEM_A}\n`, "utf8").toString("base64"); + const blocks = normalizeCertificateContent(b64, "b64-file"); + expect(blocks).toHaveLength(1); + expect(blocks[0]).toContain("BEGIN CERTIFICATE"); + }); + + it("throws for invalid input", () => { + expect(() => normalizeCertificateContent("not a cert", "bad-file")).toThrow( + /not PEM and not valid base64|did not contain PEM/, + ); + }); +}); + +describe("writeDockerCertsEnv", () => { + it("writes one EXTRA_CA_CERTS_B64 line from mixed PEM/base64 sources", () => { + const dir = mkdtempSync(join(tmpdir(), "dashlight-certs-")); + try { + const cert1 = join(dir, "cert1.pem"); + const cert2 = join(dir, "cert2.pem"); + const out = join(dir, ".docker-certs.env"); + + writeFileSync(cert1, `${PEM_A}\n`, "utf8"); + writeFileSync( + cert2, + Buffer.from(`${PEM_B}\n`, "utf8").toString("base64"), + "utf8", + ); + + const line = writeDockerCertsEnv(out, [cert1, cert2]); + expect(line.startsWith("EXTRA_CA_CERTS_B64=")).toBe(true); + + const file = readFileSync(out, "utf8"); + expect(file.split("\n").filter(Boolean)).toHaveLength(1); + + const decoded = decodeEnvValue(file.trim()); + expect(decoded).toContain("MIIBAAAATESTCERTA"); + expect(decoded).toContain("MIIBBBBATESTCERTB"); + expect(decoded.match(/BEGIN CERTIFICATE/g)?.length).toBe(2); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + + it("buildExtraCaCertsB64 requires at least one cert path", () => { + expect(() => buildExtraCaCertsB64([])).toThrow(/at least one certificate/); + }); +}); + +describe("parseArgs", () => { + it("ignores standalone -- separator", () => { + const parsed = parseArgs(["--", "ca-1.pem", "ca-2.pem"]); + expect(parsed.outputPath).toBe(".docker-certs.env"); + expect(parsed.certPaths).toEqual(["ca-1.pem", "ca-2.pem"]); + }); + + it("supports --out alongside -- separator", () => { + const parsed = parseArgs(["--out", "custom.env", "--", "ca-1.pem"]); + expect(parsed.outputPath).toBe("custom.env"); + expect(parsed.certPaths).toEqual(["ca-1.pem"]); + }); +}); diff --git a/scripts/generate-docker-certs-env.mjs b/scripts/generate-docker-certs-env.mjs new file mode 100644 index 0000000..4fb5489 --- /dev/null +++ b/scripts/generate-docker-certs-env.mjs @@ -0,0 +1,113 @@ +import { readFileSync, writeFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +const CERT_BLOCK_RE = + /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g; + +function extractPemBlocks(text) { + const blocks = text.match(CERT_BLOCK_RE); + return blocks ?? []; +} + +function decodeBase64Text(text) { + const compact = text.replace(/\s+/g, ""); + if (!compact) return null; + try { + return Buffer.from(compact, "base64").toString("utf8"); + } catch { + return null; + } +} + +export function normalizeCertificateContent(raw, sourceLabel = "input") { + const text = raw.toString("utf8").trim(); + + const pemBlocks = extractPemBlocks(text); + if (pemBlocks.length > 0) return pemBlocks; + + const decoded = decodeBase64Text(text); + if (!decoded) { + throw new Error(`${sourceLabel}: not PEM and not valid base64 content`); + } + + const decodedBlocks = extractPemBlocks(decoded); + if (decodedBlocks.length === 0) { + throw new Error( + `${sourceLabel}: base64 decoded successfully but did not contain PEM certificate blocks`, + ); + } + + return decodedBlocks; +} + +export function buildExtraCaCertsB64(certPaths) { + if (!Array.isArray(certPaths) || certPaths.length === 0) { + throw new Error("Provide at least one certificate file path"); + } + + const normalizedBlocks = []; + for (const certPath of certPaths) { + const fileContent = readFileSync(certPath, "utf8"); + const pemBlocks = normalizeCertificateContent(fileContent, certPath); + normalizedBlocks.push(...pemBlocks); + } + + const normalizedPemBundle = `${normalizedBlocks.join("\n")}\n`; + return Buffer.from(normalizedPemBundle, "utf8").toString("base64"); +} + +export function writeDockerCertsEnv(outputPath, certPaths) { + const encoded = buildExtraCaCertsB64(certPaths); + const line = `EXTRA_CA_CERTS_B64=${encoded}\n`; + writeFileSync(outputPath, line, "utf8"); + return line; +} + +export function parseArgs(argv) { + const args = [...argv]; + let outputPath = ".docker-certs.env"; + const certPaths = []; + + for (let i = 0; i < args.length; i += 1) { + const arg = args[i]; + + if (arg === "--") { + continue; + } + + if (arg === "--out") { + const next = args[i + 1]; + if (!next || next === "--") { + throw new Error("Missing value for --out"); + } + outputPath = next; + i += 1; + continue; + } + + certPaths.push(arg); + } + + if (certPaths.length === 0) { + throw new Error( + "Usage: node scripts/generate-docker-certs-env.mjs [--out .docker-certs.env] [cert2 ...]", + ); + } + + return { outputPath, certPaths }; +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + try { + const { outputPath, certPaths } = parseArgs(process.argv.slice(2)); + writeDockerCertsEnv(outputPath, certPaths); + process.stdout.write( + `Wrote ${outputPath} from ${certPaths.length} certificate file(s).\n`, + ); + } catch (error) { + process.stderr.write( + `${error instanceof Error ? error.message : String(error)}\n`, + ); + process.exit(1); + } +} From c6a08f6427ec14bcc48814c91999381a24e91995 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:54:59 +0200 Subject: [PATCH 05/51] feat-usability-updates (#22) * feat: add sortable column headers, runs by workflow and unified search placeholder to runs views * feat: run detail rework * feat: add test --- env.example | 2 +- .../src/components/dag/WorkflowDAG.test.tsx | 98 +++ .../web/src/components/dag/WorkflowDAG.tsx | 172 ++--- packages/web/src/components/ui/Badge.test.tsx | 20 + packages/web/src/components/ui/Badge.tsx | 17 +- .../-repositories.$owner.$repo.runs.test.tsx | 634 ++++++++++++++++++ .../_app/-repositories.$owner.$repo.test.tsx | 74 +- packages/web/src/routes/_app/-runs.test.tsx | 205 +++++- .../repositories.$owner.$repo.runs.$runId.tsx | 20 +- .../_app/repositories.$owner.$repo.runs.tsx | 191 ++++-- .../routes/_app/repositories.$owner.$repo.tsx | 25 +- packages/web/src/routes/_app/repositories.tsx | 84 +-- packages/web/src/routes/_app/runs.tsx | 118 +++- .../routes/_app/runs_.$owner.$repo.$runId.tsx | 24 +- 14 files changed, 1474 insertions(+), 210 deletions(-) create mode 100644 packages/web/src/components/dag/WorkflowDAG.test.tsx create mode 100644 packages/web/src/routes/_app/-repositories.$owner.$repo.runs.test.tsx diff --git a/env.example b/env.example index 296356e..606fafd 100644 --- a/env.example +++ b/env.example @@ -36,7 +36,7 @@ GITHUB_REPOS= # ---- # In-memory LRU cache max size in MB -CACHE_MAX_SIZE_MB=128s +CACHE_MAX_SIZE_MB=128 # ---- Corporate HTTP Proxy (optional) # If outbound HTTPS to api.github.com requires an HTTP proxy. diff --git a/packages/web/src/components/dag/WorkflowDAG.test.tsx b/packages/web/src/components/dag/WorkflowDAG.test.tsx new file mode 100644 index 0000000..9745150 --- /dev/null +++ b/packages/web/src/components/dag/WorkflowDAG.test.tsx @@ -0,0 +1,98 @@ +import { describe, it, expect } from "vitest" +import { render, screen } from "@testing-library/react" +import { sortJobs, WorkflowDAG } from "./WorkflowDAG.js" +import type { WorkflowJob } from "../../types/index.js" + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +let _id = 0 +function makeJob(overrides: Partial = {}): WorkflowJob { + return { + id: ++_id, + name: `Job ${_id}`, + status: "completed", + conclusion: "success", + startedAt: "2024-01-01T10:00:00Z", + completedAt: "2024-01-01T10:05:00Z", + steps: [], + runnerName: "ubuntu-latest", + labels: [], + htmlUrl: "https://github.com", + ...overrides, + } +} + +// ── sortJobs ────────────────────────────────────────────────────────────────── + +describe("sortJobs", () => { + it("returns empty array for no jobs", () => { + expect(sortJobs([])).toEqual([]) + }) + + it("sorts by startedAt ascending", () => { + const a = makeJob({ name: "first", startedAt: "2024-01-01T10:00:00Z" }) + const b = makeJob({ name: "second", startedAt: "2024-01-01T10:10:00Z" }) + expect(sortJobs([b, a]).map((j) => j.name)).toEqual(["first", "second"]) + }) + + it("places jobs without startedAt at the end", () => { + const started = makeJob({ name: "started", startedAt: "2024-01-01T10:00:00Z" }) + const pending = makeJob({ name: "pending", startedAt: null }) + expect(sortJobs([pending, started]).map((j) => j.name)).toEqual(["started", "pending"]) + }) + + it("keeps multiple pending jobs together at the end", () => { + const started = makeJob({ name: "started", startedAt: "2024-01-01T10:00:00Z" }) + const p1 = makeJob({ name: "p1", startedAt: null }) + const p2 = makeJob({ name: "p2", startedAt: null }) + const result = sortJobs([p1, started, p2]).map((j) => j.name) + expect(result[0]).toBe("started") + expect(result.slice(1)).toEqual(expect.arrayContaining(["p1", "p2"])) + }) + + it("does not mutate the original array", () => { + const jobs = [ + makeJob({ startedAt: "2024-01-01T10:10:00Z" }), + makeJob({ startedAt: "2024-01-01T10:00:00Z" }), + ] + const originalIds = jobs.map((j) => j.id) + sortJobs(jobs) + expect(jobs.map((j) => j.id)).toEqual(originalIds) + }) +}) + +// ── WorkflowDAG rendering ───────────────────────────────────────────────────── + +describe("WorkflowDAG", () => { + it("shows empty state when no jobs", () => { + render() + expect(screen.getByText("No jobs to display.")).toBeInTheDocument() + }) + + it("renders a pill for each job", () => { + const jobs = [makeJob({ name: "build" }), makeJob({ name: "test" })] + render() + expect(screen.getByText("build")).toBeInTheDocument() + expect(screen.getByText("test")).toBeInTheDocument() + }) + + it("renders arrows between jobs", () => { + const jobs = [makeJob({ name: "check" }), makeJob({ name: "build" }), makeJob({ name: "deploy" })] + render() + expect(screen.getAllByText("→")).toHaveLength(2) + }) + + it("renders no arrow for a single job", () => { + render() + expect(screen.queryByText("→")).not.toBeInTheDocument() + }) + + it("renders jobs in startedAt order", () => { + const a = makeJob({ name: "validate", startedAt: "2024-01-01T10:00:00Z" }) + const b = makeJob({ name: "deploy", startedAt: "2024-01-01T10:20:00Z" }) + render() + const pills = screen.getAllByText(/validate|deploy/) + expect(pills[0]).toHaveTextContent("validate") + expect(pills[1]).toHaveTextContent("deploy") + }) +}) diff --git a/packages/web/src/components/dag/WorkflowDAG.tsx b/packages/web/src/components/dag/WorkflowDAG.tsx index 90cc5ee..2099988 100644 --- a/packages/web/src/components/dag/WorkflowDAG.tsx +++ b/packages/web/src/components/dag/WorkflowDAG.tsx @@ -1,94 +1,116 @@ -import { useMemo } from "react" -import { - ReactFlow, - Background, - Controls, - type Node, - type Edge, -} from "@xyflow/react" -import dagre from "@dagrejs/dagre" -import { runStatusVariant } from "../../lib/utils.js" +import { Fragment } from "react" +import { runStatusVariant, formatDuration } from "../../lib/utils.js" import type { WorkflowJob } from "../../types/index.js" -import "@xyflow/react/dist/style.css" interface WorkflowDAGProps { jobs: WorkflowJob[] } -const NODE_WIDTH = 180 -const NODE_HEIGHT = 40 +// ── Ordering ────────────────────────────────────────────────────────────────── -export function WorkflowDAG({ jobs }: WorkflowDAGProps) { - const { nodes, edges } = useMemo(() => layoutJobs(jobs), [jobs]) +/** Returns jobs sorted by startedAt, with not-yet-started jobs at the end. */ +export function sortJobs(jobs: WorkflowJob[]): WorkflowJob[] { + return [...jobs].sort((a, b) => { + if (!a.startedAt && !b.startedAt) return 0 + if (!a.startedAt) return 1 + if (!b.startedAt) return -1 + return new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime() + }) +} - if (nodes.length === 0) { - return

No jobs to display.

- } +// ── Job pill ────────────────────────────────────────────────────────────────── + +const COLOR: Record = { + success: "var(--color-success)", + failure: "var(--color-failure)", + running: "var(--color-running)", + cancelled: "var(--color-cancelled)", + neutral: "var(--color-neutral)", + pending: "var(--color-neutral)", +} + +function JobPill({ job }: { job: WorkflowJob }) { + const variant = runStatusVariant(job.status, job.conclusion) + const color = COLOR[variant] ?? "var(--color-border)" + const duration = formatDuration(job.startedAt, job.completedAt) return ( -
- - - - +
+ + + {job.name} + + {duration && ( + + {duration} + + )}
) } -function layoutJobs(jobs: WorkflowJob[]): { nodes: Node[]; edges: Edge[] } { - if (jobs.length === 0) return { nodes: [], edges: [] } +// ── DAG ─────────────────────────────────────────────────────────────────────── - const g = new dagre.graphlib.Graph() - g.setDefaultEdgeLabel(() => ({})) - g.setGraph({ rankdir: "LR", nodesep: 20, ranksep: 40 }) - - for (const job of jobs) { - g.setNode(String(job.id), { width: NODE_WIDTH, height: NODE_HEIGHT }) +export function WorkflowDAG({ jobs }: WorkflowDAGProps) { + if (jobs.length === 0) { + return

No jobs to display.

} - // Infer dependencies from step ordering (jobs don't explicitly list deps in the API) - // In practice this just displays jobs in parallel layout since GitHub doesn't expose deps - // A future improvement: parse workflow YAML to extract `needs` keys - dagre.layout(g) - - const nodes: Node[] = jobs.map((job) => { - const nodeWithPos = g.node(String(job.id)) - const variant = runStatusVariant(job.status, job.conclusion) - const colorMap: Record = { - success: "var(--color-success)", - failure: "var(--color-failure)", - running: "var(--color-running)", - cancelled: "var(--color-cancelled)", - neutral: "var(--color-neutral)", - pending: "var(--color-neutral)", - } - return { - id: String(job.id), - position: { x: nodeWithPos.x - NODE_WIDTH / 2, y: nodeWithPos.y - NODE_HEIGHT / 2 }, - data: { label: job.name }, - style: { - background: "var(--color-bg-secondary)", - border: `2px solid ${colorMap[variant] ?? "var(--color-border)"}`, - borderRadius: "var(--radius)", - padding: "0.375rem 0.75rem", - fontSize: 12, - fontWeight: 500, - width: NODE_WIDTH, - height: NODE_HEIGHT, - display: "flex", - alignItems: "center", - justifyContent: "center", - }, - } - }) + const sorted = sortJobs(jobs) - return { nodes, edges: [] } + return ( +
+
+ {sorted.map((job, i) => ( + + {i > 0 && ( + + → + + )} + + + ))} +
+
+ ) } diff --git a/packages/web/src/components/ui/Badge.test.tsx b/packages/web/src/components/ui/Badge.test.tsx index 9957c81..50aade5 100644 --- a/packages/web/src/components/ui/Badge.test.tsx +++ b/packages/web/src/components/ui/Badge.test.tsx @@ -64,6 +64,26 @@ describe("StatusBadge", () => { const { container } = render() expect(container.querySelector(".spinner")).toBeInTheDocument() }) + + it("dotOnly: does not render the label text", () => { + render() + expect(screen.queryByText("Success")).not.toBeInTheDocument() + }) + + it("dotOnly: moves label into title tooltip on the badge", () => { + const { container } = render() + expect(container.querySelector(".badge")).toHaveAttribute("title", "Failure") + }) + + it("dotOnly: still renders the dot element", () => { + const { container } = render() + expect(container.querySelector("span[style]")).toBeInTheDocument() + }) + + it("default (no dotOnly): does not set title on badge", () => { + const { container } = render() + expect(container.querySelector(".badge")).not.toHaveAttribute("title") + }) }) describe("TierBadge", () => { diff --git a/packages/web/src/components/ui/Badge.tsx b/packages/web/src/components/ui/Badge.tsx index 4b76ffd..078940b 100644 --- a/packages/web/src/components/ui/Badge.tsx +++ b/packages/web/src/components/ui/Badge.tsx @@ -6,18 +6,25 @@ interface BadgeProps { children: React.ReactNode variant?: StatusVariant | "neutral" className?: string + title?: string } -export function Badge({ children, variant = "neutral", className }: BadgeProps) { - return {children} +export function Badge({ children, variant = "neutral", className, title }: BadgeProps) { + return ( + + {children} + + ) } interface StatusBadgeProps { status: RunStatus conclusion: RunConclusion + /** Show only the coloured dot; label text is moved to a title tooltip. */ + dotOnly?: boolean } -export function StatusBadge({ status, conclusion }: StatusBadgeProps) { +export function StatusBadge({ status, conclusion, dotOnly = false }: StatusBadgeProps) { const variant = runStatusVariant(status, conclusion) const label = runStatusLabel(status, conclusion) @@ -38,9 +45,9 @@ export function StatusBadge({ status, conclusion }: StatusBadgeProps) { ) return ( - + {dot} - {label} + {!dotOnly && label} ) } diff --git a/packages/web/src/routes/_app/-repositories.$owner.$repo.runs.test.tsx b/packages/web/src/routes/_app/-repositories.$owner.$repo.runs.test.tsx new file mode 100644 index 0000000..50ebc48 --- /dev/null +++ b/packages/web/src/routes/_app/-repositories.$owner.$repo.runs.test.tsx @@ -0,0 +1,634 @@ +import { describe, it, expect, vi, beforeEach } from "vitest" +import { render, screen, fireEvent } from "@testing-library/react" +import type { WorkflowRun } from "../../types/index.js" + +// ── Mocks ───────────────────────────────────────────────────────────────────── + +const mockNavigate = vi.fn() + +vi.mock("@tanstack/react-router", () => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + createFileRoute: () => (opts: any) => ({ + ...opts, + useParams: vi.fn(() => ({ owner: "acme", repo: "api" })), + useSearch: vi.fn(() => ({ page: 1 })), + fullPath: "/repositories/$owner/$repo/runs", + }), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Link: ({ children, to: _to, params: _p, search: _s, ...rest }: any) => ( + {children} + ), + useNavigate: () => mockNavigate, +})) + +vi.mock("@tanstack/react-query", () => ({ + useQuery: vi.fn(), +})) + +vi.mock("../../api/index.js", () => ({ + getRuns: vi.fn(), +})) + +vi.mock("../../components/ui/Spinner.js", () => ({ + PageSpinner: () =>
, +})) + +vi.mock("../../components/ui/Badge.js", () => ({ + StatusBadge: ({ conclusion, status }: { conclusion: string | null; status: string }) => ( + {conclusion ?? status} + ), +})) + +vi.mock("../../components/ui/Button.js", () => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Button: ({ children, onClick, disabled }: any) => ( + + ), +})) + +vi.mock("../../components/ui/EventBadge.js", () => ({ + EventBadge: ({ event }: { event: string }) => ( + {event} + ), +})) + +// ── Imports after mocks ─────────────────────────────────────────────────────── + +import React from "react" +import { useQuery } from "@tanstack/react-query" +import { Route, RunsList, filterRuns, sortRuns } from "./repositories.$owner.$repo.runs.js" +import type { SortKey } from "./repositories.$owner.$repo.runs.js" + +const mockUseQuery = vi.mocked(useQuery) + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +let _id = 0 +beforeEach(() => { + _id = 0 + vi.clearAllMocks() + mockNavigate.mockReturnValue(() => {}) +}) + +function makeRun(overrides: Partial = {}): WorkflowRun { + return { + id: ++_id, + name: "CI", + displayTitle: `Run ${_id}`, + status: "completed", + conclusion: "success", + headBranch: "main", + headSha: "abc1234def5678", + runNumber: _id, + event: "push", + workflowId: 10, + workflowPath: ".github/workflows/ci.yml", + workflowName: "CI", + repository: "acme/api", + createdAt: "2024-01-01T10:00:00Z", + updatedAt: "2024-01-01T10:05:00Z", + runStartedAt: "2024-01-01T10:00:00Z", + runAttempt: 1, + url: "https://api.github.com/runs/1", + htmlUrl: "https://github.com/acme/api/actions/runs/1", + actor: { login: "alice", avatarUrl: "" }, + ...overrides, + } +} + +function withSearch(search: Record) { + vi.mocked(Route.useSearch).mockReturnValue(search as ReturnType) +} + +function withRuns(runs: WorkflowRun[], total = runs.length) { + mockUseQuery.mockReturnValue({ + data: { runs, total }, + isLoading: false, + } as ReturnType) +} + +// ── filterRuns — pure unit tests ────────────────────────────────────────────── + +describe("filterRuns", () => { + it("returns all runs when query is empty string", () => { + const runs = [makeRun(), makeRun()] + expect(filterRuns(runs, "")).toHaveLength(2) + }) + + it("matches by workflowName (case-insensitive)", () => { + const runs = [ + makeRun({ workflowName: "Deploy Production" }), + makeRun({ workflowName: "CI" }), + ] + expect(filterRuns(runs, "deploy")).toHaveLength(1) + expect(filterRuns(runs, "DEPLOY PRODUCTION")).toHaveLength(1) + }) + + it("matches partial workflowName", () => { + const runs = [ + makeRun({ workflowName: "Nightly Dependency audit" }), + makeRun({ workflowName: "CI" }), + ] + expect(filterRuns(runs, "Night")).toHaveLength(1) + expect(filterRuns(runs, "audit")).toHaveLength(1) + }) + + it("matches by headBranch", () => { + const runs = [ + makeRun({ headBranch: "feature/my-feature" }), + makeRun({ headBranch: "main" }), + ] + expect(filterRuns(runs, "feature")).toHaveLength(1) + expect(filterRuns(runs, "my-feature")).toHaveLength(1) + }) + + it("matches by headSha (full SHA)", () => { + const runs = [ + makeRun({ headSha: "aabbccdd11223344" }), + makeRun({ headSha: "ffffeeeeddddcccc" }), + ] + expect(filterRuns(runs, "aabbccdd")).toHaveLength(1) + }) + + it("matches by headSha prefix (short SHA)", () => { + const runs = [makeRun({ headSha: "deadbeef12345678" })] + expect(filterRuns(runs, "deadbe")).toHaveLength(1) + expect(filterRuns(runs, "xxxxxx")).toHaveLength(0) + }) + + it("matches by actor login", () => { + const runs = [ + makeRun({ actor: { login: "alice", avatarUrl: "" } }), + makeRun({ actor: { login: "bob", avatarUrl: "" } }), + ] + expect(filterRuns(runs, "alice")).toHaveLength(1) + expect(filterRuns(runs, "ALI")).toHaveLength(1) + }) + + it("handles null actor without throwing", () => { + const runs = [makeRun({ actor: null })] + expect(() => filterRuns(runs, "alice")).not.toThrow() + expect(filterRuns(runs, "alice")).toHaveLength(0) + }) + + it("matches by status", () => { + const runs = [ + makeRun({ status: "in_progress", conclusion: null }), + makeRun({ status: "completed", conclusion: "success" }), + ] + expect(filterRuns(runs, "in_progress")).toHaveLength(1) + expect(filterRuns(runs, "completed")).toHaveLength(1) + }) + + it("matches by conclusion", () => { + const runs = [ + makeRun({ status: "completed", conclusion: "failure" }), + makeRun({ status: "completed", conclusion: "success" }), + ] + expect(filterRuns(runs, "failure")).toHaveLength(1) + expect(filterRuns(runs, "success")).toHaveLength(1) + }) + + it("handles null conclusion without throwing", () => { + const runs = [makeRun({ conclusion: null })] + expect(() => filterRuns(runs, "success")).not.toThrow() + expect(filterRuns(runs, "success")).toHaveLength(0) + }) + + it("returns empty array when nothing matches", () => { + const runs = [makeRun({ workflowName: "CI", headBranch: "main" })] + expect(filterRuns(runs, "zzznomatch")).toHaveLength(0) + }) + + it("matches across different fields in different runs", () => { + const runs = [ + makeRun({ workflowName: "Deploy", headBranch: "main" }), + makeRun({ workflowName: "CI", headBranch: "deploy/hotfix" }), + ] + // "deploy" matches workflowName of run 1 AND headBranch of run 2 + expect(filterRuns(runs, "deploy")).toHaveLength(2) + }) + + it("a single run matching multiple fields is returned once", () => { + const runs = [makeRun({ workflowName: "deploy", headBranch: "deploy" })] + expect(filterRuns(runs, "deploy")).toHaveLength(1) + }) +}) + +// ── sortRuns — pure unit tests ──────────────────────────────────────────────── + +describe("sortRuns", () => { + function s(key: SortKey, dir: "asc" | "desc" = "asc") { + return (runs: ReturnType[]) => sortRuns(runs, key, dir) + } + + it("sorts by runNumber asc", () => { + const runs = [makeRun({ runNumber: 3 }), makeRun({ runNumber: 1 }), makeRun({ runNumber: 2 })] + expect(s("runNumber")(runs).map((r) => r.runNumber)).toEqual([1, 2, 3]) + }) + + it("sorts by runNumber desc", () => { + const runs = [makeRun({ runNumber: 1 }), makeRun({ runNumber: 3 }), makeRun({ runNumber: 2 })] + expect(s("runNumber", "desc")(runs).map((r) => r.runNumber)).toEqual([3, 2, 1]) + }) + + it("sorts by displayTitle asc (case-insensitive locale)", () => { + const runs = [makeRun({ displayTitle: "Zebra" }), makeRun({ displayTitle: "Alpha" })] + expect(s("displayTitle")(runs).map((r) => r.displayTitle)).toEqual(["Alpha", "Zebra"]) + }) + + it("sorts by workflowName asc", () => { + const runs = [makeRun({ workflowName: "Release" }), makeRun({ workflowName: "CI" })] + expect(s("workflowName")(runs).map((r) => r.workflowName)).toEqual(["CI", "Release"]) + }) + + it("sorts by headBranch asc", () => { + const runs = [makeRun({ headBranch: "main" }), makeRun({ headBranch: "develop" })] + expect(s("headBranch")(runs).map((r) => r.headBranch)).toEqual(["develop", "main"]) + }) + + it("sorts by event asc alphabetically", () => { + const runs = [ + makeRun({ event: "workflow_dispatch" }), + makeRun({ event: "push" }), + makeRun({ event: "schedule" }), + ] + expect(s("event")(runs).map((r) => r.event)).toEqual(["push", "schedule", "workflow_dispatch"]) + }) + + it("sorts by actor login asc", () => { + const runs = [ + makeRun({ actor: { login: "zara", avatarUrl: "" } }), + makeRun({ actor: { login: "alice", avatarUrl: "" } }), + ] + expect(s("actor")(runs).map((r) => r.actor?.login)).toEqual(["alice", "zara"]) + }) + + it("sorts null actor as empty string (last asc)", () => { + const runs = [ + makeRun({ actor: null }), + makeRun({ actor: { login: "alice", avatarUrl: "" } }), + ] + expect(s("actor")(runs).map((r) => r.actor?.login ?? "")).toEqual(["", "alice"]) + }) + + it("sorts by status asc: running → failure → cancelled → success", () => { + const runs = [ + makeRun({ status: "completed", conclusion: "success" }), + makeRun({ status: "in_progress", conclusion: null }), + makeRun({ status: "completed", conclusion: "cancelled" }), + makeRun({ status: "completed", conclusion: "failure" }), + ] + const sorted = s("status")(runs) + expect(sorted.map((r) => r.conclusion ?? r.status)).toEqual([ + "in_progress", "failure", "cancelled", "success", + ]) + }) + + it("sorts by status desc: success → cancelled → failure → running", () => { + const runs = [ + makeRun({ status: "in_progress", conclusion: null }), + makeRun({ status: "completed", conclusion: "failure" }), + makeRun({ status: "completed", conclusion: "success" }), + ] + const sorted = s("status", "desc")(runs) + expect(sorted.map((r) => r.conclusion ?? r.status)).toEqual([ + "success", "failure", "in_progress", + ]) + }) + + it("sorts by duration asc (shorter first)", () => { + const runs = [ + makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:10:00Z" }), // 10 min + makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:02:00Z" }), // 2 min + ] + const sorted = s("duration")(runs) + const durations = sorted.map( + (r) => new Date(r.updatedAt).getTime() - new Date(r.runStartedAt!).getTime() + ) + expect(durations[0]).toBeLessThan(durations[1]!) + }) + + it("sorts by duration desc (longer first)", () => { + const runs = [ + makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:02:00Z" }), // 2 min + makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:10:00Z" }), // 10 min + ] + const sorted = s("duration", "desc")(runs) + const durations = sorted.map( + (r) => new Date(r.updatedAt).getTime() - new Date(r.runStartedAt!).getTime() + ) + expect(durations[0]).toBeGreaterThan(durations[1]!) + }) + + it("sorts by started asc (oldest first)", () => { + const runs = [ + makeRun({ runStartedAt: "2024-03-01T00:00:00Z" }), + makeRun({ runStartedAt: "2024-01-01T00:00:00Z" }), + ] + expect(s("started")(runs).map((r) => r.runStartedAt)).toEqual([ + "2024-01-01T00:00:00Z", + "2024-03-01T00:00:00Z", + ]) + }) + + it("sorts by started desc (newest first)", () => { + const runs = [ + makeRun({ runStartedAt: "2024-01-01T00:00:00Z" }), + makeRun({ runStartedAt: "2024-03-01T00:00:00Z" }), + ] + expect(s("started", "desc")(runs).map((r) => r.runStartedAt)).toEqual([ + "2024-03-01T00:00:00Z", + "2024-01-01T00:00:00Z", + ]) + }) + + it("does not mutate the original array", () => { + const runs = [makeRun({ runNumber: 2 }), makeRun({ runNumber: 1 })] + const original = runs.map((r) => r.runNumber) + sortRuns(runs, "runNumber", "asc") + expect(runs.map((r) => r.runNumber)).toEqual(original) + }) +}) + +// ── Filter input ────────────────────────────────────────────────────────────── + +describe("RunsList — filter input", () => { + it("renders a single filter input with the combined placeholder", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + expect( + screen.getByPlaceholderText( + "Search here...", + ), + ).toBeInTheDocument() + }) + + it("input is empty when q search param is absent", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + const input = screen.getByPlaceholderText( + "Search here...", + ) as HTMLInputElement + expect(input.value).toBe("") + }) + + it("pre-fills the input when q is set (e.g. from WorkflowsCard link)", () => { + withSearch({ page: 1, q: "Nightly Dependency audit" }) + withRuns([]) + render() + const input = screen.getByPlaceholderText( + "Search here...", + ) as HTMLInputElement + expect(input.value).toBe("Nightly Dependency audit") + }) + + it("typing calls navigate with updated q and resets page to 1", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + fireEvent.change( + screen.getByPlaceholderText("Search here..."), + { target: { value: "main" } }, + ) + expect(mockNavigate).toHaveBeenCalledOnce() + const { search } = mockNavigate.mock.calls[0]![0] as { + search: (prev: Record) => Record + } + const updated = search({ page: 3 }) + expect(updated.q).toBe("main") + expect(updated.page).toBe(1) + }) + + it("clearing the input sets q to undefined", () => { + withSearch({ page: 1, q: "CI" }) + withRuns([]) + render() + fireEvent.change( + screen.getByPlaceholderText("Search here..."), + { target: { value: "" } }, + ) + const { search } = mockNavigate.mock.calls[0]![0] as { + search: (prev: Record) => Record + } + expect(search({}).q).toBeUndefined() + }) + + it("only one filter input is rendered (no branch or status inputs)", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + expect(screen.getAllByRole("textbox")).toHaveLength(1) + }) +}) + +// ── Client-side filtering in the table ─────────────────────────────────────── + +describe("RunsList — filtered table output", () => { + it("shows all runs when q is not set", () => { + withSearch({ page: 1 }) + withRuns([ + makeRun({ displayTitle: "Run A", workflowName: "CI" }), + makeRun({ displayTitle: "Run B", workflowName: "Deploy" }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.getByText("Run B")).toBeInTheDocument() + }) + + it("hides runs that don't match the query", () => { + withSearch({ page: 1, q: "deploy" }) + withRuns([ + makeRun({ displayTitle: "Run A", workflowName: "CI" }), + makeRun({ displayTitle: "Run B", workflowName: "Deploy" }), + ]) + render() + expect(screen.queryByText("Run A")).not.toBeInTheDocument() + expect(screen.getByText("Run B")).toBeInTheDocument() + }) + + it("filters by branch", () => { + withSearch({ page: 1, q: "feature/x" }) + withRuns([ + makeRun({ displayTitle: "Run A", headBranch: "feature/x", workflowName: "CI" }), + makeRun({ displayTitle: "Run B", headBranch: "main", workflowName: "CI" }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.queryByText("Run B")).not.toBeInTheDocument() + }) + + it("filters by commit SHA prefix", () => { + withSearch({ page: 1, q: "deadbeef" }) + withRuns([ + makeRun({ displayTitle: "Run A", headSha: "deadbeef12345678" }), + makeRun({ displayTitle: "Run B", headSha: "aaaabbbbccccdddd" }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.queryByText("Run B")).not.toBeInTheDocument() + }) + + it("filters by actor login", () => { + withSearch({ page: 1, q: "alice" }) + withRuns([ + makeRun({ displayTitle: "Run A", actor: { login: "alice", avatarUrl: "" } }), + makeRun({ displayTitle: "Run B", actor: { login: "bob", avatarUrl: "" } }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.queryByText("Run B")).not.toBeInTheDocument() + }) + + it("filters by status", () => { + withSearch({ page: 1, q: "in_progress" }) + withRuns([ + makeRun({ displayTitle: "Run A", status: "in_progress", conclusion: null }), + makeRun({ displayTitle: "Run B", status: "completed", conclusion: "success" }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.queryByText("Run B")).not.toBeInTheDocument() + }) + + it("filters by conclusion", () => { + withSearch({ page: 1, q: "failure" }) + withRuns([ + makeRun({ displayTitle: "Run A", status: "completed", conclusion: "failure" }), + makeRun({ displayTitle: "Run B", status: "completed", conclusion: "success" }), + ]) + render() + expect(screen.getByText("Run A")).toBeInTheDocument() + expect(screen.queryByText("Run B")).not.toBeInTheDocument() + }) + + it("shows empty state when filter matches nothing", () => { + withSearch({ page: 1, q: "zzznomatch" }) + withRuns([makeRun({ workflowName: "CI" })]) + render() + expect(screen.getByText("No runs found.")).toBeInTheDocument() + }) +}) + +// ── Pagination ──────────────────────────────────────────────────────────────── + +describe("RunsList — pagination", () => { + it("shows pagination when no filter is active and total > 30", () => { + withSearch({ page: 1 }) + mockUseQuery.mockReturnValue({ + data: { runs: [makeRun()], total: 90 }, + isLoading: false, + } as ReturnType) + render() + expect(screen.getByText(/Page 1 of 3/)).toBeInTheDocument() + }) + + it("hides pagination when a filter is active", () => { + withSearch({ page: 1, q: "CI" }) + mockUseQuery.mockReturnValue({ + data: { runs: Array.from({ length: 5 }, () => makeRun({ workflowName: "CI" })), total: 300 }, + isLoading: false, + } as ReturnType) + render() + expect(screen.queryByText(/Page/)).not.toBeInTheDocument() + }) +}) + +// ── Basic states ────────────────────────────────────────────────────────────── + +describe("RunsList — basic states", () => { + it("shows spinner while loading", () => { + withSearch({ page: 1 }) + mockUseQuery.mockReturnValue({ data: undefined, isLoading: true } as ReturnType) + render() + expect(screen.getByTestId("page-spinner")).toBeInTheDocument() + }) + + it("shows empty state when no runs are returned", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + expect(screen.getByText("No runs found.")).toBeInTheDocument() + }) + + it("renders the Workflow column header", () => { + withSearch({ page: 1 }) + withRuns([makeRun()]) + render() + expect(screen.getByRole("columnheader", { name: "Workflow" })).toBeInTheDocument() + }) + + it("shows workflowName in each row", () => { + withSearch({ page: 1 }) + withRuns([makeRun({ workflowName: "Release Pipeline" })]) + render() + expect(screen.getByText("Release Pipeline")).toBeInTheDocument() + }) + + it("breadcrumb renders owner and repo as separate items, not combined", () => { + withSearch({ page: 1 }) + withRuns([]) + render() + // owner and repo appear as separate text nodes + expect(screen.getByText("acme")).toBeInTheDocument() + expect(screen.getByText("api")).toBeInTheDocument() + // they are NOT rendered as a combined "acme/api" string + expect(screen.queryByText("acme/api")).not.toBeInTheDocument() + }) + + it("all column headers are clickable", () => { + withSearch({ page: 1 }) + withRuns([makeRun()]) + render() + for (const name of ["#", "Run", "Workflow", "Branch / Commit", "Event", "Actor", "Status", "Duration", "Started"]) { + expect(screen.getByRole("columnheader", { name })).toBeInTheDocument() + } + }) +}) + +// ── Sort ────────────────────────────────────────────────────────────────────── + +describe("RunsList — column sort", () => { + it("clicking a column header sorts rows by that column", () => { + withSearch({ page: 1 }) + withRuns([ + makeRun({ workflowName: "Zebra", displayTitle: "Run 1" }), + makeRun({ workflowName: "Alpha", displayTitle: "Run 2" }), + ]) + render() + fireEvent.click(screen.getByRole("columnheader", { name: "Workflow" })) + const rows = screen.getAllByRole("row").slice(1) + expect(rows[0]).toHaveTextContent("Alpha") + expect(rows[1]).toHaveTextContent("Zebra") + }) + + it("clicking the same header again reverses sort direction", () => { + withSearch({ page: 1 }) + withRuns([ + makeRun({ workflowName: "Alpha" }), + makeRun({ workflowName: "Zebra" }), + ]) + render() + const header = screen.getByRole("columnheader", { name: "Workflow" }) + fireEvent.click(header) // first click: asc → Alpha, Zebra + fireEvent.click(header) // second click: desc → Zebra, Alpha + const rows = screen.getAllByRole("row").slice(1) + expect(rows[0]).toHaveTextContent("Zebra") + expect(rows[1]).toHaveTextContent("Alpha") + }) + + it("clicking a different header resets to that column's default direction", () => { + withSearch({ page: 1 }) + withRuns([ + makeRun({ workflowName: "Alpha", headBranch: "main" }), + makeRun({ workflowName: "Zebra", headBranch: "develop" }), + ]) + render() + fireEvent.click(screen.getByRole("columnheader", { name: "Branch / Commit" })) + const rows = screen.getAllByRole("row").slice(1) + expect(rows[0]).toHaveTextContent("develop") + expect(rows[1]).toHaveTextContent("main") + }) +}) diff --git a/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx b/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx index 86a8c79..2512c18 100644 --- a/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx +++ b/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx @@ -4,6 +4,8 @@ import type { WorkflowRun, Workflow } from "../../types/index.js" // ── Mocks (must precede imports of the module under test) ───────────────────── +const mockUseChildMatches = vi.fn(() => [] as unknown[]) + vi.mock("@tanstack/react-router", () => ({ // eslint-disable-next-line @typescript-eslint/no-explicit-any createFileRoute: () => (opts: any) => ({ @@ -11,7 +13,9 @@ vi.mock("@tanstack/react-router", () => ({ useParams: vi.fn(() => ({ owner: "acme", repo: "api" })), }), // eslint-disable-next-line @typescript-eslint/no-explicit-any - Link: ({ children, to: _to, params: _p, ...rest }: any) => {children}, + Link: ({ children, to: _to, params: _p, search: _s, ...rest }: any) => {children}, + Outlet: () =>
, + useChildMatches: () => mockUseChildMatches(), })) vi.mock("@tanstack/react-query", () => ({ @@ -73,7 +77,11 @@ import { Route, triggersFromRuns, WorkflowsCard, RecentRunsCard } from "./reposi // ── Test helpers ─────────────────────────────────────────────────────────────── let _id = 0 -beforeEach(() => { _id = 0; vi.clearAllMocks() }) +beforeEach(() => { + _id = 0 + vi.clearAllMocks() + mockUseChildMatches.mockReturnValue([]) +}) function makeRun(overrides: Partial = {}): WorkflowRun { return { @@ -242,6 +250,49 @@ describe("WorkflowsCard", () => { }) }) +// ── WorkflowsCard — name links ──────────────────────────────────────────────── + +describe("WorkflowsCard — workflow name links", () => { + it("renders the workflow name as an internal link (Link mock, no github.com href)", () => { + const workflow = makeWorkflow({ id: 1, name: "Deploy Production" }) + mockUseQuery + .mockReturnValueOnce({ data: [workflow], isLoading: false } as ReturnType) + .mockReturnValueOnce({ data: { runs: [] }, isLoading: false } as ReturnType) + const { container } = render() + // Link mock renders without href; the external ↗ has the github.com href + const anchors = Array.from(container.querySelectorAll("a")) + const nameAnchor = anchors.find((a) => a.textContent?.trim() === "Deploy Production") + expect(nameAnchor).toBeTruthy() + expect(nameAnchor!.getAttribute("href") ?? "").not.toContain("github.com") + }) + + it("renders an external ↗ icon linking to the workflow file on GitHub", () => { + const workflow = makeWorkflow({ + id: 1, + htmlUrl: "https://github.com/acme/api/actions/workflows/deploy.yml", + }) + mockUseQuery + .mockReturnValueOnce({ data: [workflow], isLoading: false } as ReturnType) + .mockReturnValueOnce({ data: { runs: [] }, isLoading: false } as ReturnType) + render() + const icon = screen.getByTitle("Open workflow on GitHub") + expect(icon).toBeInTheDocument() + expect(icon).toHaveAttribute("href", "https://github.com/acme/api/actions/workflows/deploy.yml") + expect(icon).toHaveAttribute("target", "_blank") + }) + + it("each workflow row has an independent name link and external icon", () => { + const wf1 = makeWorkflow({ id: 1, name: "CI" }) + const wf2 = makeWorkflow({ id: 2, name: "Deploy" }) + mockUseQuery + .mockReturnValueOnce({ data: [wf1, wf2], isLoading: false } as ReturnType) + .mockReturnValueOnce({ data: { runs: [] }, isLoading: false } as ReturnType) + render() + const icons = screen.getAllByTitle("Open workflow on GitHub") + expect(icons).toHaveLength(2) + }) +}) + // ── RecentRunsCard ──────────────────────────────────────────────────────────── describe("RecentRunsCard", () => { @@ -350,4 +401,23 @@ describe("RepositoryDetail page", () => { render() expect(screen.getByText("api")).toBeInTheDocument() }) + + it("renders Outlet (not repo content) when a child route is active", () => { + mockUseChildMatches.mockReturnValue([{ routeId: "/_app/repositories/$owner/$repo/runs" }]) + mockUseQuery.mockReturnValue({ data: undefined, isLoading: false } as ReturnType) + render() + expect(screen.getByTestId("outlet")).toBeInTheDocument() + expect(screen.queryByTestId("page-spinner")).not.toBeInTheDocument() + expect(screen.queryByText("Repository not found.")).not.toBeInTheDocument() + }) + + it("renders repo detail content (not Outlet) when no child route is active", () => { + mockUseChildMatches.mockReturnValue([]) + mockUseQuery + .mockReturnValueOnce({ data: { id: 1 }, isLoading: false } as ReturnType) + .mockReturnValue({ data: undefined, isLoading: false } as ReturnType) + const { container } = render() + expect(screen.queryByTestId("outlet")).not.toBeInTheDocument() + expect(container.querySelector(".health-repo-label-owner")).not.toBeNull() + }) }) diff --git a/packages/web/src/routes/_app/-runs.test.tsx b/packages/web/src/routes/_app/-runs.test.tsx index a8555a2..d2e1764 100644 --- a/packages/web/src/routes/_app/-runs.test.tsx +++ b/packages/web/src/routes/_app/-runs.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach } from "vitest" -import { render, screen } from "@testing-library/react" +import { render, screen, fireEvent } from "@testing-library/react" import type { WorkflowRun } from "../../types/index.js" // ── Mocks ───────────────────────────────────────────────────────────────────── @@ -49,8 +49,8 @@ vi.mock("../../components/ui/EventBadge.js", () => ({ import React from "react" import { useQuery, useQueries } from "@tanstack/react-query" -import { Route, mergeAndSortRuns, filterRuns, AllRunsTable } from "./runs.js" -import type { RunWithRepo } from "./runs.js" +import { Route, mergeAndSortRuns, filterRuns, sortRuns, AllRunsTable } from "./runs.js" +import type { RunWithRepo, SortKey } from "./runs.js" // ── Helpers ─────────────────────────────────────────────────────────────────── @@ -143,6 +143,7 @@ describe("AllRunsTable", () => { render() expect(screen.getByText("Repository")).toBeInTheDocument() expect(screen.getByText("Run")).toBeInTheDocument() + expect(screen.getByText("Workflow")).toBeInTheDocument() expect(screen.getByText("Branch / Commit")).toBeInTheDocument() expect(screen.getByText("Event")).toBeInTheDocument() expect(screen.getByText("Actor")).toBeInTheDocument() @@ -151,6 +152,12 @@ describe("AllRunsTable", () => { expect(screen.getByText("Started")).toBeInTheDocument() }) + it("renders workflowName in each row", () => { + const run = makeRun({ workflowName: "Release Pipeline" }) + render() + expect(screen.getByText("Release Pipeline")).toBeInTheDocument() + }) + it("renders one row per run", () => { const runs = [entry(makeRun()), entry(makeRun()), entry(makeRun())] const { container } = render() @@ -234,6 +241,52 @@ describe("AllRunsTable", () => { render() expect(screen.queryByText(/×/)).not.toBeInTheDocument() }) + + it("all column headers are clickable", () => { + render() + for (const name of ["Repository", "Run", "Workflow", "Branch / Commit", "Event", "Actor", "Status", "Duration", "Started"]) { + expect(screen.getByRole("columnheader", { name })).toBeInTheDocument() + } + }) + + it("clicking a column header sorts rows by that column", () => { + const runs = [ + entry(makeRun({ workflowName: "Zebra" })), + entry(makeRun({ workflowName: "Alpha" })), + ] + render() + fireEvent.click(screen.getByRole("columnheader", { name: "Workflow" })) + const rows = screen.getAllByRole("row").slice(1) // skip header + expect(rows[0]).toHaveTextContent("Alpha") + expect(rows[1]).toHaveTextContent("Zebra") + }) + + it("clicking the same header again reverses sort direction", () => { + const runs = [ + entry(makeRun({ workflowName: "Alpha" })), + entry(makeRun({ workflowName: "Zebra" })), + ] + render() + const header = screen.getByRole("columnheader", { name: "Workflow" }) + fireEvent.click(header) // first click: asc → Alpha, Zebra + fireEvent.click(header) // second click: desc → Zebra, Alpha + const rows = screen.getAllByRole("row").slice(1) + expect(rows[0]).toHaveTextContent("Zebra") + expect(rows[1]).toHaveTextContent("Alpha") + }) + + it("clicking a different header resets to that column's default direction", () => { + const runs = [ + entry(makeRun({ workflowName: "Alpha", headBranch: "main" })), + entry(makeRun({ workflowName: "Zebra", headBranch: "develop" })), + ] + render() + // sort by branch asc: develop (Zebra), main (Alpha) + fireEvent.click(screen.getByRole("columnheader", { name: "Branch / Commit" })) + const rows = screen.getAllByRole("row").slice(1) + expect(rows[0]).toHaveTextContent("develop") + expect(rows[1]).toHaveTextContent("main") + }) }) // ── filterRuns ──────────────────────────────────────────────────────────────── @@ -303,6 +356,150 @@ describe("filterRuns", () => { expect(() => filterRuns(runs, "alice")).not.toThrow() expect(filterRuns(runs, "alice")).toHaveLength(0) }) + + it("filters by workflow name (case-insensitive)", () => { + const runs = [ + entry(makeRun({ workflowName: "Deploy Production" })), + entry(makeRun({ workflowName: "CI" })), + ] + expect(filterRuns(runs, "deploy")).toHaveLength(1) + expect(filterRuns(runs, "DEPLOY PRODUCTION")).toHaveLength(1) + }) + + it("filters by partial workflow name", () => { + const runs = [ + entry(makeRun({ workflowName: "Nightly Dependency audit" })), + entry(makeRun({ workflowName: "CI" })), + ] + expect(filterRuns(runs, "nightly")).toHaveLength(1) + expect(filterRuns(runs, "audit")).toHaveLength(1) + }) +}) + +// ── sortRuns ────────────────────────────────────────────────────────────────── + +describe("sortRuns (AllRuns)", () => { + function s(key: SortKey, dir: "asc" | "desc" = "asc") { + return (runs: RunWithRepo[]) => sortRuns(runs, key, dir) + } + + it("sorts by repository asc", () => { + const runs = [ + { run: makeRun(), owner: "zeta", repo: "api" }, + { run: makeRun(), owner: "acme", repo: "api" }, + ] + expect(s("repository")(runs).map((r) => r.owner)).toEqual(["acme", "zeta"]) + }) + + it("sorts by displayTitle asc", () => { + const runs = [ + entry(makeRun({ displayTitle: "Zebra" })), + entry(makeRun({ displayTitle: "Alpha" })), + ] + expect(s("displayTitle")(runs).map((r) => r.run.displayTitle)).toEqual(["Alpha", "Zebra"]) + }) + + it("sorts by workflowName asc", () => { + const runs = [ + entry(makeRun({ workflowName: "Release" })), + entry(makeRun({ workflowName: "CI" })), + ] + expect(s("workflowName")(runs).map((r) => r.run.workflowName)).toEqual(["CI", "Release"]) + }) + + it("sorts by event asc alphabetically", () => { + const runs = [ + entry(makeRun({ event: "workflow_dispatch" })), + entry(makeRun({ event: "push" })), + entry(makeRun({ event: "schedule" })), + ] + expect(s("event")(runs).map((r) => r.run.event)).toEqual(["push", "schedule", "workflow_dispatch"]) + }) + + it("sorts by status asc: running → failure → cancelled → success", () => { + const runs = [ + entry(makeRun({ status: "completed", conclusion: "success" })), + entry(makeRun({ status: "in_progress", conclusion: null })), + entry(makeRun({ status: "completed", conclusion: "failure" })), + ] + const sorted = s("status")(runs) + expect(sorted.map((r) => r.run.conclusion ?? r.run.status)).toEqual([ + "in_progress", "failure", "success", + ]) + }) + + it("sorts by status desc: success → failure → running", () => { + const runs = [ + entry(makeRun({ status: "in_progress", conclusion: null })), + entry(makeRun({ status: "completed", conclusion: "failure" })), + entry(makeRun({ status: "completed", conclusion: "success" })), + ] + const sorted = s("status", "desc")(runs) + expect(sorted.map((r) => r.run.conclusion ?? r.run.status)).toEqual([ + "success", "failure", "in_progress", + ]) + }) + + it("sorts by started desc (newest first)", () => { + const runs = [ + entry(makeRun({ runStartedAt: "2024-01-01T00:00:00Z" })), + entry(makeRun({ runStartedAt: "2024-06-01T00:00:00Z" })), + ] + expect(s("started", "desc")(runs).map((r) => r.run.runStartedAt)).toEqual([ + "2024-06-01T00:00:00Z", + "2024-01-01T00:00:00Z", + ]) + }) + + it("sorts by headBranch asc", () => { + const runs = [ + entry(makeRun({ headBranch: "main" })), + entry(makeRun({ headBranch: "develop" })), + ] + expect(s("headBranch")(runs).map((r) => r.run.headBranch)).toEqual(["develop", "main"]) + }) + + it("sorts by actor login asc", () => { + const runs = [ + entry(makeRun({ actor: { login: "zara", avatarUrl: "" } })), + entry(makeRun({ actor: { login: "alice", avatarUrl: "" } })), + ] + expect(s("actor")(runs).map((r) => r.run.actor?.login)).toEqual(["alice", "zara"]) + }) + + it("sorts by duration desc (longer first)", () => { + const runs = [ + entry(makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:02:00Z" })), // 2 min + entry(makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:10:00Z" })), // 10 min + ] + const sorted = s("duration", "desc")(runs) + const durations = sorted.map( + (r) => new Date(r.run.updatedAt).getTime() - new Date(r.run.runStartedAt!).getTime() + ) + expect(durations[0]).toBeGreaterThan(durations[1]!) + }) + + it("sorts by duration asc (shorter first)", () => { + const runs = [ + entry(makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:10:00Z" })), // 10 min + entry(makeRun({ runStartedAt: "2024-01-01T10:00:00Z", updatedAt: "2024-01-01T10:02:00Z" })), // 2 min + ] + const sorted = s("duration")(runs) + const durations = sorted.map( + (r) => new Date(r.run.updatedAt).getTime() - new Date(r.run.runStartedAt!).getTime() + ) + expect(durations[0]).toBeLessThan(durations[1]!) + }) + + it("does not mutate the original array", () => { + const runs = [ + entry(makeRun({ workflowName: "Z" })), + entry(makeRun({ workflowName: "A" })), + ] + const originalOrder = runs.map((r) => r.run.workflowName) + sortRuns(runs, "workflowName", "asc") + expect(runs.map((r) => r.run.workflowName)).toEqual(originalOrder) + }) }) // ── AllRuns page ────────────────────────────────────────────────────────────── @@ -381,6 +578,6 @@ describe("AllRuns page", () => { vi.mocked(useQuery).mockReturnValue({ data: [], isLoading: false } as never) vi.mocked(useQueries).mockReturnValue([]) render() - expect(screen.getByPlaceholderText(/Filter by repo/)).toBeInTheDocument() + expect(screen.getByPlaceholderText("Search here...")).toBeInTheDocument() }) }) diff --git a/packages/web/src/routes/_app/repositories.$owner.$repo.runs.$runId.tsx b/packages/web/src/routes/_app/repositories.$owner.$repo.runs.$runId.tsx index 1cbfb22..b59bb17 100644 --- a/packages/web/src/routes/_app/repositories.$owner.$repo.runs.$runId.tsx +++ b/packages/web/src/routes/_app/repositories.$owner.$repo.runs.$runId.tsx @@ -1,6 +1,6 @@ import { createFileRoute, Link } from "@tanstack/react-router" import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" -import { lazy, Suspense, useState, Fragment } from "react" +import { useState, Fragment } from "react" import { getRun, getRunJobs, getRuns, getRunArtifacts, getJobLogs, rerunWorkflow, rerunFailedJobs, cancelRun, @@ -9,13 +9,11 @@ import { StatusBadge } from "../../components/ui/Badge.js" import { EventBadge } from "../../components/ui/EventBadge.js" import { Button } from "../../components/ui/Button.js" import { Card, CardHeader } from "../../components/ui/Card.js" -import { PageSpinner, Spinner } from "../../components/ui/Spinner.js" +import { PageSpinner } from "../../components/ui/Spinner.js" import { formatRelativeTime, formatDuration, formatDateTime } from "../../lib/utils.js" import type { WorkflowRun, WorkflowJob, JobStep, RunArtifact } from "../../types/index.js" -const WorkflowDAG = lazy(() => - import("../../components/dag/WorkflowDAG.js").then((m) => ({ default: m.WorkflowDAG })) -) +import { WorkflowDAG } from "../../components/dag/WorkflowDAG.js" export const Route = createFileRoute("/_app/repositories/$owner/$repo/runs/$runId")({ component: RunDetail, @@ -95,8 +93,10 @@ function RunDetail() {
Repositories / + {owner} + / - {owner}/{repo} + {repo} / @@ -138,7 +138,7 @@ function RunDetail() { {!isActive && ( <> {hasFailed && (
}> - - + )} @@ -416,7 +414,7 @@ function BranchHistoryCard({ + View all } diff --git a/packages/web/src/routes/_app/repositories.$owner.$repo.runs.tsx b/packages/web/src/routes/_app/repositories.$owner.$repo.runs.tsx index 67db022..b95442c 100644 --- a/packages/web/src/routes/_app/repositories.$owner.$repo.runs.tsx +++ b/packages/web/src/routes/_app/repositories.$owner.$repo.runs.tsx @@ -1,7 +1,9 @@ +import { useState } from "react" import { createFileRoute, Link, useNavigate } from "@tanstack/react-router" import { useQuery } from "@tanstack/react-query" import { z } from "zod" import { getRuns } from "../../api/index.js" +import type { WorkflowRun } from "../../types/index.js" import { StatusBadge } from "../../components/ui/Badge.js" import { Button } from "../../components/ui/Button.js" import { PageSpinner } from "../../components/ui/Spinner.js" @@ -9,8 +11,7 @@ import { EventBadge } from "../../components/ui/EventBadge.js" import { formatRelativeTime, formatDuration, formatDateTime } from "../../lib/utils.js" const searchSchema = z.object({ - branch: z.string().optional(), - status: z.string().optional(), + q: z.string().optional(), page: z.number().optional().default(1), }) @@ -19,25 +20,136 @@ export const Route = createFileRoute("/_app/repositories/$owner/$repo/runs")({ component: RunsList, }) -function RunsList() { +// ── Sort ─────────────────────────────────────────────────────────────────────── + +export type SortKey = + | "runNumber" | "displayTitle" | "workflowName" | "headBranch" + | "event" | "actor" | "status" | "duration" | "started" + +/** Natural first-click direction for each column. */ +const DEFAULT_DIR: Record = { + runNumber: "desc", + displayTitle: "asc", + workflowName: "asc", + headBranch: "asc", + event: "asc", + actor: "asc", + status: "asc", // asc = problems first (running → failure → cancelled → success) + duration: "desc", + started: "desc", +} + +/** asc: running → failure → cancelled → success */ +function statusOrder(status: string, conclusion: string | null): number { + if (status !== "completed") return 0 + switch (conclusion) { + case "failure": + case "timed_out": return 1 + case "cancelled": + case "skipped": return 2 + case "success": return 3 + default: return 4 + } +} + +function runDurationMs(run: WorkflowRun): number { + if (!run.runStartedAt) return 0 + return new Date(run.updatedAt).getTime() - new Date(run.runStartedAt).getTime() +} + +export function sortRuns( + runs: WorkflowRun[], + key: SortKey, + dir: "asc" | "desc", +): WorkflowRun[] { + const factor = dir === "asc" ? 1 : -1 + return [...runs].sort((a, b) => { + let cmp = 0 + switch (key) { + case "runNumber": cmp = a.runNumber - b.runNumber; break + case "displayTitle": cmp = a.displayTitle.localeCompare(b.displayTitle); break + case "workflowName": cmp = a.workflowName.localeCompare(b.workflowName); break + case "headBranch": cmp = a.headBranch.localeCompare(b.headBranch); break + case "event": cmp = a.event.localeCompare(b.event); break + case "actor": cmp = (a.actor?.login ?? "").localeCompare(b.actor?.login ?? ""); break + case "status": cmp = statusOrder(a.status, a.conclusion) - statusOrder(b.status, b.conclusion); break + case "duration": cmp = runDurationMs(a) - runDurationMs(b); break + case "started": cmp = new Date(a.runStartedAt ?? a.createdAt).getTime() - new Date(b.runStartedAt ?? b.createdAt).getTime(); break + } + return factor * cmp + }) +} + +// ── Filter ───────────────────────────────────────────────────────────────────── + +/** + * Client-side multi-field filter. Checks all searchable text fields on a run + * against the query string (case-insensitive substring match). + * + * Fields searched: workflow name, branch, commit SHA, actor login, + * run status, and conclusion. + */ +export function filterRuns(runs: WorkflowRun[], q: string): WorkflowRun[] { + if (!q) return runs + const lower = q.toLowerCase() + return runs.filter( + (r) => + r.workflowName.toLowerCase().includes(lower) || + r.headBranch.toLowerCase().includes(lower) || + r.headSha.toLowerCase().includes(lower) || + (r.actor?.login.toLowerCase().includes(lower) ?? false) || + r.status.toLowerCase().includes(lower) || + (r.conclusion?.toLowerCase().includes(lower) ?? false), + ) +} + +// ── Component ────────────────────────────────────────────────────────────────── + +export function RunsList() { const { owner, repo } = Route.useParams() - const { branch, status, page } = Route.useSearch() + const { q, page } = Route.useSearch() const navigate = useNavigate({ from: Route.fullPath }) + const [sortKey, setSortKey] = useState("started") + const [sortDir, setSortDir] = useState<"asc" | "desc">("desc") + + function toggleSort(key: SortKey) { + if (key === sortKey) { + setSortDir((d) => (d === "asc" ? "desc" : "asc")) + } else { + setSortKey(key) + setSortDir(DEFAULT_DIR[key]) + } + } + + // When a filter is active, fetch a larger batch so the client-side filter + // has enough history. Pagination is suppressed in this mode. + const perPage = q ? 100 : 30 + const { data, isLoading } = useQuery({ - queryKey: ["runs", `${owner}/${repo}`, { branch, status, page }], - queryFn: () => getRuns(owner, repo, { branch, status, page, per_page: 30 }), + queryKey: ["runs", `${owner}/${repo}`, { page: q ? 1 : page, perPage }], + queryFn: () => getRuns(owner, repo, { page: q ? 1 : page, per_page: perPage }), refetchInterval: 30_000, }) - function setSearch(updates: Partial>) { - void navigate({ search: (prev) => ({ ...prev, ...updates, page: 1 }) }) + const allRuns = data?.runs ?? [] + const runs = sortRuns(filterRuns(allRuns, q ?? ""), sortKey, sortDir) + const totalPages = q ? 0 : Math.ceil((data?.total ?? 0) / 30) + + function setQ(value: string) { + void navigate({ search: (prev) => ({ ...prev, q: value || undefined, page: 1 }) }) } if (isLoading) return - const runs = data?.runs ?? [] - const totalPages = Math.ceil((data?.total ?? 0) / 30) + const th = (key: SortKey, label: string, extra?: React.CSSProperties) => ( + toggleSort(key)} + style={{ cursor: "pointer", userSelect: "none", ...extra }} + > + {label} + + ) return (
@@ -45,46 +157,33 @@ function RunsList() {
Repositories / + {owner} + / - {owner}/{repo} + {repo} / Runs
-
+
setSearch({ branch: e.target.value || undefined })} + placeholder="Search here..." + value={q ?? ""} + onChange={(e) => setQ(e.target.value)} style={{ - padding: "0.25rem 0.5rem", borderRadius: "var(--radius)", + width: "100%", maxWidth: 480, + padding: "0.375rem 0.625rem", borderRadius: "var(--radius)", border: "1px solid var(--color-border)", background: "var(--color-bg)", color: "var(--color-text)", fontSize: 13, }} /> -
@@ -95,14 +194,15 @@ function RunsList() { - - - - - - - - + {th("runNumber", "#")} + {th("displayTitle", "Run")} + {th("workflowName", "Workflow")} + {th("headBranch", "Branch / Commit")} + {th("event", "Event")} + {th("actor", "Actor")} + {th("status", "Status")} + {th("duration", "Duration")} + {th("started", "Started")} @@ -113,6 +213,8 @@ function RunsList() { {run.displayTitle} @@ -122,6 +224,7 @@ function RunsList() { )} + diff --git a/packages/web/src/routes/_app/repositories.tsx b/packages/web/src/routes/_app/repositories.tsx index 326a13c..ce61ba4 100644 --- a/packages/web/src/routes/_app/repositories.tsx +++ b/packages/web/src/routes/_app/repositories.tsx @@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query" import { useState } from "react" import { getRepos, getRuns } from "../../api/index.js" import { StatusBadge } from "../../components/ui/Badge.js" +import { Card, CardHeader } from "../../components/ui/Card.js" import { PageSpinner } from "../../components/ui/Spinner.js" import { SuccessSquares } from "../../components/ui/SuccessSquares.js" import { formatRelativeTime } from "../../lib/utils.js" @@ -43,44 +44,47 @@ function Repositories() { ) : repos + const title = q + ? `Repositories (${visibleRepos.length} of ${repos.length})` + : `Repositories (${repos.length})` + return (
-
- setFilter(e.target.value)} - style={{ - width: "100%", - padding: "0.3125rem 0.625rem", - fontSize: 13, - border: "1px solid var(--color-border)", - borderRadius: "var(--radius)", - background: "var(--color-bg)", - color: "var(--color-text)", - }} - /> -
-
-
-
#RunBranch / CommitEventActorStatusDurationStarted
{run.workflowName}
{run.headBranch} @@ -150,7 +255,7 @@ function RunsList() { {run.actor?.login ?? "—"}
- + {formatDuration(run.runStartedAt, run.updatedAt)} @@ -170,7 +275,7 @@ function RunsList() { @@ -180,7 +285,7 @@ function RunsList() { diff --git a/packages/web/src/routes/_app/repositories.$owner.$repo.tsx b/packages/web/src/routes/_app/repositories.$owner.$repo.tsx index 4bd4034..98667fa 100644 --- a/packages/web/src/routes/_app/repositories.$owner.$repo.tsx +++ b/packages/web/src/routes/_app/repositories.$owner.$repo.tsx @@ -1,4 +1,4 @@ -import { createFileRoute, Link } from "@tanstack/react-router" +import { createFileRoute, Link, Outlet, useChildMatches } from "@tanstack/react-router" import { useQuery } from "@tanstack/react-query" import { getRepo, getRepoScore, getWorkflows, getRuns } from "../../api/index.js" import { StatusBadge, TierBadge } from "../../components/ui/Badge.js" @@ -30,12 +30,18 @@ export function triggersFromRuns(runs: WorkflowRun[]): Map { function RepositoryDetail() { const { owner, repo } = Route.useParams() + const childMatches = useChildMatches() + // Always call useQuery — hooks must not be called conditionally. const { data: repoData, isLoading: repoLoading } = useQuery({ queryKey: ["repo", owner, repo], queryFn: () => getRepo(owner, repo), }) + // When a child route is active (e.g. /runs, /runs/$runId), render it + // exclusively. Outlet renders nothing when no child is matched. + if (childMatches.length > 0) return + if (repoLoading) return if (!repoData) return

Repository not found.

@@ -165,8 +171,23 @@ export function WorkflowsCard({ owner, repo }: { owner: string; repo: string }) return (
- + {w.name} + + {" "} + + ↗ {w.path}
- - - - - - - - - - - {visibleRepos.length === 0 ? ( + + +
+ setFilter(e.target.value)} + style={{ + width: "100%", + padding: "0.3125rem 0.625rem", + fontSize: 13, + border: "1px solid var(--color-border)", + borderRadius: "var(--radius)", + background: "var(--color-bg)", + color: "var(--color-text)", + }} + /> +
+ {visibleRepos.length === 0 ? ( +

No repositories match "{filter}".

+ ) : ( +
+
RepositoryLanguageLast pushLast runHealth
+ - + + + + + - ) : ( - visibleRepos.map((repo) => { + + + {visibleRepos.map((repo) => { const [owner, name] = repo.fullName.split("/") return ( ) - }) - )} - -
No repositories match "{filter}".RepositoryLanguageLast pushLast runHealth
-
-
+ })} + + +
+ )} +
) } diff --git a/packages/web/src/routes/_app/runs.tsx b/packages/web/src/routes/_app/runs.tsx index 49f6383..daf7fd6 100644 --- a/packages/web/src/routes/_app/runs.tsx +++ b/packages/web/src/routes/_app/runs.tsx @@ -1,3 +1,4 @@ +import { useState } from "react" import { createFileRoute, Link, useNavigate } from "@tanstack/react-router" import { useQuery, useQueries } from "@tanstack/react-query" import { z } from "zod" @@ -33,17 +34,78 @@ export function mergeAndSortRuns(perRepo: RunWithRepo[][]): RunWithRepo[] { .sort((a, b) => new Date(b.run.createdAt).getTime() - new Date(a.run.createdAt).getTime()) } -/** Case-insensitive filter across repo, title, branch and actor. */ +/** Case-insensitive filter across repo, title, branch, actor and workflow name. */ export function filterRuns(runs: RunWithRepo[], query: string): RunWithRepo[] { const q = query.toLowerCase() return runs.filter(({ run, owner, repo }) => `${owner}/${repo}`.includes(q) || run.displayTitle.toLowerCase().includes(q) || run.headBranch.toLowerCase().includes(q) || - (run.actor?.login.toLowerCase().includes(q) ?? false) + (run.actor?.login.toLowerCase().includes(q) ?? false) || + run.workflowName.toLowerCase().includes(q) ) } +// ── Sort ─────────────────────────────────────────────────────────────────────── + +export type SortKey = + | "repository" | "displayTitle" | "workflowName" | "headBranch" + | "event" | "actor" | "status" | "duration" | "started" + +/** Natural first-click direction for each column. */ +const DEFAULT_DIR: Record = { + repository: "asc", + displayTitle: "asc", + workflowName: "asc", + headBranch: "asc", + event: "asc", + actor: "asc", + status: "asc", // asc = problems first (running → failure → cancelled → success) + duration: "desc", + started: "desc", +} + +/** asc: running → failure → cancelled → success */ +function statusOrder(status: string, conclusion: string | null): number { + if (status !== "completed") return 0 + switch (conclusion) { + case "failure": + case "timed_out": return 1 + case "cancelled": + case "skipped": return 2 + case "success": return 3 + default: return 4 + } +} + +function runDurationMs(run: WorkflowRun): number { + if (!run.runStartedAt) return 0 + return new Date(run.updatedAt).getTime() - new Date(run.runStartedAt).getTime() +} + +export function sortRuns( + runs: RunWithRepo[], + key: SortKey, + dir: "asc" | "desc", +): RunWithRepo[] { + const factor = dir === "asc" ? 1 : -1 + return [...runs].sort((a, b) => { + let cmp = 0 + switch (key) { + case "repository": cmp = `${a.owner}/${a.repo}`.localeCompare(`${b.owner}/${b.repo}`); break + case "displayTitle": cmp = a.run.displayTitle.localeCompare(b.run.displayTitle); break + case "workflowName": cmp = a.run.workflowName.localeCompare(b.run.workflowName); break + case "headBranch": cmp = a.run.headBranch.localeCompare(b.run.headBranch); break + case "event": cmp = a.run.event.localeCompare(b.run.event); break + case "actor": cmp = (a.run.actor?.login ?? "").localeCompare(b.run.actor?.login ?? ""); break + case "status": cmp = statusOrder(a.run.status, a.run.conclusion) - statusOrder(b.run.status, b.run.conclusion); break + case "duration": cmp = runDurationMs(a.run) - runDurationMs(b.run); break + case "started": cmp = new Date(a.run.runStartedAt ?? a.run.createdAt).getTime() - new Date(b.run.runStartedAt ?? b.run.createdAt).getTime(); break + } + return factor * cmp + }) +} + // ── Route component ─────────────────────────────────────────────────────────── function AllRuns() { @@ -101,7 +163,7 @@ function AllRuns() {
setFilter(e.target.value)} style={{ @@ -130,23 +192,47 @@ function AllRuns() { // ── Presentational table ─────────────────────────────────────────────────────── export function AllRunsTable({ runs }: { runs: RunWithRepo[] }) { + const [sortKey, setSortKey] = useState("started") + const [sortDir, setSortDir] = useState<"asc" | "desc">("desc") + + function toggleSort(key: SortKey) { + if (key === sortKey) { + setSortDir((d) => (d === "asc" ? "desc" : "asc")) + } else { + setSortKey(key) + setSortDir(DEFAULT_DIR[key]) + } + } + + const sorted = sortRuns(runs, sortKey, sortDir) + + const th = (key: SortKey, label: string) => ( + toggleSort(key)} + style={{ cursor: "pointer", userSelect: "none" }} + > + {label} + + ) + return (
- - - - - - - - + {th("repository", "Repository")} + {th("displayTitle", "Run")} + {th("workflowName", "Workflow")} + {th("headBranch", "Branch / Commit")} + {th("event", "Event")} + {th("actor", "Actor")} + {th("status", "Status")} + {th("duration", "Duration")} + {th("started", "Started")} - {runs.map(({ run, owner, repo }) => ( + {sorted.map(({ run, owner, repo }) => ( + - - - + {expanded.has(job.id) && ( diff --git a/packages/web/src/types/index.ts b/packages/web/src/types/index.ts index e8dbaf2..bc7c5cc 100644 --- a/packages/web/src/types/index.ts +++ b/packages/web/src/types/index.ts @@ -127,6 +127,15 @@ export interface RunArtifact { expired: boolean } +export interface SelfHostedRunner { + id: number + name: string + os: string + status: "online" | "offline" + busy: boolean + labels: string[] +} + // ── Scoring ─────────────────────────────────────────────────────────────────── export interface CheckResult { From 6da6271bbbeefe61a361d762e790f51000dfbc7f Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Thu, 4 Jun 2026 12:30:22 +0200 Subject: [PATCH 13/51] feat: dependabot config (#30) --- .github/dependabot.yml | 115 ++++++++++++++++++++++++++++++++ .github/dependabot.yml.disabled | 38 ----------- 2 files changed, 115 insertions(+), 38 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/dependabot.yml.disabled diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e934c39 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,115 @@ +version: 2 + +updates: + # ============================================================================ + # NPM Server + # ============================================================================ + - package-ecosystem: npm + directory: "/packages/server" + schedule: + interval: weekly + day: sunday + time: "01:00" + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 14 + semver-patch-days: 7 + open-pull-requests-limit: 2 + assignees: + - "manieperplex" + commit-message: + prefix: "chore(server):" + include: "scope" + groups: + version-all: + applies-to: version-updates + patterns: ["*"] + security-all: + applies-to: security-updates + patterns: ["*"] + rebase-strategy: "auto" + pull-request-branch-name: + separator: "/" + + # ============================================================================ + # NPM Web + # ============================================================================ + - package-ecosystem: npm + directory: "/packages/web" + schedule: + interval: weekly + day: sunday + time: "01:30" + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 14 + semver-patch-days: 7 + open-pull-requests-limit: 2 + assignees: + - "manieperplex" + commit-message: + prefix: "chore(web):" + include: "scope" + groups: + version-all: + applies-to: version-updates + patterns: ["*"] + security-all: + applies-to: security-updates + patterns: ["*"] + rebase-strategy: "auto" + pull-request-branch-name: + separator: "/" + + # ============================================================================ + # Docker + # ============================================================================ + - package-ecosystem: docker + directories: + - "/cerberus/tools" + registries: + - github-private-repos + schedule: + interval: weekly + day: sunday + time: "02:00" + open-pull-requests-limit: 1 + assignees: + - "manieperplex" + commit-message: + prefix: "chore(docker):" + # Keep version updates as one PR per image; only security updates are grouped. + groups: + security-all: + applies-to: security-updates + patterns: ["*"] + rebase-strategy: "auto" + pull-request-branch-name: + separator: "/" + + # ============================================================================ + # GitHub Actions - Workflow updates + # ============================================================================ + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + day: sunday + time: "02:30" + open-pull-requests-limit: 1 + assignees: + - "manieperplex" + commit-message: + prefix: "chore(gha):" + groups: + version-all: + applies-to: version-updates + patterns: ["*"] + security-all: + applies-to: security-updates + patterns: ["*"] + rebase-strategy: "auto" + pull-request-branch-name: + separator: "/" \ No newline at end of file diff --git a/.github/dependabot.yml.disabled b/.github/dependabot.yml.disabled deleted file mode 100644 index 615e310..0000000 --- a/.github/dependabot.yml.disabled +++ /dev/null @@ -1,38 +0,0 @@ -version: 2 - -updates: - # ── GitHub Actions ────────────────────────────────────────────────────────── - - package-ecosystem: "github-actions" - directory: "/" - target-branch: "develop" - schedule: - interval: "weekly" - day: "monday" - labels: - - "dependencies" - - "github-actions" - - # ── Docker images (server) ────────────────────────────────────────────────── - - package-ecosystem: "docker" - directory: "/packages/server" - target-branch: "develop" - schedule: - interval: "weekly" - day: "monday" - labels: - - "dependencies" - - "docker" - - # ── Docker images (web) ───────────────────────────────────────────────────── - - package-ecosystem: "docker" - directory: "/packages/web" - target-branch: "develop" - schedule: - interval: "weekly" - day: "monday" - labels: - - "dependencies" - - "docker" - - # npm dependencies are managed by Renovate (see renovate.json). - # Renovate supports pnpm catalog: protocol which Dependabot does not. From a7c6d414a0a47f63abc75ebe129fec1ca94987e7 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Thu, 4 Jun 2026 14:12:32 +0200 Subject: [PATCH 14/51] fix: remove registries from dependabot config, dockerfile directories --- .github/dependabot.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e934c39..f78142a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -68,9 +68,8 @@ updates: # ============================================================================ - package-ecosystem: docker directories: - - "/cerberus/tools" - registries: - - github-private-repos + - "/web/Dockerfile" + - "/server/Dockerfile" schedule: interval: weekly day: sunday From fb6526d8f56e9438c5b3fe77819b2f8fb24cdef2 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Thu, 4 Jun 2026 14:20:24 +0200 Subject: [PATCH 15/51] fix: dependebaot dockerfile path --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f78142a..b2f43c4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -68,8 +68,8 @@ updates: # ============================================================================ - package-ecosystem: docker directories: - - "/web/Dockerfile" - - "/server/Dockerfile" + - "packages/web/Dockerfile" + - "packages/server/Dockerfile" schedule: interval: weekly day: sunday From 5176170deb7dd70a764ba412ea4d40a609467251 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Thu, 4 Jun 2026 14:24:54 +0200 Subject: [PATCH 16/51] fix: dependebaot dockerfile only path --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b2f43c4..e6e6c67 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -68,8 +68,8 @@ updates: # ============================================================================ - package-ecosystem: docker directories: - - "packages/web/Dockerfile" - - "packages/server/Dockerfile" + - "/packages/web" + - "/packages/server" schedule: interval: weekly day: sunday From 60d3c23275d59effdb68d8ec3b9534ffc55a46b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:32:38 +0200 Subject: [PATCH 17/51] chore(gha): bump the version-all group across 1 directory with 6 updates (#31) Bumps the version-all group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4.3.1` | `6.0.3` | | [pnpm/action-setup](https://github.com/pnpm/action-setup) | `5.0.0` | `6.0.8` | | [actions/setup-node](https://github.com/actions/setup-node) | `4.4.0` | `6.4.0` | | [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `2.6.2` | `3.0.0` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.12.0` | `4.1.0` | | [docker/build-push-action](https://github.com/docker/build-push-action) | `6.19.2` | `7.2.0` | Updates `actions/checkout` from 4.3.1 to 6.0.3 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/34e114876b0b11c390a56381ad16ebd13914f8d5...df4cb1c069e1874edd31b4311f1884172cec0e10) Updates `pnpm/action-setup` from 5.0.0 to 6.0.8 - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/fc06bc1257f339d1d5d8b3a19a8cae5388b55320...0e279bb959325dab635dd2c09392533439d90093) Updates `actions/setup-node` from 4.4.0 to 6.4.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/49933ea5288caeca8642d1e84afbd3f7d6820020...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e) Updates `softprops/action-gh-release` from 2.6.2 to 3.0.0 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/3bb12739c298aeb8a4eeaf626c5b8d85266b0e65...b4309332981a82ec1c5618f44dd2e27cc8bfbfda) Updates `docker/setup-buildx-action` from 3.12.0 to 4.1.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/8d2750c68a42422c14e847fe6c8ac0403b4cbd6f...d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5) Updates `docker/build-push-action` from 6.19.2 to 7.2.0 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/10e90e3645eae34f1e60eeb005ba3a3d33f178e8...f9f3042f7e2789586610d6e8b85c8f03e5195baf) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: actions/setup-node dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: docker/build-push-action dependency-version: 7.2.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: docker/setup-buildx-action dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: pnpm/action-setup dependency-version: 6.0.8 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: softprops/action-gh-release dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly-deps.yml | 6 +++--- .github/workflows/release.yml | 14 +++++++------- .github/workflows/test-build.yml | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/nightly-deps.yml b/.github/workflows/nightly-deps.yml index 58314ff..2cced6b 100644 --- a/.github/workflows/nightly-deps.yml +++ b/.github/workflows/nightly-deps.yml @@ -18,13 +18,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ff7a88..a09cce3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,15 +31,15 @@ jobs: tag: ${{ steps.compute.outputs.tag }} skip: ${{ steps.compute.outputs.skip }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 # full history required by conventional-recommended-bump - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm @@ -81,15 +81,15 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm @@ -130,7 +130,7 @@ jobs: } >> "$GITHUB_OUTPUT" - name: Create GitHub Release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: tag_name: ${{ needs.version.outputs.tag }} name: ${{ needs.version.outputs.tag }} diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index a5e913a..1dbb9bd 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -23,13 +23,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm @@ -49,13 +49,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm @@ -76,13 +76,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 + - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 with: version: 10 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 cache: pnpm @@ -107,12 +107,12 @@ jobs: - image: web dockerfile: packages/web/Dockerfile steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Build ${{ matrix.image }} - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: . file: ${{ matrix.dockerfile }} From c8f1aac63fd51aa16178478fae585c57b216b4ff Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Thu, 4 Jun 2026 14:35:51 +0200 Subject: [PATCH 18/51] fix: dependabot grouping for dev dependencies --- .github/dependabot.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e6e6c67..a8e3640 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -22,6 +22,14 @@ updates: prefix: "chore(server):" include: "scope" groups: + tooling: + applies-to: version-updates + patterns: + - "eslint" + - "typescript*" + - "@typescript-eslint/*" + - "vitest" + - "@vitest/*" version-all: applies-to: version-updates patterns: ["*"] @@ -53,6 +61,14 @@ updates: prefix: "chore(web):" include: "scope" groups: + tooling: + applies-to: version-updates + patterns: + - "eslint" + - "typescript*" + - "@typescript-eslint/*" + - "vitest" + - "@vitest/*" version-all: applies-to: version-updates patterns: ["*"] From 79685a13ba048439e70bc2cb5b23f40d763acf88 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Thu, 4 Jun 2026 14:51:40 +0200 Subject: [PATCH 19/51] fix: dependabot root entry for resolve and update catalog from pnpm-workspace.yaml, reduce pr limits --- .github/dependabot.yml | 64 +++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a8e3640..66c698a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,24 +2,24 @@ version: 2 updates: # ============================================================================ - # NPM Server + # NPM Root — pnpm workspace catalog + root devDependencies # ============================================================================ - package-ecosystem: npm - directory: "/packages/server" + directory: "/" schedule: interval: weekly day: sunday - time: "01:00" + time: "00:30" cooldown: default-days: 7 semver-major-days: 30 semver-minor-days: 14 semver-patch-days: 7 - open-pull-requests-limit: 2 + open-pull-requests-limit: 1 assignees: - "manieperplex" commit-message: - prefix: "chore(server):" + prefix: "chore(deps):" include: "scope" groups: tooling: @@ -40,6 +40,43 @@ updates: pull-request-branch-name: separator: "/" + # ============================================================================ + # NPM Server + - package-ecosystem: npm + directory: "/packages/server" + schedule: + interval: weekly + day: sunday + time: "01:00" + cooldown: + default-days: 7 + semver-major-days: 30 + semver-minor-days: 14 + semver-patch-days: 7 + open-pull-requests-limit: 1 + assignees: + - "manieperplex" + commit-message: + prefix: "chore(server):" + include: "scope" + ignore: + # pnpm catalog-managed — updated via root entry to keep pnpm-workspace.yaml in sync + - dependency-name: "eslint" + - dependency-name: "typescript" + - dependency-name: "typescript-eslint" + - dependency-name: "vitest" + - dependency-name: "@vitest/coverage-v8" + groups: + version-all: + applies-to: version-updates + patterns: ["*"] + security-all: + applies-to: security-updates + patterns: ["*"] + rebase-strategy: "auto" + pull-request-branch-name: + separator: "/" + # ============================================================================ # NPM Web # ============================================================================ @@ -54,21 +91,20 @@ updates: semver-major-days: 30 semver-minor-days: 14 semver-patch-days: 7 - open-pull-requests-limit: 2 + open-pull-requests-limit: 1 assignees: - "manieperplex" commit-message: prefix: "chore(web):" include: "scope" + ignore: + # pnpm catalog-managed — updated via root entry to keep pnpm-workspace.yaml in sync + - dependency-name: "eslint" + - dependency-name: "typescript" + - dependency-name: "typescript-eslint" + - dependency-name: "vitest" + - dependency-name: "@vitest/coverage-v8" groups: - tooling: - applies-to: version-updates - patterns: - - "eslint" - - "typescript*" - - "@typescript-eslint/*" - - "vitest" - - "@vitest/*" version-all: applies-to: version-updates patterns: ["*"] From ee1004320fad653af33b02fe5d199603758c2721 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:14:45 +0200 Subject: [PATCH 20/51] chore(server):(deps): bump the version-all group across 1 directory with 7 updates (#32) * chore(server):(deps): bump the version-all group across 1 directory with 7 updates Bumps the version-all group with 7 updates in the /packages/server directory: | Package | From | To | | --- | --- | --- | | [@hono/node-server](https://github.com/honojs/node-server) | `1.19.14` | `2.0.1` | | [hono](https://github.com/honojs/hono) | `4.12.18` | `4.12.23` | | [jose](https://github.com/panva/jose) | `6.2.2` | `6.2.3` | | [lru-cache](https://github.com/isaacs/node-lru-cache) | `11.3.5` | `11.5.0` | | [undici](https://github.com/nodejs/undici) | `8.1.0` | `8.3.0` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.6.0` | `25.9.1` | | [tsx](https://github.com/privatenumber/tsx) | `4.21.0` | `4.22.3` | Updates `@hono/node-server` from 1.19.14 to 2.0.1 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v1.19.14...v2.0.1) Updates `hono` from 4.12.18 to 4.12.23 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.18...v4.12.23) Updates `jose` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/panva/jose/releases) - [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md) - [Commits](https://github.com/panva/jose/compare/v6.2.2...v6.2.3) Updates `lru-cache` from 11.3.5 to 11.5.0 - [Changelog](https://github.com/isaacs/node-lru-cache/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-lru-cache/compare/v11.3.5...v11.5.0) Updates `undici` from 8.1.0 to 8.3.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.1.0...v8.3.0) Updates `@types/node` from 25.6.0 to 25.9.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `tsx` from 4.21.0 to 4.22.3 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.3) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: "@types/node" dependency-version: 25.9.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: hono dependency-version: 4.12.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: jose dependency-version: 6.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: lru-cache dependency-version: 11.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: tsx dependency-version: 4.22.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: undici dependency-version: 8.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(server): update pnpm.lock, add peer dep rules --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- package.json | 7 + packages/server/package.json | 14 +- pnpm-lock.yaml | 361 +++++++++++++++++------------------ 3 files changed, 188 insertions(+), 194 deletions(-) diff --git a/package.json b/package.json index b733cb9..3ddce95 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,13 @@ "packages/server/src/**/*.ts": "pnpm --filter @dashlight/server exec eslint --fix", "packages/web/src/**/*.{ts,tsx}": "pnpm --filter @dashlight/web exec eslint --fix" }, + "pnpm": { + "peerDependencyRules": { + "allowedVersions": { + "eslint-plugin-react-hooks>eslint": ">=10" + } + } + }, "devDependencies": { "conventional-changelog-conventionalcommits": "^9.3.1", "conventional-recommended-bump": "^11.2.0", diff --git a/packages/server/package.json b/packages/server/package.json index bf47a0d..59b3c05 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -15,19 +15,19 @@ "clean": "rm -rf dist" }, "dependencies": { - "@hono/node-server": "^1.19.14", - "hono": "^4.12.18", - "jose": "^6.2.2", + "@hono/node-server": "^2.0.1", + "hono": "^4.12.23", + "jose": "^6.2.3", "js-yaml": "^4.1.1", - "lru-cache": "^11.3.5", - "undici": "^8.1.0" + "lru-cache": "^11.5.0", + "undici": "^8.3.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@types/node": "^25.6.0", + "@types/node": "^25.9.1", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", - "tsx": "^4.21.0", + "tsx": "^4.22.3", "typescript": "catalog:", "typescript-eslint": "catalog:", "vitest": "catalog:" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 662328a..c96009a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,35 +43,35 @@ importers: version: 6.0.2 vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) packages/server: dependencies: '@hono/node-server': - specifier: ^1.19.14 - version: 1.19.14(hono@4.12.18) + specifier: ^2.0.1 + version: 2.0.4(hono@4.12.23) hono: - specifier: ^4.12.18 - version: 4.12.18 + specifier: ^4.12.23 + version: 4.12.23 jose: - specifier: ^6.2.2 - version: 6.2.2 + specifier: ^6.2.3 + version: 6.2.3 js-yaml: specifier: ^4.1.1 version: 4.1.1 lru-cache: - specifier: ^11.3.5 - version: 11.3.5 + specifier: ^11.5.0 + version: 11.5.1 undici: - specifier: ^8.1.0 - version: 8.1.0 + specifier: ^8.3.0 + version: 8.3.0 devDependencies: '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 '@types/node': - specifier: ^25.6.0 - version: 25.6.0 + specifier: ^25.9.1 + version: 25.9.1 '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.4(vitest@4.1.4) @@ -79,8 +79,8 @@ importers: specifier: 'catalog:' version: 10.2.0 tsx: - specifier: ^4.21.0 - version: 4.21.0 + specifier: ^4.22.3 + version: 4.22.4 typescript: specifier: 'catalog:' version: 6.0.2 @@ -89,7 +89,7 @@ importers: version: 8.58.2(eslint@10.2.0)(typescript@6.0.2) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) packages/web: dependencies: @@ -132,7 +132,7 @@ importers: version: 1.166.13(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.15)(csstype@3.2.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@tanstack/router-vite-plugin': specifier: ^1.166.37 - version: 1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + version: 1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -147,7 +147,7 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.4(vitest@4.1.4) @@ -168,10 +168,10 @@ importers: version: 8.58.2(eslint@10.2.0)(typescript@6.0.2) vite: specifier: ^8.0.8 - version: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) packages: @@ -352,158 +352,158 @@ packages: '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -547,9 +547,9 @@ packages: '@noble/hashes': optional: true - '@hono/node-server@1.19.14': - resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} - engines: {node: '>=18.14.1'} + '@hono/node-server@2.0.4': + resolution: {integrity: sha512-Ut3y0dMMPWy6bZ2kVfx25EOVbZlm15dhF4mOsezMlhpNHy+4MkU1qN9Y6lnruYi4wPmFzimGX2X7LF/FwHli4A==} + engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -912,8 +912,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.6.0': - resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + '@types/node@25.9.1': + resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -1346,8 +1346,8 @@ packages: es-toolkit@1.45.1: resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} - esbuild@0.27.7: - resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} engines: {node: '>=18'} hasBin: true @@ -1467,9 +1467,6 @@ packages: resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} engines: {node: '>=18'} - get-tsconfig@4.14.0: - resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1493,8 +1490,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.18: - resolution: {integrity: sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==} + hono@4.12.23: + resolution: {integrity: sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -1584,8 +1581,8 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - jose@6.2.2: - resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -1723,8 +1720,8 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} - lru-cache@11.3.5: - resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -1904,9 +1901,6 @@ packages: reselect@5.1.1: resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -2051,8 +2045,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + tsx@4.22.4: + resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} engines: {node: '>=18.0.0'} hasBin: true @@ -2072,15 +2066,15 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@7.19.2: - resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} undici@7.25.0: resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} engines: {node: '>=20.18.1'} - undici@8.1.0: - resolution: {integrity: sha512-E9MkTS4xXLnRPYqxH2e6Hr2/49e7WFDKczKcCaFH4VaZs2iNvHMqeIkyUAD9vM8kujy9TjVrRlQ5KkdEJxB2pw==} + undici@8.3.0: + resolution: {integrity: sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==} engines: {node: '>=22.19.0'} unplugin@2.3.11: @@ -2470,82 +2464,82 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.27.7': + '@esbuild/aix-ppc64@0.28.0': optional: true - '@esbuild/android-arm64@0.27.7': + '@esbuild/android-arm64@0.28.0': optional: true - '@esbuild/android-arm@0.27.7': + '@esbuild/android-arm@0.28.0': optional: true - '@esbuild/android-x64@0.27.7': + '@esbuild/android-x64@0.28.0': optional: true - '@esbuild/darwin-arm64@0.27.7': + '@esbuild/darwin-arm64@0.28.0': optional: true - '@esbuild/darwin-x64@0.27.7': + '@esbuild/darwin-x64@0.28.0': optional: true - '@esbuild/freebsd-arm64@0.27.7': + '@esbuild/freebsd-arm64@0.28.0': optional: true - '@esbuild/freebsd-x64@0.27.7': + '@esbuild/freebsd-x64@0.28.0': optional: true - '@esbuild/linux-arm64@0.27.7': + '@esbuild/linux-arm64@0.28.0': optional: true - '@esbuild/linux-arm@0.27.7': + '@esbuild/linux-arm@0.28.0': optional: true - '@esbuild/linux-ia32@0.27.7': + '@esbuild/linux-ia32@0.28.0': optional: true - '@esbuild/linux-loong64@0.27.7': + '@esbuild/linux-loong64@0.28.0': optional: true - '@esbuild/linux-mips64el@0.27.7': + '@esbuild/linux-mips64el@0.28.0': optional: true - '@esbuild/linux-ppc64@0.27.7': + '@esbuild/linux-ppc64@0.28.0': optional: true - '@esbuild/linux-riscv64@0.27.7': + '@esbuild/linux-riscv64@0.28.0': optional: true - '@esbuild/linux-s390x@0.27.7': + '@esbuild/linux-s390x@0.28.0': optional: true - '@esbuild/linux-x64@0.27.7': + '@esbuild/linux-x64@0.28.0': optional: true - '@esbuild/netbsd-arm64@0.27.7': + '@esbuild/netbsd-arm64@0.28.0': optional: true - '@esbuild/netbsd-x64@0.27.7': + '@esbuild/netbsd-x64@0.28.0': optional: true - '@esbuild/openbsd-arm64@0.27.7': + '@esbuild/openbsd-arm64@0.28.0': optional: true - '@esbuild/openbsd-x64@0.27.7': + '@esbuild/openbsd-x64@0.28.0': optional: true - '@esbuild/openharmony-arm64@0.27.7': + '@esbuild/openharmony-arm64@0.28.0': optional: true - '@esbuild/sunos-x64@0.27.7': + '@esbuild/sunos-x64@0.28.0': optional: true - '@esbuild/win32-arm64@0.27.7': + '@esbuild/win32-arm64@0.28.0': optional: true - '@esbuild/win32-ia32@0.27.7': + '@esbuild/win32-ia32@0.28.0': optional: true - '@esbuild/win32-x64@0.27.7': + '@esbuild/win32-x64@0.28.0': optional: true '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)': @@ -2580,9 +2574,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@1.19.14(hono@4.12.18)': + '@hono/node-server@2.0.4(hono@4.12.23)': dependencies: - hono: 4.12.18 + hono: 4.12.23 '@humanfs/core@0.19.1': {} @@ -2772,12 +2766,12 @@ snapshots: '@tanstack/virtual-file-routes': 1.161.7 magic-string: 0.30.21 prettier: 3.8.3 - tsx: 4.21.0 + tsx: 4.22.4 zod: 3.25.76 transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))': + '@tanstack/router-plugin@1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -2794,7 +2788,7 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -2812,9 +2806,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))': + '@tanstack/router-vite-plugin@1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: - '@tanstack/router-plugin': 1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + '@tanstack/router-plugin': 1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -2918,9 +2912,9 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.6.0': + '@types/node@25.9.1': dependencies: - undici-types: 7.19.2 + undici-types: 7.24.6 '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: @@ -3023,10 +3017,10 @@ snapshots: '@typescript-eslint/types': 8.58.2 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.1(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) '@vitest/coverage-v8@4.1.4(vitest@4.1.4)': dependencies: @@ -3040,7 +3034,7 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/expect@4.1.4': dependencies: @@ -3051,13 +3045,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) '@vitest/pretty-format@4.1.4': dependencies: @@ -3376,34 +3370,34 @@ snapshots: es-toolkit@1.45.1: {} - esbuild@0.27.7: + esbuild@0.28.0: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.7 - '@esbuild/android-arm': 0.27.7 - '@esbuild/android-arm64': 0.27.7 - '@esbuild/android-x64': 0.27.7 - '@esbuild/darwin-arm64': 0.27.7 - '@esbuild/darwin-x64': 0.27.7 - '@esbuild/freebsd-arm64': 0.27.7 - '@esbuild/freebsd-x64': 0.27.7 - '@esbuild/linux-arm': 0.27.7 - '@esbuild/linux-arm64': 0.27.7 - '@esbuild/linux-ia32': 0.27.7 - '@esbuild/linux-loong64': 0.27.7 - '@esbuild/linux-mips64el': 0.27.7 - '@esbuild/linux-ppc64': 0.27.7 - '@esbuild/linux-riscv64': 0.27.7 - '@esbuild/linux-s390x': 0.27.7 - '@esbuild/linux-x64': 0.27.7 - '@esbuild/netbsd-arm64': 0.27.7 - '@esbuild/netbsd-x64': 0.27.7 - '@esbuild/openbsd-arm64': 0.27.7 - '@esbuild/openbsd-x64': 0.27.7 - '@esbuild/openharmony-arm64': 0.27.7 - '@esbuild/sunos-x64': 0.27.7 - '@esbuild/win32-arm64': 0.27.7 - '@esbuild/win32-ia32': 0.27.7 - '@esbuild/win32-x64': 0.27.7 + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 escalade@3.2.0: {} @@ -3529,10 +3523,6 @@ snapshots: get-east-asian-width@1.5.0: {} - get-tsconfig@4.14.0: - dependencies: - resolve-pkg-maps: 1.0.0 - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -3553,7 +3543,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.18: {} + hono@4.12.23: {} html-encoding-sniffer@6.0.0: dependencies: @@ -3618,7 +3608,7 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jose@6.2.2: {} + jose@6.2.3: {} js-tokens@10.0.0: {} @@ -3640,7 +3630,7 @@ snapshots: decimal.js: 10.6.0 html-encoding-sniffer: 6.0.0 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.3.5 + lru-cache: 11.5.1 parse5: 8.0.0 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -3752,7 +3742,7 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 9.0.2 - lru-cache@11.3.5: {} + lru-cache@11.5.1: {} lru-cache@5.1.1: dependencies: @@ -3912,8 +3902,6 @@ snapshots: reselect@5.1.1: {} - resolve-pkg-maps@1.0.0: {} - restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -4049,10 +4037,9 @@ snapshots: tslib@2.8.1: optional: true - tsx@4.21.0: + tsx@4.22.4: dependencies: - esbuild: 0.27.7 - get-tsconfig: 4.14.0 + esbuild: 0.28.0 optionalDependencies: fsevents: 2.3.3 @@ -4073,11 +4060,11 @@ snapshots: typescript@6.0.2: {} - undici-types@7.19.2: {} + undici-types@7.24.6: {} undici@7.25.0: {} - undici@8.1.0: {} + undici@8.3.0: {} unplugin@2.3.11: dependencies: @@ -4117,7 +4104,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -4125,16 +4112,16 @@ snapshots: rolldown: 1.0.0-rc.15 tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 25.6.0 - esbuild: 0.27.7 + '@types/node': 25.9.1 + esbuild: 0.28.0 fsevents: 2.3.3 - tsx: 4.21.0 + tsx: 4.22.4 yaml: 2.8.3 - vitest@4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.4 '@vitest/runner': 4.1.4 '@vitest/snapshot': 4.1.4 @@ -4151,10 +4138,10 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.9.1 '@vitest/coverage-v8': 4.1.4(vitest@4.1.4) jsdom: 29.0.2 transitivePeerDependencies: From 928eb33cf14d10e9e8548217bb764bf342ac0237 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:26:17 +0200 Subject: [PATCH 21/51] chore(web):(deps): bump the version-all group across 1 directory with 16 updates (#33) * chore(web):(deps): bump the version-all group across 1 directory with 16 updates Bumps the version-all group with 16 updates in the /packages/web directory: | Package | From | To | | --- | --- | --- | | [@tanstack/query-async-storage-persister](https://github.com/TanStack/query/tree/HEAD/packages/query-async-storage-persister) | `5.99.0` | `5.100.11` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.99.0` | `5.100.11` | | [@tanstack/react-query-persist-client](https://github.com/TanStack/query/tree/HEAD/packages/react-query-persist-client) | `5.99.0` | `5.100.11` | | [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router) | `1.168.22` | `1.170.6` | | [@dagrejs/dagre](https://github.com/dagrejs/dagre) | `1.1.8` | `3.0.0` | | [idb-keyval](https://github.com/jakearchibald/idb-keyval) | `6.2.2` | `6.2.4` | | [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.2.5` | `19.2.6` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.14` | `19.2.15` | | [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.2.5` | `19.2.6` | | [zod](https://github.com/colinhacks/zod) | `4.3.6` | `4.4.3` | | [@tanstack/react-router-devtools](https://github.com/TanStack/router/tree/HEAD/packages/react-router-devtools) | `1.166.13` | `1.167.0` | | [@tanstack/router-vite-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-vite-plugin) | `1.166.37` | `1.167.9` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.1` | `6.0.2` | | [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) | `7.0.1` | `7.1.1` | | [jsdom](https://github.com/jsdom/jsdom) | `29.0.2` | `29.1.1` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.0.8` | `8.0.14` | Updates `@tanstack/query-async-storage-persister` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/query-async-storage-persister/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/query-async-storage-persister@5.100.11/packages/query-async-storage-persister) Updates `@tanstack/react-query` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.100.11/packages/react-query) Updates `@tanstack/react-query-persist-client` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-persist-client/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-persist-client@5.100.11/packages/react-query-persist-client) Updates `@tanstack/react-router` from 1.168.22 to 1.170.6 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.6/packages/react-router) Updates `@dagrejs/dagre` from 1.1.8 to 3.0.0 - [Release notes](https://github.com/dagrejs/dagre/releases) - [Changelog](https://github.com/dagrejs/dagre/blob/master/changelog.md) - [Commits](https://github.com/dagrejs/dagre/compare/v1.1.8...v3.0.0) Updates `idb-keyval` from 6.2.2 to 6.2.4 - [Changelog](https://github.com/jakearchibald/idb-keyval/blob/main/CHANGELOG.md) - [Commits](https://github.com/jakearchibald/idb-keyval/compare/v6.2.2...v6.2.4) Updates `react` from 19.2.5 to 19.2.6 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react) Updates `@types/react` from 19.2.14 to 19.2.15 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `react-dom` from 19.2.5 to 19.2.6 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react-dom) Updates `zod` from 4.3.6 to 4.4.3 - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v4.3.6...v4.4.3) Updates `@tanstack/react-router-devtools` from 1.166.13 to 1.167.0 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router-devtools/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router-devtools@1.167.0/packages/react-router-devtools) Updates `@tanstack/router-vite-plugin` from 1.166.37 to 1.167.9 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/router-vite-plugin/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/router-vite-plugin@1.167.9/packages/router-vite-plugin) Updates `@vitejs/plugin-react` from 6.0.1 to 6.0.2 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.2/packages/plugin-react) Updates `eslint-plugin-react-hooks` from 7.0.1 to 7.1.1 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/eslint-plugin-react-hooks@7.1.1/packages/eslint-plugin-react-hooks) Updates `jsdom` from 29.0.2 to 29.1.1 - [Release notes](https://github.com/jsdom/jsdom/releases) - [Commits](https://github.com/jsdom/jsdom/compare/v29.0.2...v29.1.1) Updates `vite` from 8.0.8 to 8.0.14 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.0.14/packages/vite) --- updated-dependencies: - dependency-name: "@dagrejs/dagre" dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: "@tanstack/query-async-storage-persister" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-query" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-query-persist-client" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-router" dependency-version: 1.170.6 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-router-devtools" dependency-version: 1.167.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/router-vite-plugin" dependency-version: 1.167.9 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@types/react" dependency-version: 19.2.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: eslint-plugin-react-hooks dependency-version: 7.1.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: idb-keyval dependency-version: 6.2.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: jsdom dependency-version: 29.1.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: react dependency-version: 19.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: react-dom dependency-version: 19.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: vite dependency-version: 8.0.14 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: zod dependency-version: 4.4.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(web): pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- packages/web/package.json | 32 +- pnpm-lock.yaml | 848 +++++++++++++++++--------------------- 2 files changed, 400 insertions(+), 480 deletions(-) diff --git a/packages/web/package.json b/packages/web/package.json index 900fa7d..2c5e9bc 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -14,33 +14,33 @@ "clean": "rm -rf dist" }, "dependencies": { - "@tanstack/query-async-storage-persister": "^5.99.0", - "@tanstack/react-query": "^5.99.0", - "@tanstack/react-query-persist-client": "^5.99.0", - "@tanstack/react-router": "^1.168.22", + "@tanstack/query-async-storage-persister": "^5.100.11", + "@tanstack/react-query": "^5.100.11", + "@tanstack/react-query-persist-client": "^5.100.11", + "@tanstack/react-router": "^1.170.6", "@xyflow/react": "^12.10.2", - "@dagrejs/dagre": "^1.1.4", - "idb-keyval": "^6.2.2", - "react": "^19.2.5", - "react-dom": "^19.2.5", + "@dagrejs/dagre": "^3.0.0", + "idb-keyval": "^6.2.4", + "react": "^19.2.6", + "react-dom": "^19.2.6", "recharts": "^3.8.1", - "zod": "^4.3.6" + "zod": "^4.4.3" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.13", - "@tanstack/router-vite-plugin": "^1.166.37", + "@tanstack/react-router-devtools": "^1.167.0", + "@tanstack/router-vite-plugin": "^1.167.9", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", - "@types/react": "^19.2.14", + "@types/react": "^19.2.15", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", + "@vitejs/plugin-react": "^6.0.2", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "^7.0.1", - "jsdom": "^29.0.2", + "eslint-plugin-react-hooks": "^7.1.1", + "jsdom": "^29.1.1", "typescript": "catalog:", "typescript-eslint": "catalog:", - "vite": "^8.0.8", + "vite": "^8.0.14", "vitest": "catalog:" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c96009a..dcf77e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: version: 6.0.2 vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages/server: dependencies: @@ -77,7 +77,7 @@ importers: version: 4.1.4(vitest@4.1.4) eslint: specifier: 'catalog:' - version: 10.2.0 + version: 10.2.0(jiti@2.7.0) tsx: specifier: ^4.22.3 version: 4.22.4 @@ -86,92 +86,92 @@ importers: version: 6.0.2 typescript-eslint: specifier: 'catalog:' - version: 8.58.2(eslint@10.2.0)(typescript@6.0.2) + version: 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages/web: dependencies: '@dagrejs/dagre': - specifier: ^1.1.4 - version: 1.1.8 + specifier: ^3.0.0 + version: 3.0.0 '@tanstack/query-async-storage-persister': - specifier: ^5.99.0 - version: 5.99.0 + specifier: ^5.100.11 + version: 5.101.0 '@tanstack/react-query': - specifier: ^5.99.0 - version: 5.99.0(react@19.2.5) + specifier: ^5.100.11 + version: 5.101.0(react@19.2.7) '@tanstack/react-query-persist-client': - specifier: ^5.99.0 - version: 5.99.0(@tanstack/react-query@5.99.0(react@19.2.5))(react@19.2.5) + specifier: ^5.100.11 + version: 5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7) '@tanstack/react-router': - specifier: ^1.168.22 - version: 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: ^1.170.6 + version: 1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@xyflow/react': specifier: ^12.10.2 - version: 12.10.2(@types/react@19.2.14)(immer@11.1.4)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 12.10.2(@types/react@19.2.16)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) idb-keyval: - specifier: ^6.2.2 - version: 6.2.2 + specifier: ^6.2.4 + version: 6.2.5 react: - specifier: ^19.2.5 - version: 19.2.5 + specifier: ^19.2.6 + version: 19.2.7 react-dom: - specifier: ^19.2.5 - version: 19.2.5(react@19.2.5) + specifier: ^19.2.6 + version: 19.2.7(react@19.2.7) recharts: specifier: ^3.8.1 - version: 3.8.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react-is@18.3.1)(react@19.2.5)(redux@5.0.1) + version: 3.8.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1) zod: - specifier: ^4.3.6 - version: 4.3.6 + specifier: ^4.4.3 + version: 4.4.3 devDependencies: '@tanstack/react-router-devtools': - specifier: ^1.166.13 - version: 1.166.13(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.15)(csstype@3.2.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: ^1.167.0 + version: 1.167.0(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.9)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/router-vite-plugin': - specifier: ^1.166.37 - version: 1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + specifier: ^1.167.9 + version: 1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/react': - specifier: ^19.2.14 - version: 19.2.14 + specifier: ^19.2.15 + version: 19.2.16 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.14) + version: 19.2.3(@types/react@19.2.16) '@vitejs/plugin-react': - specifier: ^6.0.1 - version: 6.0.1(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + specifier: ^6.0.2 + version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.4(vitest@4.1.4) eslint: specifier: 'catalog:' - version: 10.2.0 + version: 10.2.0(jiti@2.7.0) eslint-plugin-react-hooks: - specifier: ^7.0.1 - version: 7.0.1(eslint@10.2.0) + specifier: ^7.1.1 + version: 7.1.1(eslint@10.2.0(jiti@2.7.0)) jsdom: - specifier: ^29.0.2 - version: 29.0.2 + specifier: ^29.1.1 + version: 29.1.1 typescript: specifier: 'catalog:' version: 6.0.2 typescript-eslint: specifier: 'catalog:' - version: 8.58.2(eslint@10.2.0)(typescript@6.0.2) + version: 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) vite: - specifier: ^8.0.8 - version: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) + specifier: ^8.0.14 + version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages: @@ -182,8 +182,8 @@ packages: resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@asamuzakjp/dom-selector@7.0.10': - resolution: {integrity: sha512-KyOb19eytNSELkmdqzZZUXWCU25byIlOld5qVFg0RYdS0T3tt7jeDByxk9hIAC73frclD8GKrHttr0SUjKCCdQ==} + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} '@asamuzakjp/generational-cache@1.0.1': @@ -336,18 +336,17 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} - '@dagrejs/dagre@1.1.8': - resolution: {integrity: sha512-5SEDlndt4W/LaVzPYJW+bSmSEZc9EzTf8rJ20WCKvjS5EAZAN0b+x0Yww7VMT4R3Wootkg+X9bUfUxazYw6Blw==} + '@dagrejs/dagre@3.0.0': + resolution: {integrity: sha512-ZzhnTy1rfuoew9Ez3EIw4L2znPGnYYhfn8vc9c4oB8iw6QAsszbiU0vRhlxWPFnmmNSFAkrYeF1PhM5m4lAN0Q==} - '@dagrejs/graphlib@2.2.4': - resolution: {integrity: sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==} - engines: {node: '>17.0.0'} + '@dagrejs/graphlib@4.0.1': + resolution: {integrity: sha512-IvcV6FduIIAmLwnH+yun+QtV36SC7mERqa86aClNqmMN09WhmPPYU8ckHrZBozErf+UvHPWOTJYaGYiIcs0DgA==} - '@emnapi/core@1.9.2': - resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -591,8 +590,8 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@oxc-project/types@0.124.0': - resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} '@reduxjs/toolkit@2.11.2': resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} @@ -605,106 +604,103 @@ packages: react-redux: optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.15': - resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': - resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': - resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': - resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': - resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': - resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': - resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': - resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} - engines: {node: '>=14.0.0'} + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': - resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': - resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.15': - resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} - - '@rolldown/pluginutils@1.0.0-rc.7': - resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} '@simple-libs/child-process-utils@1.0.2': resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==} @@ -720,44 +716,44 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@tanstack/history@1.161.6': - resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==} + '@tanstack/history@1.162.0': + resolution: {integrity: sha512-79pf/RkhteYZTRgcR4F9kbk84P2N8rugQJswxfIqovlbRiT3yI7eBE+5QorIrZaOKktsgzRlXh1l/du/xpl4iA==} engines: {node: '>=20.19'} - '@tanstack/query-async-storage-persister@5.99.0': - resolution: {integrity: sha512-RUG++yZf8RoRK1Yz83WHHYJ6EF8DqKIF/UNNUUDEw/cY9SLKhAeEd4a0+kDzNRdb4RGXXeF5UIuzoEFJ7elLwQ==} + '@tanstack/query-async-storage-persister@5.101.0': + resolution: {integrity: sha512-8Y8pwMVPh4kqU9m+MhbDYBuub+i5T2M9P/0+Ae3KccX1BwMIp6AdFAx3zDgLoZcEVI830mbJYf0sjAgsawCWVw==} - '@tanstack/query-core@5.99.0': - resolution: {integrity: sha512-3Jv3WQG0BCcH7G+7lf/bP8QyBfJOXeY+T08Rin3GZ1bshvwlbPt7NrDHMEzGdKIOmOzvIQmxjk28YEQX60k7pQ==} + '@tanstack/query-core@5.101.0': + resolution: {integrity: sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==} - '@tanstack/query-persist-client-core@5.99.0': - resolution: {integrity: sha512-FzXoxqGYa+ozGNGBIPHJT06rJD4geiHGbVXNS8K7cwN34te64LXlO5Ep+roQYvZjXJFNrLa4W48DIYITpMxzuA==} + '@tanstack/query-persist-client-core@5.101.0': + resolution: {integrity: sha512-LH99WepGVLwlLfuOcQcPK7f3Xg/Gf+xlMMIj9xWu/8oQ3egnDzjr+a4HvEmi6PGob5SmGXvmDKZaH5+In9dzjw==} - '@tanstack/react-query-persist-client@5.99.0': - resolution: {integrity: sha512-A3TTaaYZOy6dFUNJj3r10rwmUBWaXqc2N71a7jzpFXilYAYWLKJf9ivT5n5bhXsJnSkdvv1RLifUg/GdvDGaDw==} + '@tanstack/react-query-persist-client@5.101.0': + resolution: {integrity: sha512-AUcdBgz8V6sM9axzdqkVmWjYSOETkhr6yAZSBnEFyZT2jo6vkFq3UrpRuxGs6fmhKMWv8FA+ZJGcbaKPaoAElQ==} peerDependencies: - '@tanstack/react-query': ^5.99.0 + '@tanstack/react-query': ^5.101.0 react: ^18 || ^19 - '@tanstack/react-query@5.99.0': - resolution: {integrity: sha512-OY2bCqPemT1LlqJ8Y2CUau4KELnIhhG9Ol3ZndPbdnB095pRbPo1cHuXTndg8iIwtoHTgwZjyaDnQ0xD0mYwAw==} + '@tanstack/react-query@5.101.0': + resolution: {integrity: sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==} peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.166.13': - resolution: {integrity: sha512-6yKRFFJrEEOiGp5RAAuGCYsl81M4XAhJmLcu9PKj+HZle4A3dsP60lwHoqQYWHMK9nKKFkdXR+D8qxzxqtQbEA==} + '@tanstack/react-router-devtools@1.167.0': + resolution: {integrity: sha512-nGw095EG7IHx0h5NtlEmzf6vcCTaFNPWdTSuDKazajhN0ct/v/TkekJ9J6KYUCeV1a8/2ZmToc58M+0rrOyn7w==} engines: {node: '>=20.19'} peerDependencies: - '@tanstack/react-router': ^1.168.15 - '@tanstack/router-core': ^1.168.11 + '@tanstack/react-router': ^1.170.0 + '@tanstack/router-core': ^1.170.0 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.168.22': - resolution: {integrity: sha512-W2LyfkfJtDCf//jOjZeUBWwOVl8iDRVTECpGHa2M28MT3T5/VVnjgicYNHR/ax0Filk1iU67MRjcjHheTYvK1Q==} + '@tanstack/react-router@1.170.11': + resolution: {integrity: sha512-gP2vzdyaI8Ow/Uz/MRPfK2wN09YwRI0Y/oF74Wuy9R3KmjbfJv2tLrkM+Onu1xWklSn3ugZarMPJXRE0kzrJTA==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -769,32 +765,30 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.168.15': - resolution: {integrity: sha512-Wr0424NDtD8fT/uALobMZ9DdcfsTyXtW5IPR++7zvW8/7RaIOeaqXpVDId8ywaGtqPWLWOfaUg2zUtYtukoXYA==} + '@tanstack/router-core@1.171.9': + resolution: {integrity: sha512-QM5ZwLT9c5ZcTJW0QQZRRIBC4qjImUyUCXCVyuYVOF9xr76XLsJSX4F2dOxr9VptAv+W+TkWNOYdX8VaO9kdgA==} engines: {node: '>=20.19'} - hasBin: true - '@tanstack/router-devtools-core@1.167.3': - resolution: {integrity: sha512-fJ1VMhyQgnoashTrP763c2HRc9kofgF61L7Jb3F6eTHAmCKtGVx8BRtiFt37sr3U0P0jmaaiiSPGP6nT5JtVNg==} + '@tanstack/router-devtools-core@1.168.0': + resolution: {integrity: sha512-wQoQhlBK7nlZgqzaqdYXKWNTpdHdsaREdaPhFZVH0/Ador+F+eM3/NF2i3f2LPeS0GgKraZUQXe1Q/1+KHyEYg==} engines: {node: '>=20.19'} peerDependencies: - '@tanstack/router-core': ^1.168.11 + '@tanstack/router-core': ^1.170.0 csstype: ^3.0.10 peerDependenciesMeta: csstype: optional: true - '@tanstack/router-generator@1.166.32': - resolution: {integrity: sha512-VuusKwEXcgKq+myq1JQfZogY8scTXIIeFls50dJ/UXgCXWp5n14iFreYNlg41wURcak2oA3M+t2TVfD0xUUD6g==} + '@tanstack/router-generator@1.167.13': + resolution: {integrity: sha512-DldbCjA8S/CXQBuoyQqr76xqZe9k+H1ymV+ugj2IBHFi4yRzx4z4f2nSsPYlLdpXD2Cf/MEjLncaG7ceY5H5ig==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.167.22': - resolution: {integrity: sha512-wYPzIvBK8bcmXVUpZfSgGBXOrfBAdF4odKevz6rejio5rEd947NtKDF5R7eYdwlAOmRqYpLJnJ1QHkc5t8bY4w==} + '@tanstack/router-plugin@1.168.14': + resolution: {integrity: sha512-z+3vYJ7ouNnMzBIC1hsNWsxaQFu9Gf0WSdE3jBHWa326ipnONqDD5KeCqWGczq0HMdZY4UsDjyfvjucxXhrb0A==} engines: {node: '>=20.19'} - hasBin: true peerDependencies: - '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.168.21 + '@rsbuild/core': '>=1.0.2 || ^2.0.0' + '@tanstack/react-router': ^1.170.11 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' @@ -810,21 +804,20 @@ packages: webpack: optional: true - '@tanstack/router-utils@1.161.6': - resolution: {integrity: sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw==} + '@tanstack/router-utils@1.162.1': + resolution: {integrity: sha512-62layyTGmclHDQS/eidwKRfN1hhCKwViG7iEBcVmL0MXgcAB3OOucWCEcDDGd9Cu11H6b4QQ5oOo47MWIqwz0A==} engines: {node: '>=20.19'} - '@tanstack/router-vite-plugin@1.166.37': - resolution: {integrity: sha512-D32YhrfB1262QxzRrKMvbF/786AHLu4KIfAZ1UIEwbBUAFnpd/l8vQ4em7HE1G9e7+95zSlq99DyLvAfDxErGw==} + '@tanstack/router-vite-plugin@1.167.14': + resolution: {integrity: sha512-B3/SPQ3hh61/QdrI39EZDZ1JDoeHvj+eDT7KOg9cPn3poXSgPiO4VmM/J0eD96vLFchZBS+fhnFvb8jtxrxtIw==} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} - '@tanstack/virtual-file-routes@1.161.7': - resolution: {integrity: sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ==} + '@tanstack/virtual-file-routes@1.162.0': + resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} engines: {node: '>=20.19'} - hasBin: true '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} @@ -920,8 +913,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/react@19.2.16': + resolution: {integrity: sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==} '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} @@ -985,8 +978,8 @@ packages: resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@6.0.1': - resolution: {integrity: sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==} + '@vitejs/plugin-react@6.0.2': + resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 @@ -1082,10 +1075,6 @@ packages: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1121,18 +1110,10 @@ packages: bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - brace-expansion@5.0.5: resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} engines: {node: 18 || 20 || >=22} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - browserslist@4.28.2: resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1145,9 +1126,9 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} classcat@5.0.5: resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} @@ -1332,9 +1313,9 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} @@ -1359,11 +1340,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-plugin-react-hooks@7.0.1: - resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} engines: {node: '>=18'} peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + 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-scope@9.1.2: resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} @@ -1439,10 +1420,6 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1467,10 +1444,6 @@ packages: resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} engines: {node: '>=18'} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -1506,8 +1479,8 @@ packages: engines: {node: '>=18'} hasBin: true - idb-keyval@6.2.2: - resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} + idb-keyval@6.2.5: + resolution: {integrity: sha512-eKQkTnS0relYsSOYomx8ozIbmdsQCKUdhyuIaQ2DZgKuaxtyQQMkyD/wlnQN32pO3yutN1b1L8uqwcDKaJd7/Q==} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} @@ -1535,10 +1508,6 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1551,10 +1520,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - is-obj@2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} @@ -1581,6 +1546,10 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + jose@6.2.3: resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} @@ -1594,8 +1563,8 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - jsdom@29.0.2: - resolution: {integrity: sha512-9VnGEBosc/ZpwyOsJBCQ/3I5p7Q5ngOY14a9bf5btenAORmZfDse1ZEheMiWcJ3h81+Fv7HmJFdS0szo/waF2w==} + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} peerDependencies: canvas: ^3.0.0 @@ -1763,8 +1732,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -1774,10 +1743,6 @@ packages: node-releases@2.0.37: resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} @@ -1797,8 +1762,8 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - parse5@8.0.0: - resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -1814,16 +1779,12 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.2: - resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} - engines: {node: '>=8.6'} - picomatch@4.0.4: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} - postcss@8.5.10: - resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -1843,10 +1804,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - react-dom@19.2.5: - resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} + react-dom@19.2.7: + resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} peerDependencies: - react: ^19.2.5 + react: ^19.2.7 react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} @@ -1866,13 +1827,13 @@ packages: redux: optional: true - react@19.2.5: - resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} + react@19.2.7: + resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} engines: {node: '>=0.10.0'} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} recharts@3.8.1: resolution: {integrity: sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==} @@ -1908,8 +1869,8 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown@1.0.0-rc.15: - resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1929,14 +1890,14 @@ packages: engines: {node: '>=10'} hasBin: true - seroval-plugins@1.5.2: - resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==} + seroval-plugins@1.5.4: + resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.5.2: - resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==} + seroval@1.5.4: + resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} engines: {node: '>=10'} shebang-command@2.0.0: @@ -2013,6 +1974,10 @@ packages: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + tinyrainbow@3.1.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} @@ -2024,10 +1989,6 @@ packages: resolution: {integrity: sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==} hasBin: true - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - tough-cookie@6.0.1: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} @@ -2077,9 +2038,9 @@ packages: resolution: {integrity: sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==} engines: {node: '>=22.19.0'} - unplugin@2.3.11: - resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} - engines: {node: '>=18.12.0'} + unplugin@3.0.0: + resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} + engines: {node: ^20.19.0 || >=22.12.0} update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -2098,13 +2059,13 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite@8.0.8: - resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==} + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.0 + '@vitejs/devtools': ^0.1.18 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -2244,11 +2205,8 @@ packages: peerDependencies: zod: ^3.25.0 || ^4.0.0 - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} zustand@4.5.7: resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} @@ -2277,7 +2235,7 @@ snapshots: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 - '@asamuzakjp/dom-selector@7.0.10': + '@asamuzakjp/dom-selector@7.1.1': dependencies: '@asamuzakjp/generational-cache': 1.0.1 '@asamuzakjp/nwsapi': 2.3.9 @@ -2442,19 +2400,19 @@ snapshots: '@csstools/css-tokenizer@4.0.0': {} - '@dagrejs/dagre@1.1.8': + '@dagrejs/dagre@3.0.0': dependencies: - '@dagrejs/graphlib': 2.2.4 + '@dagrejs/graphlib': 4.0.1 - '@dagrejs/graphlib@2.2.4': {} + '@dagrejs/graphlib@4.0.1': {} - '@emnapi/core@1.9.2': + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.2': + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true @@ -2542,9 +2500,9 @@ snapshots: '@esbuild/win32-x64@0.28.0': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)': + '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(jiti@2.7.0))': dependencies: - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2608,16 +2566,16 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.10.1 optional: true - '@oxc-project/types@0.124.0': {} + '@oxc-project/types@0.133.0': {} - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1))(react@19.2.5)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1))(react@19.2.7)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 @@ -2626,61 +2584,59 @@ snapshots: redux-thunk: 3.1.0(redux@5.0.1) reselect: 5.1.1 optionalDependencies: - react: 19.2.5 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1) + react: 19.2.7 + react-redux: 9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1) - '@rolldown/binding-android-arm64@1.0.0-rc.15': + '@rolldown/binding-android-arm64@1.0.3': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.15': + '@rolldown/binding-darwin-arm64@1.0.3': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.15': + '@rolldown/binding-darwin-x64@1.0.3': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.15': + '@rolldown/binding-freebsd-x64@1.0.3': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': + '@rolldown/binding-linux-arm64-gnu@1.0.3': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': + '@rolldown/binding-linux-arm64-musl@1.0.3': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + '@rolldown/binding-linux-ppc64-gnu@1.0.3': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + '@rolldown/binding-linux-s390x-gnu@1.0.3': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + '@rolldown/binding-linux-x64-gnu@1.0.3': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + '@rolldown/binding-linux-x64-musl@1.0.3': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + '@rolldown/binding-openharmony-arm64@1.0.3': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': + '@rolldown/binding-wasm32-wasi@1.0.3': dependencies: - '@emnapi/core': 1.9.2 - '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + '@rolldown/binding-win32-arm64-msvc@1.0.3': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + '@rolldown/binding-win32-x64-msvc@1.0.3': optional: true - '@rolldown/pluginutils@1.0.0-rc.15': {} - - '@rolldown/pluginutils@1.0.0-rc.7': {} + '@rolldown/pluginutils@1.0.1': {} '@simple-libs/child-process-utils@1.0.2': dependencies: @@ -2692,86 +2648,86 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@tanstack/history@1.161.6': {} + '@tanstack/history@1.162.0': {} - '@tanstack/query-async-storage-persister@5.99.0': + '@tanstack/query-async-storage-persister@5.101.0': dependencies: - '@tanstack/query-core': 5.99.0 - '@tanstack/query-persist-client-core': 5.99.0 + '@tanstack/query-core': 5.101.0 + '@tanstack/query-persist-client-core': 5.101.0 - '@tanstack/query-core@5.99.0': {} + '@tanstack/query-core@5.101.0': {} - '@tanstack/query-persist-client-core@5.99.0': + '@tanstack/query-persist-client-core@5.101.0': dependencies: - '@tanstack/query-core': 5.99.0 + '@tanstack/query-core': 5.101.0 - '@tanstack/react-query-persist-client@5.99.0(@tanstack/react-query@5.99.0(react@19.2.5))(react@19.2.5)': + '@tanstack/react-query-persist-client@5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/query-persist-client-core': 5.99.0 - '@tanstack/react-query': 5.99.0(react@19.2.5) - react: 19.2.5 + '@tanstack/query-persist-client-core': 5.101.0 + '@tanstack/react-query': 5.101.0(react@19.2.7) + react: 19.2.7 - '@tanstack/react-query@5.99.0(react@19.2.5)': + '@tanstack/react-query@5.101.0(react@19.2.7)': dependencies: - '@tanstack/query-core': 5.99.0 - react: 19.2.5 + '@tanstack/query-core': 5.101.0 + react: 19.2.7 - '@tanstack/react-router-devtools@1.166.13(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@tanstack/router-core@1.168.15)(csstype@3.2.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.9)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/react-router': 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - '@tanstack/router-devtools-core': 1.167.3(@tanstack/router-core@1.168.15)(csstype@3.2.3) - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + '@tanstack/react-router': 1.170.11(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.9)(csstype@3.2.3) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@tanstack/router-core': 1.168.15 + '@tanstack/router-core': 1.171.9 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/history': 1.161.6 - '@tanstack/react-store': 0.9.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - '@tanstack/router-core': 1.168.15 + '@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.9 isbot: 5.1.38 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) - '@tanstack/react-store@0.9.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@tanstack/react-store@0.9.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@tanstack/store': 0.9.3 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) - use-sync-external-store: 1.6.0(react@19.2.5) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + use-sync-external-store: 1.6.0(react@19.2.7) - '@tanstack/router-core@1.168.15': + '@tanstack/router-core@1.171.9': dependencies: - '@tanstack/history': 1.161.6 + '@tanstack/history': 1.162.0 cookie-es: 3.1.1 - seroval: 1.5.2 - seroval-plugins: 1.5.2(seroval@1.5.2) + seroval: 1.5.4 + seroval-plugins: 1.5.4(seroval@1.5.4) - '@tanstack/router-devtools-core@1.167.3(@tanstack/router-core@1.168.15)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.9)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.168.15 + '@tanstack/router-core': 1.171.9 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.166.32': + '@tanstack/router-generator@1.167.13': dependencies: '@babel/types': 7.29.0 - '@tanstack/router-core': 1.168.15 - '@tanstack/router-utils': 1.161.6 - '@tanstack/virtual-file-routes': 1.161.7 + '@tanstack/router-core': 1.171.9 + '@tanstack/router-utils': 1.162.1 + '@tanstack/virtual-file-routes': 1.162.0 + jiti: 2.7.0 magic-string: 0.30.21 prettier: 3.8.3 - tsx: 4.22.4 - zod: 3.25.76 + zod: 4.4.3 transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': + '@tanstack/router-plugin@1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -2779,20 +2735,20 @@ snapshots: '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 - '@tanstack/router-core': 1.168.15 - '@tanstack/router-generator': 1.166.32 - '@tanstack/router-utils': 1.161.6 - '@tanstack/virtual-file-routes': 1.161.7 - chokidar: 3.6.0 - unplugin: 2.3.11 - zod: 3.25.76 + '@tanstack/router-core': 1.171.9 + '@tanstack/router-generator': 1.167.13 + '@tanstack/router-utils': 1.162.1 + '@tanstack/virtual-file-routes': 1.162.0 + chokidar: 5.0.0 + unplugin: 3.0.0 + zod: 4.4.3 optionalDependencies: - '@tanstack/react-router': 1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) + '@tanstack/react-router': 1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) transitivePeerDependencies: - supports-color - '@tanstack/router-utils@1.161.6': + '@tanstack/router-utils@1.162.1': dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.1 @@ -2806,9 +2762,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.166.37(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': + '@tanstack/router-vite-plugin@1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: - '@tanstack/router-plugin': 1.167.22(@tanstack/react-router@1.168.22(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + '@tanstack/router-plugin': 1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -2819,7 +2775,7 @@ snapshots: '@tanstack/store@0.9.3': {} - '@tanstack/virtual-file-routes@1.161.7': {} + '@tanstack/virtual-file-routes@1.162.0': {} '@testing-library/dom@10.4.1': dependencies: @@ -2841,15 +2797,15 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@babel/runtime': 7.29.2 '@testing-library/dom': 10.4.1 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.16 + '@types/react-dom': 19.2.3(@types/react@19.2.16) '@tybys/wasm-util@0.10.1': dependencies: @@ -2916,25 +2872,25 @@ snapshots: dependencies: undici-types: 7.24.6 - '@types/react-dom@19.2.3(@types/react@19.2.14)': + '@types/react-dom@19.2.3(@types/react@19.2.16)': dependencies: - '@types/react': 19.2.14 + '@types/react': 19.2.16 - '@types/react@19.2.14': + '@types/react@19.2.16': dependencies: csstype: 3.2.3 '@types/use-sync-external-store@0.0.6': {} - '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2)': + '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/type-utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/type-utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) '@typescript-eslint/visitor-keys': 8.58.2 - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.2) @@ -2942,14 +2898,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2)': + '@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': dependencies: '@typescript-eslint/scope-manager': 8.58.2 '@typescript-eslint/types': 8.58.2 '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) '@typescript-eslint/visitor-keys': 8.58.2 debug: 4.4.3 - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) typescript: 6.0.2 transitivePeerDependencies: - supports-color @@ -2972,13 +2928,13 @@ snapshots: dependencies: typescript: 6.0.2 - '@typescript-eslint/type-utils@8.58.2(eslint@10.2.0)(typescript@6.0.2)': + '@typescript-eslint/type-utils@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': dependencies: '@typescript-eslint/types': 8.58.2 '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) debug: 4.4.3 - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@6.0.2) typescript: 6.0.2 transitivePeerDependencies: @@ -3001,13 +2957,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.58.2(eslint@10.2.0)(typescript@6.0.2)': + '@typescript-eslint/utils@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.58.2 '@typescript-eslint/types': 8.58.2 '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) typescript: 6.0.2 transitivePeerDependencies: - supports-color @@ -3017,10 +2973,10 @@ snapshots: '@typescript-eslint/types': 8.58.2 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.1(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: - '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) + '@rolldown/pluginutils': 1.0.1 + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) '@vitest/coverage-v8@4.1.4(vitest@4.1.4)': dependencies: @@ -3034,7 +2990,7 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + vitest: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/expect@4.1.4': dependencies: @@ -3045,13 +3001,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitest/mocker@4.1.4(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) '@vitest/pretty-format@4.1.4': dependencies: @@ -3077,13 +3033,13 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@xyflow/react@12.10.2(@types/react@19.2.14)(immer@11.1.4)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@xyflow/react@12.10.2(@types/react@19.2.16)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@xyflow/system': 0.0.76 classcat: 5.0.5 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) - zustand: 4.5.7(@types/react@19.2.14)(immer@11.1.4)(react@19.2.5) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.16)(immer@11.1.4)(react@19.2.7) transitivePeerDependencies: - '@types/react' - immer @@ -3127,11 +3083,6 @@ snapshots: ansis@4.2.0: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.2 - argparse@2.0.1: {} aria-query@5.3.0: @@ -3167,16 +3118,10 @@ snapshots: dependencies: require-from-string: 2.0.2 - binary-extensions@2.3.0: {} - brace-expansion@5.0.5: dependencies: balanced-match: 4.0.4 - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - browserslist@4.28.2: dependencies: baseline-browser-mapping: 2.10.19 @@ -3189,17 +3134,9 @@ snapshots: chai@6.2.2: {} - chokidar@3.6.0: + chokidar@5.0.0: dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + readdirp: 5.0.0 classcat@5.0.5: {} @@ -3362,7 +3299,7 @@ snapshots: emoji-regex@10.6.0: {} - entities@6.0.1: {} + entities@8.0.0: {} environment@1.1.0: {} @@ -3403,14 +3340,14 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@7.0.1(eslint@10.2.0): + eslint-plugin-react-hooks@7.1.1(eslint@10.2.0(jiti@2.7.0)): dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.2 - eslint: 10.2.0 + eslint: 10.2.0(jiti@2.7.0) hermes-parser: 0.25.1 - zod: 3.25.76 - zod-validation-error: 4.0.2(zod@3.25.76) + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) transitivePeerDependencies: - supports-color @@ -3425,9 +3362,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.2.0: + eslint@10.2.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.5.5 @@ -3457,6 +3394,8 @@ snapshots: minimatch: 10.2.5 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -3500,10 +3439,6 @@ snapshots: dependencies: flat-cache: 4.0.1 - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -3523,10 +3458,6 @@ snapshots: get-east-asian-width@1.5.0: {} - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -3555,7 +3486,7 @@ snapshots: husky@9.1.7: {} - idb-keyval@6.2.2: {} + idb-keyval@6.2.5: {} ignore@5.3.2: {} @@ -3571,10 +3502,6 @@ snapshots: internmap@2.0.3: {} - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - is-extglob@2.1.1: {} is-fullwidth-code-point@5.1.0: @@ -3585,8 +3512,6 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-number@7.0.0: {} - is-obj@2.0.0: {} is-potential-custom-element-name@1.0.1: {} @@ -3608,6 +3533,8 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + jiti@2.7.0: {} + jose@6.2.3: {} js-tokens@10.0.0: {} @@ -3618,10 +3545,10 @@ snapshots: dependencies: argparse: 2.0.1 - jsdom@29.0.2: + jsdom@29.1.1: dependencies: '@asamuzakjp/css-color': 5.1.11 - '@asamuzakjp/dom-selector': 7.0.10 + '@asamuzakjp/dom-selector': 7.1.1 '@bramus/specificity': 2.4.2 '@csstools/css-syntax-patches-for-csstree': 1.1.3(css-tree@3.2.1) '@exodus/bytes': 1.15.0 @@ -3631,7 +3558,7 @@ snapshots: html-encoding-sniffer: 6.0.0 is-potential-custom-element-name: 1.0.1 lru-cache: 11.5.1 - parse5: 8.0.0 + parse5: 8.0.1 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 @@ -3778,14 +3705,12 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.11: {} + nanoid@3.3.12: {} natural-compare@1.4.0: {} node-releases@2.0.37: {} - normalize-path@3.0.0: {} - obug@2.1.1: {} onetime@7.0.0: @@ -3809,9 +3734,9 @@ snapshots: dependencies: p-limit: 3.1.0 - parse5@8.0.0: + parse5@8.0.1: dependencies: - entities: 6.0.1 + entities: 8.0.0 path-exists@4.0.0: {} @@ -3821,13 +3746,11 @@ snapshots: picocolors@1.1.1: {} - picomatch@2.3.2: {} - picomatch@4.0.4: {} - postcss@8.5.10: + postcss@8.5.15: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -3843,45 +3766,43 @@ snapshots: punycode@2.3.1: {} - react-dom@19.2.5(react@19.2.5): + react-dom@19.2.7(react@19.2.7): dependencies: - react: 19.2.5 + react: 19.2.7 scheduler: 0.27.0 react-is@17.0.2: {} react-is@18.3.1: {} - react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 - react: 19.2.5 - use-sync-external-store: 1.6.0(react@19.2.5) + react: 19.2.7 + use-sync-external-store: 1.6.0(react@19.2.7) optionalDependencies: - '@types/react': 19.2.14 + '@types/react': 19.2.16 redux: 5.0.1 - react@19.2.5: {} + react@19.2.7: {} - readdirp@3.6.0: - dependencies: - picomatch: 2.3.2 + readdirp@5.0.0: {} - recharts@3.8.1(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react-is@18.3.1)(react@19.2.5)(redux@5.0.1): + recharts@3.8.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1))(react@19.2.5) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1))(react@19.2.7) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.45.1 eventemitter3: 5.0.4 immer: 10.2.0 - react: 19.2.5 - react-dom: 19.2.5(react@19.2.5) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) react-is: 18.3.1 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.5)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 - use-sync-external-store: 1.6.0(react@19.2.5) + use-sync-external-store: 1.6.0(react@19.2.7) victory-vendor: 37.3.6 transitivePeerDependencies: - '@types/react' @@ -3909,26 +3830,26 @@ snapshots: rfdc@1.4.1: {} - rolldown@1.0.0-rc.15: + rolldown@1.0.3: dependencies: - '@oxc-project/types': 0.124.0 - '@rolldown/pluginutils': 1.0.0-rc.15 + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.15 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.15 - '@rolldown/binding-darwin-x64': 1.0.0-rc.15 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.15 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.15 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.15 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.15 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 saxes@6.0.0: dependencies: @@ -3940,11 +3861,11 @@ snapshots: semver@7.7.4: {} - seroval-plugins@1.5.2(seroval@1.5.2): + seroval-plugins@1.5.4(seroval@1.5.4): dependencies: - seroval: 1.5.2 + seroval: 1.5.4 - seroval@1.5.2: {} + seroval@1.5.4: {} shebang-command@2.0.0: dependencies: @@ -4010,6 +3931,11 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + tinyrainbow@3.1.0: {} tldts-core@7.0.28: {} @@ -4018,10 +3944,6 @@ snapshots: dependencies: tldts-core: 7.0.28 - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - tough-cookie@6.0.1: dependencies: tldts: 7.0.28 @@ -4047,13 +3969,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.58.2(eslint@10.2.0)(typescript@6.0.2): + typescript-eslint@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2) - '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) - eslint: 10.2.0 + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + eslint: 10.2.0(jiti@2.7.0) typescript: 6.0.2 transitivePeerDependencies: - supports-color @@ -4066,10 +3988,9 @@ snapshots: undici@8.3.0: {} - unplugin@2.3.11: + unplugin@3.0.0: dependencies: '@jridgewell/remapping': 2.3.5 - acorn: 8.16.0 picomatch: 4.0.4 webpack-virtual-modules: 0.6.2 @@ -4083,9 +4004,9 @@ snapshots: dependencies: punycode: 2.3.1 - use-sync-external-store@1.6.0(react@19.2.5): + use-sync-external-store@1.6.0(react@19.2.7): dependencies: - react: 19.2.5 + react: 19.2.7 victory-vendor@37.3.6: dependencies: @@ -4104,24 +4025,25 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3): + vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.10 - rolldown: 1.0.0-rc.15 - tinyglobby: 0.2.16 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 optionalDependencies: '@types/node': 25.9.1 esbuild: 0.28.0 fsevents: 2.3.3 + jiti: 2.7.0 tsx: 4.22.4 yaml: 2.8.3 - vitest@4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)): + vitest@4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3)) + '@vitest/mocker': 4.1.4(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.4 '@vitest/runner': 4.1.4 '@vitest/snapshot': 4.1.4 @@ -4138,12 +4060,12 @@ snapshots: tinyexec: 1.1.1 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.8(@types/node@25.9.1)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.9.1 '@vitest/coverage-v8': 4.1.4(vitest@4.1.4) - jsdom: 29.0.2 + jsdom: 29.1.1 transitivePeerDependencies: - msw @@ -4192,18 +4114,16 @@ snapshots: yocto-queue@0.1.0: {} - zod-validation-error@4.0.2(zod@3.25.76): + zod-validation-error@4.0.2(zod@4.4.3): dependencies: - zod: 3.25.76 - - zod@3.25.76: {} + zod: 4.4.3 - zod@4.3.6: {} + zod@4.4.3: {} - zustand@4.5.7(@types/react@19.2.14)(immer@11.1.4)(react@19.2.5): + zustand@4.5.7(@types/react@19.2.16)(immer@11.1.4)(react@19.2.7): dependencies: - use-sync-external-store: 1.6.0(react@19.2.5) + use-sync-external-store: 1.6.0(react@19.2.7) optionalDependencies: - '@types/react': 19.2.14 + '@types/react': 19.2.16 immer: 11.1.4 - react: 19.2.5 + react: 19.2.7 From ae0491e02469b8426fdeb050f22eb72c13e3a5f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:45:42 +0200 Subject: [PATCH 22/51] chore(deps):(deps): bump the tooling group across 1 directory with 5 updates (#36) * chore(deps):(deps): bump the tooling group across 1 directory with 5 updates Bumps the tooling group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.4` | `4.1.7` | | [eslint](https://github.com/eslint/eslint) | `10.2.0` | `10.4.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.58.2` | `8.59.4` | | [typescript](https://github.com/microsoft/TypeScript) | `6.0.2` | `6.0.3` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.4` | `4.1.7` | Updates `@vitest/coverage-v8` from 4.1.4 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/coverage-v8) Updates `eslint` from 10.2.0 to 10.4.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.2.0...v10.4.0) Updates `typescript-eslint` from 8.58.2 to 8.59.4 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/typescript-eslint) Updates `typescript` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3) Updates `vitest` from 4.1.4 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/vitest) --- updated-dependencies: - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling - dependency-name: eslint dependency-version: 10.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: typescript dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling - dependency-name: typescript-eslint dependency-version: 8.59.4 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: vitest dependency-version: 4.1.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling ... Signed-off-by: dependabot[bot] * chore(web): pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- pnpm-lock.yaml | 436 ++++++++++++++++++++++++-------------------- pnpm-workspace.yaml | 10 +- 2 files changed, 246 insertions(+), 200 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dcf77e4..24ec881 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,20 +7,20 @@ settings: catalogs: default: '@vitest/coverage-v8': - specifier: ^4.1.4 - version: 4.1.4 + specifier: ^4.1.7 + version: 4.1.8 eslint: - specifier: ^10.2.0 - version: 10.2.0 + specifier: ^10.4.0 + version: 10.4.1 typescript: - specifier: ^6.0.2 - version: 6.0.2 + specifier: ^6.0.3 + version: 6.0.3 typescript-eslint: - specifier: ^8.58.2 - version: 8.58.2 + specifier: ^8.59.4 + version: 8.60.1 vitest: - specifier: ^4.1.4 - version: 4.1.4 + specifier: ^4.1.7 + version: 4.1.7 importers: @@ -40,10 +40,10 @@ importers: version: 16.4.0 typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages/server: dependencies: @@ -74,22 +74,22 @@ importers: version: 25.9.1 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.4(vitest@4.1.4) + version: 4.1.8(vitest@4.1.7) eslint: specifier: 'catalog:' - version: 10.2.0(jiti@2.7.0) + version: 10.4.1(jiti@2.7.0) tsx: specifier: ^4.22.3 version: 4.22.4 typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 typescript-eslint: specifier: 'catalog:' - version: 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages/web: dependencies: @@ -150,28 +150,28 @@ importers: version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.4(vitest@4.1.4) + version: 4.1.8(vitest@4.1.7) eslint: specifier: 'catalog:' - version: 10.2.0(jiti@2.7.0) + version: 10.4.1(jiti@2.7.0) eslint-plugin-react-hooks: specifier: ^7.1.1 - version: 7.1.1(eslint@10.2.0(jiti@2.7.0)) + version: 7.1.1(eslint@10.4.1(jiti@2.7.0)) jsdom: specifier: ^29.1.1 version: 29.1.1 typescript: specifier: 'catalog:' - version: 6.0.2 + version: 6.0.3 typescript-eslint: specifier: 'catalog:' - version: 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vite: specifier: ^8.0.14 version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) packages: @@ -197,6 +197,10 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.0': resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} engines: {node: '>=6.9.0'} @@ -239,6 +243,10 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -268,6 +276,10 @@ packages: resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -521,8 +533,8 @@ packages: resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.5.5': - resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} + '@eslint/config-helpers@0.6.0': + resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.2.1': @@ -533,8 +545,8 @@ packages: resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.1': - resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@exodus/bytes@1.15.0': @@ -899,6 +911,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} @@ -919,63 +934,63 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@typescript-eslint/eslint-plugin@8.58.2': - resolution: {integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==} + '@typescript-eslint/eslint-plugin@8.60.1': + resolution: {integrity: sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.58.2 + '@typescript-eslint/parser': ^8.60.1 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.58.2': - resolution: {integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==} + '@typescript-eslint/parser@8.60.1': + resolution: {integrity: sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==} 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.58.2': - resolution: {integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==} + '@typescript-eslint/project-service@8.60.1': + resolution: {integrity: sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.58.2': - resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==} + '@typescript-eslint/scope-manager@8.60.1': + resolution: {integrity: sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.58.2': - resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==} + '@typescript-eslint/tsconfig-utils@8.60.1': + resolution: {integrity: sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.58.2': - resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==} + '@typescript-eslint/type-utils@8.60.1': + resolution: {integrity: sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==} 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.58.2': - resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==} + '@typescript-eslint/types@8.60.1': + resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.58.2': - resolution: {integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==} + '@typescript-eslint/typescript-estree@8.60.1': + resolution: {integrity: sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.58.2': - resolution: {integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==} + '@typescript-eslint/utils@8.60.1': + resolution: {integrity: sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==} 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.58.2': - resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} + '@typescript-eslint/visitor-keys@8.60.1': + resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@6.0.2': @@ -991,20 +1006,20 @@ packages: babel-plugin-react-compiler: optional: true - '@vitest/coverage-v8@4.1.4': - resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==} + '@vitest/coverage-v8@4.1.8': + resolution: {integrity: sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw==} peerDependencies: - '@vitest/browser': 4.1.4 - vitest: 4.1.4 + '@vitest/browser': 4.1.8 + vitest: 4.1.8 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.4': - resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} + '@vitest/expect@4.1.7': + resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==} - '@vitest/mocker@4.1.4': - resolution: {integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==} + '@vitest/mocker@4.1.7': + resolution: {integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1014,20 +1029,26 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.4': - resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==} + '@vitest/pretty-format@4.1.7': + resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==} + + '@vitest/pretty-format@4.1.8': + resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} - '@vitest/runner@4.1.4': - resolution: {integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==} + '@vitest/runner@4.1.7': + resolution: {integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==} - '@vitest/snapshot@4.1.4': - resolution: {integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==} + '@vitest/snapshot@4.1.7': + resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==} - '@vitest/spy@4.1.4': - resolution: {integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==} + '@vitest/spy@4.1.7': + resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==} - '@vitest/utils@4.1.4': - resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==} + '@vitest/utils@4.1.7': + resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} + + '@vitest/utils@4.1.8': + resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} '@xyflow/react@12.10.2': resolution: {integrity: sha512-CgIi6HwlcHXwlkTpr0fxLv/0sRVNZ8IdwKLzzeCscaYBwpvfcH1QFOCeaTCuEn1FQEs/B8CjnTSjhs8udgmBgQ==} @@ -1321,8 +1342,8 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} es-toolkit@1.45.1: resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} @@ -1358,8 +1379,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.2.0: - resolution: {integrity: sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==} + eslint@10.4.1: + resolution: {integrity: sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1746,6 +1767,10 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + obug@2.1.2: + resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==} + engines: {node: '>=12.20.0'} + onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} @@ -1970,9 +1995,9 @@ packages: resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} engines: {node: '>=18'} - tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} - engines: {node: '>=12.0.0'} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} @@ -2015,15 +2040,15 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.58.2: - resolution: {integrity: sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==} + typescript-eslint@8.60.1: + resolution: {integrity: sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==} 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@6.0.2: - resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==} + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} hasBin: true @@ -2102,20 +2127,20 @@ packages: yaml: optional: true - vitest@4.1.4: - resolution: {integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==} + vitest@4.1.7: + resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==} 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.1.4 - '@vitest/browser-preview': 4.1.4 - '@vitest/browser-webdriverio': 4.1.4 - '@vitest/coverage-istanbul': 4.1.4 - '@vitest/coverage-v8': 4.1.4 - '@vitest/ui': 4.1.4 + '@vitest/browser-playwright': 4.1.7 + '@vitest/browser-preview': 4.1.7 + '@vitest/browser-webdriverio': 4.1.7 + '@vitest/coverage-istanbul': 4.1.7 + '@vitest/coverage-v8': 4.1.7 + '@vitest/ui': 4.1.7 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2253,6 +2278,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.29.0': {} '@babel/core@7.29.0': @@ -2315,6 +2346,8 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.29.2': @@ -2338,6 +2371,8 @@ snapshots: '@babel/runtime@7.29.2': {} + '@babel/runtime@7.29.7': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -2359,7 +2394,7 @@ snapshots: '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 '@bcoe/v8-coverage@1.0.2': {} @@ -2500,9 +2535,9 @@ snapshots: '@esbuild/win32-x64@0.28.0': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.4.1(jiti@2.7.0))': dependencies: - eslint: 10.2.0(jiti@2.7.0) + eslint: 10.4.1(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2515,7 +2550,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.5': + '@eslint/config-helpers@0.6.0': dependencies: '@eslint/core': 1.2.1 @@ -2525,7 +2560,7 @@ snapshots: '@eslint/object-schema@3.0.5': {} - '@eslint/plugin-kit@0.7.1': + '@eslint/plugin-kit@0.7.2': dependencies: '@eslint/core': 1.2.1 levn: 0.4.1 @@ -2758,7 +2793,7 @@ snapshots: babel-dead-code-elimination: 1.0.12 diff: 8.0.4 pathe: 2.0.3 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 transitivePeerDependencies: - supports-color @@ -2779,8 +2814,8 @@ snapshots: '@testing-library/dom@10.4.1': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/runtime': 7.29.2 + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.29.7 '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 @@ -2864,6 +2899,8 @@ snapshots: '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} + '@types/js-yaml@4.0.9': {} '@types/json-schema@7.0.15': {} @@ -2882,95 +2919,95 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': + '@typescript-eslint/eslint-plugin@8.60.1(@typescript-eslint/parser@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/type-utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - '@typescript-eslint/visitor-keys': 8.58.2 - eslint: 10.2.0(jiti@2.7.0) + '@typescript-eslint/parser': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/type-utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.60.1 + eslint: 10.4.1(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': + '@typescript-eslint/parser@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.60.1 debug: 4.4.3 - eslint: 10.2.0(jiti@2.7.0) - typescript: 6.0.2 + eslint: 10.4.1(jiti@2.7.0) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.58.2(typescript@6.0.2)': + '@typescript-eslint/project-service@8.60.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.2) - '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@6.0.3) + '@typescript-eslint/types': 8.60.1 debug: 4.4.3 - typescript: 6.0.2 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.58.2': + '@typescript-eslint/scope-manager@8.60.1': dependencies: - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/visitor-keys': 8.60.1 - '@typescript-eslint/tsconfig-utils@8.58.2(typescript@6.0.2)': + '@typescript-eslint/tsconfig-utils@8.60.1(typescript@6.0.3)': dependencies: - typescript: 6.0.2 + typescript: 6.0.3 - '@typescript-eslint/type-utils@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': + '@typescript-eslint/type-utils@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.2.0(jiti@2.7.0) - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 + eslint: 10.4.1(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.58.2': {} + '@typescript-eslint/types@8.60.1': {} - '@typescript-eslint/typescript-estree@8.58.2(typescript@6.0.2)': + '@typescript-eslint/typescript-estree@8.60.1(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.58.2(typescript@6.0.2) - '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.2) - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/project-service': 8.60.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@6.0.3) + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/visitor-keys': 8.60.1 debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 - tinyglobby: 0.2.16 - ts-api-utils: 2.5.0(typescript@6.0.2) - typescript: 6.0.2 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2)': + '@typescript-eslint/utils@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.58.2 - '@typescript-eslint/types': 8.58.2 - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - eslint: 10.2.0(jiti@2.7.0) - typescript: 6.0.2 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) + eslint: 10.4.1(jiti@2.7.0) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.58.2': + '@typescript-eslint/visitor-keys@8.60.1': dependencies: - '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': @@ -2978,10 +3015,10 @@ snapshots: '@rolldown/pluginutils': 1.0.1 vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) - '@vitest/coverage-v8@4.1.4(vitest@4.1.4)': + '@vitest/coverage-v8@4.1.8(vitest@4.1.7)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.4 + '@vitest/utils': 4.1.8 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -2990,46 +3027,56 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + vitest: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) - '@vitest/expect@4.1.4': + '@vitest/expect@4.1.7': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.4 - '@vitest/utils': 4.1.4 + '@vitest/spy': 4.1.7 + '@vitest/utils': 4.1.7 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.4(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitest/mocker@4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.4 + '@vitest/spy': 4.1.7 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) - '@vitest/pretty-format@4.1.4': + '@vitest/pretty-format@4.1.7': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/pretty-format@4.1.8': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.4': + '@vitest/runner@4.1.7': dependencies: - '@vitest/utils': 4.1.4 + '@vitest/utils': 4.1.7 pathe: 2.0.3 - '@vitest/snapshot@4.1.4': + '@vitest/snapshot@4.1.7': dependencies: - '@vitest/pretty-format': 4.1.4 - '@vitest/utils': 4.1.4 + '@vitest/pretty-format': 4.1.7 + '@vitest/utils': 4.1.7 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.4': {} + '@vitest/spy@4.1.7': {} - '@vitest/utils@4.1.4': + '@vitest/utils@4.1.7': dependencies: - '@vitest/pretty-format': 4.1.4 + '@vitest/pretty-format': 4.1.7 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + '@vitest/utils@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -3303,7 +3350,7 @@ snapshots: environment@1.1.0: {} - es-module-lexer@2.0.0: {} + es-module-lexer@2.1.0: {} es-toolkit@1.45.1: {} @@ -3340,11 +3387,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@7.1.1(eslint@10.2.0(jiti@2.7.0)): + eslint-plugin-react-hooks@7.1.1(eslint@10.4.1(jiti@2.7.0)): dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.2 - eslint: 10.2.0(jiti@2.7.0) + eslint: 10.4.1(jiti@2.7.0) hermes-parser: 0.25.1 zod: 4.4.3 zod-validation-error: 4.0.2(zod@4.4.3) @@ -3362,14 +3409,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.2.0(jiti@2.7.0): + eslint@10.4.1(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 - '@eslint/config-helpers': 0.5.5 + '@eslint/config-helpers': 0.6.0 '@eslint/core': 1.2.1 - '@eslint/plugin-kit': 0.7.1 + '@eslint/plugin-kit': 0.7.2 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -3417,7 +3464,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -3713,6 +3760,8 @@ snapshots: obug@2.1.1: {} + obug@2.1.2: {} + onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -3926,10 +3975,7 @@ snapshots: tinyexec@1.1.1: {} - tinyglobby@0.2.16: - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + tinyexec@1.2.4: {} tinyglobby@0.2.17: dependencies: @@ -3952,9 +3998,9 @@ snapshots: dependencies: punycode: 2.3.1 - ts-api-utils@2.5.0(typescript@6.0.2): + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: - typescript: 6.0.2 + typescript: 6.0.3 tslib@2.8.1: optional: true @@ -3969,18 +4015,18 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2): + typescript-eslint@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - '@typescript-eslint/parser': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) - '@typescript-eslint/utils': 8.58.2(eslint@10.2.0(jiti@2.7.0))(typescript@6.0.2) - eslint: 10.2.0(jiti@2.7.0) - typescript: 6.0.2 + '@typescript-eslint/eslint-plugin': 8.60.1(@typescript-eslint/parser@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.4.1(jiti@2.7.0) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - typescript@6.0.2: {} + typescript@6.0.3: {} undici-types@7.24.6: {} @@ -4040,31 +4086,31 @@ snapshots: tsx: 4.22.4 yaml: 2.8.3 - vitest@4.1.4(@types/node@25.9.1)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)): + vitest@4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.4 - '@vitest/runner': 4.1.4 - '@vitest/snapshot': 4.1.4 - '@vitest/spy': 4.1.4 - '@vitest/utils': 4.1.4 - es-module-lexer: 2.0.0 + '@vitest/expect': 4.1.7 + '@vitest/mocker': 4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.7 + '@vitest/runner': 4.1.7 + '@vitest/snapshot': 4.1.7 + '@vitest/spy': 4.1.7 + '@vitest/utils': 4.1.7 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 - obug: 2.1.1 + obug: 2.1.2 pathe: 2.0.3 picomatch: 4.0.4 std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 1.1.1 - tinyglobby: 0.2.16 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 tinyrainbow: 3.1.0 vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.9.1 - '@vitest/coverage-v8': 4.1.4(vitest@4.1.4) + '@vitest/coverage-v8': 4.1.8(vitest@4.1.7) jsdom: 29.1.1 transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4a45f6d..70b3d6c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,8 +2,8 @@ packages: - 'packages/*' catalog: - typescript: "^6.0.2" - eslint: "^10.2.0" - typescript-eslint: "^8.58.2" - vitest: "^4.1.4" - "@vitest/coverage-v8": "^4.1.4" + typescript: "^6.0.3" + eslint: "^10.4.0" + typescript-eslint: "^8.59.4" + vitest: "^4.1.7" + "@vitest/coverage-v8": "^4.1.7" From e7364a6e51c2e8b22b3606e3e21ed8cfc8227eb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:48:18 +0200 Subject: [PATCH 23/51] chore(docker): bump node from 24-alpine to 26-alpine in /packages/server (#34) Bumps node from 24-alpine to 26-alpine. --- updated-dependencies: - dependency-name: node dependency-version: 26-alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/server/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 56349e9..9ed79eb 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -1,5 +1,5 @@ # ── Build stage ────────────────────────────────────────────────────────────── -FROM node:24-alpine AS builder +FROM node:26-alpine AS builder # Docker Desktop's build network has no IPv6 routing; force Node.js to prefer # IPv4 so npm/pnpm can reach registry.npmjs.org without timing out. @@ -54,7 +54,7 @@ RUN pnpm --filter @dashlight/server build RUN pnpm deploy --filter @dashlight/server --prod /standalone # ── Runtime stage ───────────────────────────────────────────────────────────── -FROM node:24.3.0-alpine3.22 AS runner +FROM node:26.3.0-alpine3.22 AS runner # Copy cert bundle from builder for Node/runtime TLS trust. COPY --from=builder /opt/dashlight/ /opt/dashlight/ From a997cb63028874e9af136de644f936f792b8bbae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:48:51 +0200 Subject: [PATCH 24/51] chore(docker): bump node from 24-alpine to 26-alpine in /packages/web (#35) Bumps node from 24-alpine to 26-alpine. --- updated-dependencies: - dependency-name: node dependency-version: 26-alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/web/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index 518839d..5a3e320 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -1,5 +1,5 @@ # ── Build stage ────────────────────────────────────────────────────────────── -FROM node:24-alpine AS builder +FROM node:26-alpine AS builder # Docker Desktop's build network has no IPv6 routing; force Node.js to prefer # IPv4 so npm/pnpm can reach registry.npmjs.org without timing out. From 1f434106e3e0580fab9e63146ee2ce830e017278 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:54:10 +0200 Subject: [PATCH 25/51] chore(docker): bump nginx in /packages/web (#37) Bumps nginx from 1.29.8-alpine to 1.31.1-alpine. --- updated-dependencies: - dependency-name: nginx dependency-version: 1.31.1-alpine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/web/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index 5a3e320..9878825 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -54,7 +54,7 @@ RUN pnpm --filter @dashlight/web build # ── Runtime stage (Nginx) ───────────────────────────────────────────────────── # The nginx runner serves only static files — no outbound HTTPS, no cert bundle needed. -FROM nginx:1.29.8-alpine AS runner +FROM nginx:1.31.1-alpine AS runner COPY --from=builder /app/packages/web/dist /usr/share/nginx/html COPY packages/web/nginx.conf /etc/nginx/conf.d/default.conf From 34b81323d3cec9ebb82110c30746970dc7421a50 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Fri, 5 Jun 2026 13:14:07 +0200 Subject: [PATCH 26/51] feat: add docker compose labels --- docker-compose.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index f2e455e..0486986 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,10 @@ services: server: + labels: + com.docker.compose.project: "dashlight" + com.docker.compose.service: "server" + com.docker.compose.project.version: "1.0.0" + keep: "true" build: context: . dockerfile: packages/server/Dockerfile @@ -39,6 +44,11 @@ services: restart: unless-stopped web: + labels: + com.docker.compose.project: "dashlight" + com.docker.compose.service: "web" + com.docker.compose.project.version: "1.0.0" + keep: "true" build: context: . dockerfile: packages/web/Dockerfile From 85395b063dd539cfcc001467c2a2b1e268c1d7ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Jun 2026 22:27:31 +0200 Subject: [PATCH 27/51] chore(deps):(deps-dev): bump lint-staged in the version-all group (#38) Bumps the version-all group with 1 update: [lint-staged](https://github.com/lint-staged/lint-staged). Updates `lint-staged` from 16.4.0 to 17.0.2 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v16.4.0...v17.0.2) --- updated-dependencies: - dependency-name: lint-staged dependency-version: 17.0.2 dependency-type: direct:development update-type: version-update:semver-major dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 135 +++++++++++++++++++++---------------------------- 2 files changed, 60 insertions(+), 77 deletions(-) diff --git a/package.json b/package.json index 3ddce95..85e6718 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "conventional-changelog-conventionalcommits": "^9.3.1", "conventional-recommended-bump": "^11.2.0", "husky": "^9.1.7", - "lint-staged": "^16.4.0", + "lint-staged": "^17.0.2", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24ec881..59c2ba3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,14 +36,14 @@ importers: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^16.4.0 - version: 16.4.0 + specifier: ^17.0.2 + version: 17.0.2 typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/server: dependencies: @@ -89,7 +89,7 @@ importers: version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/web: dependencies: @@ -132,7 +132,7 @@ importers: version: 1.167.0(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.9)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/router-vite-plugin': specifier: ^1.167.9 - version: 1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -147,7 +147,7 @@ importers: version: 19.2.3(@types/react@19.2.16) '@vitejs/plugin-react': specifier: ^6.0.2 - version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.8(vitest@4.1.7) @@ -168,10 +168,10 @@ importers: version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vite: specifier: ^8.0.14 - version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) + version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages: @@ -651,42 +651,36 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.3': resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.3': resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.3': resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.3': resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.3': resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.3': resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} @@ -1166,13 +1160,6 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - - commander@14.0.3: - resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} - engines: {node: '>=20'} - compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} @@ -1461,8 +1448,8 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} glob-parent@6.0.2: @@ -1654,28 +1641,24 @@ packages: 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'} 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'} 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'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -1693,14 +1676,14 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} - lint-staged@16.4.0: - resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} - engines: {node: '>=20.17'} + lint-staged@17.0.2: + resolution: {integrity: sha512-Rbr6rdmbCn1fIDHBZpn0madg0hEkdlh+QwajnL3Qq0ZUq/icAJfLGj9BVBajAXi7657ZzKQ7kobGP9S5XOHYRw==} + engines: {node: '>=22.22.1'} hasBin: true - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} + listr2@10.2.1: + resolution: {integrity: sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==} + engines: {node: '>=22.13.0'} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1966,8 +1949,8 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.0: - resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + string-width@8.2.1: + resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} strip-ansi@7.2.0: @@ -1991,10 +1974,6 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@1.1.1: - resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} - engines: {node: '>=18'} - tinyexec@1.2.4: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} @@ -2201,6 +2180,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@10.0.0: + resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} + engines: {node: '>=20'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -2215,8 +2198,8 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.8.3: - resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} engines: {node: '>= 14.6'} hasBin: true @@ -2762,7 +2745,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': + '@tanstack/router-plugin@1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -2779,7 +2762,7 @@ snapshots: zod: 4.4.3 optionalDependencies: '@tanstack/react-router': 1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -2797,9 +2780,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': + '@tanstack/router-vite-plugin@1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + '@tanstack/router-plugin': 1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -3010,10 +2993,10 @@ snapshots: '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) '@vitest/coverage-v8@4.1.8(vitest@4.1.7)': dependencies: @@ -3027,7 +3010,7 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + vitest: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/expect@4.1.7': dependencies: @@ -3038,13 +3021,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitest/mocker@4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.7 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) '@vitest/pretty-format@4.1.7': dependencies: @@ -3194,14 +3177,10 @@ snapshots: cli-truncate@5.2.0: dependencies: slice-ansi: 8.0.0 - string-width: 8.2.0 + string-width: 8.2.1 clsx@2.1.1: {} - colorette@2.0.20: {} - - commander@14.0.3: {} - compare-func@2.0.0: dependencies: array-ify: 1.0.0 @@ -3503,7 +3482,7 @@ snapshots: gensync@1.0.0-beta.2: {} - get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} glob-parent@6.0.2: dependencies: @@ -3553,7 +3532,7 @@ snapshots: is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 is-glob@4.0.3: dependencies: @@ -3686,23 +3665,22 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 - lint-staged@16.4.0: + lint-staged@17.0.2: dependencies: - commander: 14.0.3 - listr2: 9.0.5 + listr2: 10.2.1 picomatch: 4.0.4 string-argv: 0.3.2 - tinyexec: 1.1.1 - yaml: 2.8.3 + tinyexec: 1.2.4 + optionalDependencies: + yaml: 2.9.0 - listr2@9.0.5: + listr2@10.2.1: dependencies: cli-truncate: 5.2.0 - colorette: 2.0.20 eventemitter3: 5.0.4 log-update: 6.1.0 rfdc: 1.4.1 - wrap-ansi: 9.0.2 + wrap-ansi: 10.0.0 locate-path@6.0.0: dependencies: @@ -3947,12 +3925,12 @@ snapshots: string-width@7.2.0: dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string-width@8.2.0: + string-width@8.2.1: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 strip-ansi@7.2.0: @@ -3973,8 +3951,6 @@ snapshots: tinybench@2.9.0: {} - tinyexec@1.1.1: {} - tinyexec@1.2.4: {} tinyglobby@0.2.17: @@ -4071,7 +4047,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3): + vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -4084,12 +4060,12 @@ snapshots: fsevents: 2.3.3 jiti: 2.7.0 tsx: 4.22.4 - yaml: 2.8.3 + yaml: 2.9.0 - vitest@4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)): + vitest@4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.7 - '@vitest/mocker': 4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3)) + '@vitest/mocker': 4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.7 '@vitest/runner': 4.1.7 '@vitest/snapshot': 4.1.7 @@ -4106,7 +4082,7 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.8.3) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.9.1 @@ -4144,6 +4120,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@10.0.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 8.2.1 + strip-ansi: 7.2.0 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -4156,7 +4138,8 @@ snapshots: yallist@3.1.1: {} - yaml@2.8.3: {} + yaml@2.9.0: + optional: true yocto-queue@0.1.0: {} From aa47635489237591123522d3b2b4bfa45f3ea117 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:34:07 +0200 Subject: [PATCH 28/51] chore(gha): bump the version-all group with 3 updates (#46) Bumps the version-all group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [pnpm/action-setup](https://github.com/pnpm/action-setup) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `actions/checkout` from 6.0.3 to 7.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) Updates `pnpm/action-setup` from 6.0.8 to 6.0.9 - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/0e279bb959325dab635dd2c09392533439d90093...0ebf47130e4866e96fce0953f49152a61190b271) Updates `softprops/action-gh-release` from 3.0.0 to 3.0.1 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/b4309332981a82ec1c5618f44dd2e27cc8bfbfda...718ea10b132b3b2eba29c1007bb80653f286566b) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: pnpm/action-setup dependency-version: 6.0.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: softprops/action-gh-release dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly-deps.yml | 4 ++-- .github/workflows/release.yml | 10 +++++----- .github/workflows/test-build.yml | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/nightly-deps.yml b/.github/workflows/nightly-deps.yml index 2cced6b..7d649ab 100644 --- a/.github/workflows/nightly-deps.yml +++ b/.github/workflows/nightly-deps.yml @@ -18,9 +18,9 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a09cce3..a51cc24 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,11 +31,11 @@ jobs: tag: ${{ steps.compute.outputs.tag }} skip: ${{ steps.compute.outputs.skip }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 # full history required by conventional-recommended-bump - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 @@ -81,11 +81,11 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 @@ -130,7 +130,7 @@ jobs: } >> "$GITHUB_OUTPUT" - name: Create GitHub Release - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 with: tag_name: ${{ needs.version.outputs.tag }} name: ${{ needs.version.outputs.tag }} diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 1dbb9bd..ba102f0 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -23,9 +23,9 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 @@ -49,9 +49,9 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 @@ -76,9 +76,9 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 @@ -107,7 +107,7 @@ jobs: - image: web dockerfile: packages/web/Dockerfile steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 From 1f13097f02b3ba5fc3b198b1c5046e5810060f4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:34:54 +0200 Subject: [PATCH 29/51] chore(docker): bump nginx in /packages/web (#45) Bumps nginx from 1.31.1-alpine to 1.31.2-alpine. --- updated-dependencies: - dependency-name: nginx dependency-version: 1.31.2-alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/web/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index 9878825..5d2d571 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -54,7 +54,7 @@ RUN pnpm --filter @dashlight/web build # ── Runtime stage (Nginx) ───────────────────────────────────────────────────── # The nginx runner serves only static files — no outbound HTTPS, no cert bundle needed. -FROM nginx:1.31.1-alpine AS runner +FROM nginx:1.31.2-alpine AS runner COPY --from=builder /app/packages/web/dist /usr/share/nginx/html COPY packages/web/nginx.conf /etc/nginx/conf.d/default.conf From b23adf636fd5dc4a148bbf190b2c3c5250b5c7a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:40:50 +0200 Subject: [PATCH 30/51] chore(deps):(deps): bump hono (#42) Bumps the security-all group with 1 update in the / directory: [hono](https://github.com/honojs/hono). Updates `hono` from 4.12.23 to 4.12.25 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.23...v4.12.25) --- updated-dependencies: - dependency-name: hono dependency-version: 4.12.25 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/server/package.json | 2 +- pnpm-lock.yaml | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 59b3c05..7314d61 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "@hono/node-server": "^2.0.1", - "hono": "^4.12.23", + "hono": "^4.12.25", "jose": "^6.2.3", "js-yaml": "^4.1.1", "lru-cache": "^11.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59c2ba3..458039c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,10 +49,10 @@ importers: dependencies: '@hono/node-server': specifier: ^2.0.1 - version: 2.0.4(hono@4.12.23) + version: 2.0.4(hono@4.12.25) hono: - specifier: ^4.12.23 - version: 4.12.23 + specifier: ^4.12.25 + version: 4.12.25 jose: specifier: ^6.2.3 version: 6.2.3 @@ -651,36 +651,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.3': resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.3': resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.3': resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.3': resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.3': resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.3': resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} @@ -1471,8 +1477,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.23: - resolution: {integrity: sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==} + hono@4.12.25: + resolution: {integrity: sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -1641,24 +1647,28 @@ packages: 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'} 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'} 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'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -2550,9 +2560,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.4(hono@4.12.23)': + '@hono/node-server@2.0.4(hono@4.12.25)': dependencies: - hono: 4.12.23 + hono: 4.12.25 '@humanfs/core@0.19.1': {} @@ -3500,7 +3510,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.23: {} + hono@4.12.25: {} html-encoding-sniffer@6.0.0: dependencies: From 8a0b802ede5b7eabdb742dc74469795de78c3204 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:45:06 +0200 Subject: [PATCH 31/51] chore(deps):(deps): bump the security-all group across 1 directory with 2 updates (#47) Bumps the security-all group with 2 updates in the / directory: [js-yaml](https://github.com/nodeca/js-yaml) and [undici](https://github.com/nodejs/undici). Updates `js-yaml` from 4.1.1 to 4.2.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.1...4.2.0) Updates `undici` from 8.3.0 to 8.5.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.3.0...v8.5.0) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.2.0 dependency-type: direct:production dependency-group: security-all - dependency-name: undici dependency-version: 8.5.0 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/server/package.json | 4 ++-- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 7314d61..b8b5d82 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -18,9 +18,9 @@ "@hono/node-server": "^2.0.1", "hono": "^4.12.25", "jose": "^6.2.3", - "js-yaml": "^4.1.1", + "js-yaml": "^4.2.0", "lru-cache": "^11.5.0", - "undici": "^8.3.0" + "undici": "^8.5.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 458039c..9d28bd3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,14 +57,14 @@ importers: specifier: ^6.2.3 version: 6.2.3 js-yaml: - specifier: ^4.1.1 - version: 4.1.1 + specifier: ^4.2.0 + version: 4.2.0 lru-cache: specifier: ^11.5.0 version: 11.5.1 undici: - specifier: ^8.3.0 - version: 8.3.0 + specifier: ^8.5.0 + version: 8.5.0 devDependencies: '@types/js-yaml': specifier: ^4.0.9 @@ -1573,8 +1573,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true jsdom@29.1.1: @@ -2044,12 +2044,12 @@ packages: undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} - undici@7.25.0: - resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} - undici@8.3.0: - resolution: {integrity: sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==} + undici@8.5.0: + resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==} engines: {node: '>=22.19.0'} unplugin@3.0.0: @@ -3577,7 +3577,7 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.1.1: + js-yaml@4.2.0: dependencies: argparse: 2.0.1 @@ -3598,7 +3598,7 @@ snapshots: saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.25.0 + undici: 7.28.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -4016,9 +4016,9 @@ snapshots: undici-types@7.24.6: {} - undici@7.25.0: {} + undici@7.28.0: {} - undici@8.3.0: {} + undici@8.5.0: {} unplugin@3.0.0: dependencies: From 0a19abfa3110da3035f6a0bf010b6e3dd6597281 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:49:39 +0200 Subject: [PATCH 32/51] chore(deps):(deps): bump vitest from 4.1.7 to 4.1.8 in the tooling group (#39) * chore(deps):(deps): bump vitest from 4.1.7 to 4.1.8 in the tooling group Bumps the tooling group with 1 update: [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). Updates `vitest` from 4.1.7 to 4.1.8 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling ... Signed-off-by: dependabot[bot] * chore(deps): update pnpm-lock --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- pnpm-lock.yaml | 118 +++++++++++++++++++------------------------- pnpm-workspace.yaml | 2 +- 2 files changed, 52 insertions(+), 68 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d28bd3..48672c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,8 +19,8 @@ catalogs: specifier: ^8.59.4 version: 8.60.1 vitest: - specifier: ^4.1.7 - version: 4.1.7 + specifier: ^4.1.8 + version: 4.1.8 importers: @@ -43,7 +43,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/server: dependencies: @@ -74,7 +74,7 @@ importers: version: 25.9.1 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.7) + version: 4.1.8(vitest@4.1.8) eslint: specifier: 'catalog:' version: 10.4.1(jiti@2.7.0) @@ -89,7 +89,7 @@ importers: version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/web: dependencies: @@ -150,7 +150,7 @@ importers: version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.7) + version: 4.1.8(vitest@4.1.8) eslint: specifier: 'catalog:' version: 10.4.1(jiti@2.7.0) @@ -171,7 +171,7 @@ importers: version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages: @@ -1015,11 +1015,11 @@ packages: '@vitest/browser': optional: true - '@vitest/expect@4.1.7': - resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==} + '@vitest/expect@4.1.8': + resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} - '@vitest/mocker@4.1.7': - resolution: {integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==} + '@vitest/mocker@4.1.8': + resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1029,23 +1029,17 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.7': - resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==} - '@vitest/pretty-format@4.1.8': resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} - '@vitest/runner@4.1.7': - resolution: {integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==} + '@vitest/runner@4.1.8': + resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} - '@vitest/snapshot@4.1.7': - resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==} + '@vitest/snapshot@4.1.8': + resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} - '@vitest/spy@4.1.7': - resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==} - - '@vitest/utils@4.1.7': - resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} + '@vitest/spy@4.1.8': + resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} '@vitest/utils@4.1.8': resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} @@ -1760,8 +1754,8 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - obug@2.1.2: - resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==} + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} onetime@7.0.0: @@ -2116,20 +2110,20 @@ packages: yaml: optional: true - vitest@4.1.7: - resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==} + vitest@4.1.8: + resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} 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.1.7 - '@vitest/browser-preview': 4.1.7 - '@vitest/browser-webdriverio': 4.1.7 - '@vitest/coverage-istanbul': 4.1.7 - '@vitest/coverage-v8': 4.1.7 - '@vitest/ui': 4.1.7 + '@vitest/browser-playwright': 4.1.8 + '@vitest/browser-preview': 4.1.8 + '@vitest/browser-webdriverio': 4.1.8 + '@vitest/coverage-istanbul': 4.1.8 + '@vitest/coverage-v8': 4.1.8 + '@vitest/ui': 4.1.8 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3008,7 +3002,7 @@ snapshots: '@rolldown/pluginutils': 1.0.1 vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) - '@vitest/coverage-v8@4.1.8(vitest@4.1.7)': + '@vitest/coverage-v8@4.1.8(vitest@4.1.8)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.1.8 @@ -3020,52 +3014,42 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - '@vitest/expect@4.1.7': + '@vitest/expect@4.1.8': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.7 + '@vitest/spy': 4.1.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) - '@vitest/pretty-format@4.1.7': - dependencies: - tinyrainbow: 3.1.0 - '@vitest/pretty-format@4.1.8': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.7': + '@vitest/runner@4.1.8': dependencies: - '@vitest/utils': 4.1.7 + '@vitest/utils': 4.1.8 pathe: 2.0.3 - '@vitest/snapshot@4.1.7': + '@vitest/snapshot@4.1.8': dependencies: - '@vitest/pretty-format': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/pretty-format': 4.1.8 + '@vitest/utils': 4.1.8 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.7': {} - - '@vitest/utils@4.1.7': - dependencies: - '@vitest/pretty-format': 4.1.7 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 + '@vitest/spy@4.1.8': {} '@vitest/utils@4.1.8': dependencies: @@ -3748,7 +3732,7 @@ snapshots: obug@2.1.1: {} - obug@2.1.2: {} + obug@2.1.3: {} onetime@7.0.0: dependencies: @@ -4072,19 +4056,19 @@ snapshots: tsx: 4.22.4 yaml: 2.9.0 - vitest@4.1.7(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): + vitest@4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.7 - '@vitest/mocker': 4.1.7(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.7 - '@vitest/runner': 4.1.7 - '@vitest/snapshot': 4.1.7 - '@vitest/spy': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/expect': 4.1.8 + '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.8 + '@vitest/runner': 4.1.8 + '@vitest/snapshot': 4.1.8 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 - obug: 2.1.2 + obug: 2.1.3 pathe: 2.0.3 picomatch: 4.0.4 std-env: 4.1.0 @@ -4096,7 +4080,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.9.1 - '@vitest/coverage-v8': 4.1.8(vitest@4.1.7) + '@vitest/coverage-v8': 4.1.8(vitest@4.1.8) jsdom: 29.1.1 transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 70b3d6c..390f20f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,5 +5,5 @@ catalog: typescript: "^6.0.3" eslint: "^10.4.0" typescript-eslint: "^8.59.4" - vitest: "^4.1.7" + vitest: "^4.1.8" "@vitest/coverage-v8": "^4.1.7" From 3b8e4616b6883233d982958a3fe441f2936774aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:54:47 +0200 Subject: [PATCH 33/51] chore(web):(deps): bump the version-all group across 1 directory with 4 updates (#44) * chore(web):(deps): bump the version-all group across 1 directory with 4 updates Bumps the version-all group with 4 updates in the /packages/web directory: [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router), [@xyflow/react](https://github.com/xyflow/xyflow/tree/HEAD/packages/react), [@tanstack/router-vite-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-vite-plugin) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). Updates `@tanstack/react-router` from 1.170.11 to 1.170.15 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.15/packages/react-router) Updates `@xyflow/react` from 12.10.2 to 12.11.0 - [Release notes](https://github.com/xyflow/xyflow/releases) - [Changelog](https://github.com/xyflow/xyflow/blob/main/packages/react/CHANGELOG.md) - [Commits](https://github.com/xyflow/xyflow/commits/@xyflow/react@12.11.0/packages/react) Updates `@tanstack/router-vite-plugin` from 1.167.14 to 1.167.18 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/router-vite-plugin/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/router-vite-plugin@1.167.18/packages/router-vite-plugin) Updates `@types/react` from 19.2.16 to 19.2.17 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@tanstack/react-router" dependency-version: 1.170.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@xyflow/react" dependency-version: 12.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/router-vite-plugin" dependency-version: 1.167.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@types/react" dependency-version: 19.2.17 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(web) update pnpm-lock --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- packages/web/package.json | 8 +- pnpm-lock.yaml | 184 +++++++++++++++++--------------------- 2 files changed, 84 insertions(+), 108 deletions(-) diff --git a/packages/web/package.json b/packages/web/package.json index 2c5e9bc..25e988f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -17,8 +17,8 @@ "@tanstack/query-async-storage-persister": "^5.100.11", "@tanstack/react-query": "^5.100.11", "@tanstack/react-query-persist-client": "^5.100.11", - "@tanstack/react-router": "^1.170.6", - "@xyflow/react": "^12.10.2", + "@tanstack/react-router": "^1.170.15", + "@xyflow/react": "^12.11.0", "@dagrejs/dagre": "^3.0.0", "idb-keyval": "^6.2.4", "react": "^19.2.6", @@ -28,10 +28,10 @@ }, "devDependencies": { "@tanstack/react-router-devtools": "^1.167.0", - "@tanstack/router-vite-plugin": "^1.167.9", + "@tanstack/router-vite-plugin": "^1.167.18", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", - "@types/react": "^19.2.15", + "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", "@vitest/coverage-v8": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48672c8..67e946e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,11 +106,11 @@ importers: specifier: ^5.100.11 version: 5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7) '@tanstack/react-router': - specifier: ^1.170.6 - version: 1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.170.15 + version: 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@xyflow/react': - specifier: ^12.10.2 - version: 12.10.2(@types/react@19.2.16)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^12.11.0 + version: 12.11.0(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) idb-keyval: specifier: ^6.2.4 version: 6.2.5 @@ -122,29 +122,29 @@ importers: version: 19.2.7(react@19.2.7) recharts: specifier: ^3.8.1 - version: 3.8.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1) + version: 3.8.1(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1) zod: specifier: ^4.4.3 version: 4.4.3 devDependencies: '@tanstack/react-router-devtools': specifier: ^1.167.0 - version: 1.167.0(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.9)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/router-vite-plugin': - specifier: ^1.167.9 - version: 1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^1.167.18 + version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 16.3.2(@testing-library/dom@10.4.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) '@types/react': - specifier: ^19.2.15 - version: 19.2.16 + specifier: ^19.2.17 + version: 19.2.17 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.16) + version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^6.0.2 version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) @@ -231,10 +231,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -260,18 +256,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-jsx@7.28.6': - resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.28.6': - resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -764,8 +748,8 @@ packages: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.170.11': - resolution: {integrity: sha512-gP2vzdyaI8Ow/Uz/MRPfK2wN09YwRI0Y/oF74Wuy9R3KmjbfJv2tLrkM+Onu1xWklSn3ugZarMPJXRE0kzrJTA==} + '@tanstack/react-router@1.170.16': + resolution: {integrity: sha512-w6eq1IJklujs1tESazaK/FxH0+H2l8vm/QPuu1cD3oRW/ubgKneQpd7b64ti/8gUyEimzimJQZDmJr6YHfP5+g==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -777,8 +761,8 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.171.9': - resolution: {integrity: sha512-QM5ZwLT9c5ZcTJW0QQZRRIBC4qjImUyUCXCVyuYVOF9xr76XLsJSX4F2dOxr9VptAv+W+TkWNOYdX8VaO9kdgA==} + '@tanstack/router-core@1.171.13': + resolution: {integrity: sha512-+NOwEj1kO/6IGmpHRIZHasYxYWpyBQGNIZAST9aNrk9Q3YlU9SgqVnl1pbLa9qAKfeNdXQIRve0RQb/0kyDeDA==} engines: {node: '>=20.19'} '@tanstack/router-devtools-core@1.168.0': @@ -791,16 +775,16 @@ packages: csstype: optional: true - '@tanstack/router-generator@1.167.13': - resolution: {integrity: sha512-DldbCjA8S/CXQBuoyQqr76xqZe9k+H1ymV+ugj2IBHFi4yRzx4z4f2nSsPYlLdpXD2Cf/MEjLncaG7ceY5H5ig==} + '@tanstack/router-generator@1.167.17': + resolution: {integrity: sha512-xtB9tB2Ws0tWR6Pi7nc3Qk9IYgoh1mQCKWjHqIl9tf6BNUpKoqniJoPAQ4+LGrK8FeZYU0o0p/qlZEyj9FAulA==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.168.14': - resolution: {integrity: sha512-z+3vYJ7ouNnMzBIC1hsNWsxaQFu9Gf0WSdE3jBHWa326ipnONqDD5KeCqWGczq0HMdZY4UsDjyfvjucxXhrb0A==} + '@tanstack/router-plugin@1.168.18': + resolution: {integrity: sha512-MofS28/axfnfnhOD2RSgJEaU882aX5RsAzhGz5Vc4XhAmvCjy919u9JrNs4QsTWFbTD1P7IJ8WFlFVsrg0pStg==} engines: {node: '>=20.19'} peerDependencies: '@rsbuild/core': '>=1.0.2 || ^2.0.0' - '@tanstack/react-router': ^1.170.11 + '@tanstack/react-router': ^1.170.15 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' @@ -816,12 +800,12 @@ packages: webpack: optional: true - '@tanstack/router-utils@1.162.1': - resolution: {integrity: sha512-62layyTGmclHDQS/eidwKRfN1hhCKwViG7iEBcVmL0MXgcAB3OOucWCEcDDGd9Cu11H6b4QQ5oOo47MWIqwz0A==} + '@tanstack/router-utils@1.162.2': + resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==} engines: {node: '>=20.19'} - '@tanstack/router-vite-plugin@1.167.14': - resolution: {integrity: sha512-B3/SPQ3hh61/QdrI39EZDZ1JDoeHvj+eDT7KOg9cPn3poXSgPiO4VmM/J0eD96vLFchZBS+fhnFvb8jtxrxtIw==} + '@tanstack/router-vite-plugin@1.167.18': + resolution: {integrity: sha512-JG5kSvzF1UJasJRLO3oXiuJp1F2OIrRJuZpJ6JAfU+k1gOStHFlSP/X9xArnhtEKvitYNCN+26yn4ku8X0DP7w==} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': @@ -928,8 +912,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.16': - resolution: {integrity: sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==} + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} @@ -1044,14 +1028,21 @@ packages: '@vitest/utils@4.1.8': resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} - '@xyflow/react@12.10.2': - resolution: {integrity: sha512-CgIi6HwlcHXwlkTpr0fxLv/0sRVNZ8IdwKLzzeCscaYBwpvfcH1QFOCeaTCuEn1FQEs/B8CjnTSjhs8udgmBgQ==} + '@xyflow/react@12.11.0': + resolution: {integrity: sha512-na4IO33FSs2OS72hASgZDmTYwFAkef7Z74uBUVrong3ARmQQHfnRUVaCFn1kTt5LbS6pK03TbYjCPGLjLFfziA==} peerDependencies: + '@types/react': '>=17' + '@types/react-dom': '>=17' react: '>=17' react-dom: '>=17' + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true - '@xyflow/system@0.0.76': - resolution: {integrity: sha512-hvwvnRS1B3REwVDlWexsq7YQaPZeG3/mKo1jv38UmnpWmxihp14bW6VtEOuHEwJX2FvzFw8k77LyKSk/wiZVNA==} + '@xyflow/system@0.0.77': + resolution: {integrity: sha512-qCDCMCQAAgUu8yHnhloHG9F5mwPX5E+Wl8McpYIOPSSXfzFJJoZcwOcsDiAjitVKIg2de1WmJbCHfpcvxprsgg==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -2327,8 +2318,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.28.6': {} - '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -2346,16 +2335,6 @@ snapshots: dependencies: '@babel/types': 7.29.0 - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/runtime@7.29.2': {} '@babel/runtime@7.29.7': {} @@ -2597,7 +2576,7 @@ snapshots: '@oxc-project/types@0.133.0': {} - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1))(react@19.2.7)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1))(react@19.2.7)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 @@ -2607,7 +2586,7 @@ snapshots: reselect: 5.1.1 optionalDependencies: react: 19.2.7 - react-redux: 9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) '@rolldown/binding-android-arm64@1.0.3': optional: true @@ -2694,22 +2673,22 @@ snapshots: '@tanstack/query-core': 5.101.0 react: 19.2.7 - '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.9)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/react-router': 1.170.11(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.9)(csstype@3.2.3) + '@tanstack/react-router': 1.170.16(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.13)(csstype@3.2.3) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@tanstack/router-core': 1.171.9 + '@tanstack/router-core': 1.171.13 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': 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.9 + '@tanstack/router-core': 1.171.13 isbot: 5.1.38 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -2721,26 +2700,26 @@ snapshots: react-dom: 19.2.7(react@19.2.7) use-sync-external-store: 1.6.0(react@19.2.7) - '@tanstack/router-core@1.171.9': + '@tanstack/router-core@1.171.13': dependencies: '@tanstack/history': 1.162.0 cookie-es: 3.1.1 seroval: 1.5.4 seroval-plugins: 1.5.4(seroval@1.5.4) - '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.9)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.13)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.171.9 + '@tanstack/router-core': 1.171.13 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.167.13': + '@tanstack/router-generator@1.167.17': dependencies: '@babel/types': 7.29.0 - '@tanstack/router-core': 1.171.9 - '@tanstack/router-utils': 1.162.1 + '@tanstack/router-core': 1.171.13 + '@tanstack/router-utils': 1.162.2 '@tanstack/virtual-file-routes': 1.162.0 jiti: 2.7.0 magic-string: 0.30.21 @@ -2749,30 +2728,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.0 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 - '@tanstack/router-core': 1.171.9 - '@tanstack/router-generator': 1.167.13 - '@tanstack/router-utils': 1.162.1 - '@tanstack/virtual-file-routes': 1.162.0 + '@tanstack/router-core': 1.171.13 + '@tanstack/router-generator': 1.167.17 + '@tanstack/router-utils': 1.162.2 chokidar: 5.0.0 unplugin: 3.0.0 zod: 4.4.3 optionalDependencies: - '@tanstack/react-router': 1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@tanstack/react-router': 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@tanstack/router-utils@1.162.1': + '@tanstack/router-utils@1.162.2': dependencies: - '@babel/core': 7.29.0 '@babel/generator': 7.29.1 '@babel/parser': 7.29.2 '@babel/types': 7.29.0 @@ -2784,9 +2758,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.14(@tanstack/react-router@1.170.11(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -2819,15 +2793,15 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.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)': dependencies: '@babel/runtime': 7.29.2 '@testing-library/dom': 10.4.1 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) '@tybys/wasm-util@0.10.1': dependencies: @@ -2896,11 +2870,11 @@ snapshots: dependencies: undici-types: 7.24.6 - '@types/react-dom@19.2.3(@types/react@19.2.16)': + '@types/react-dom@19.2.3(@types/react@19.2.17)': dependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@types/react@19.2.16': + '@types/react@19.2.17': dependencies: csstype: 3.2.3 @@ -3057,18 +3031,20 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@xyflow/react@12.10.2(@types/react@19.2.16)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@xyflow/react@12.11.0(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@xyflow/system': 0.0.76 + '@xyflow/system': 0.0.77 classcat: 5.0.5 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - zustand: 4.5.7(@types/react@19.2.16)(immer@11.1.4)(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(immer@11.1.4)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) transitivePeerDependencies: - - '@types/react' - immer - '@xyflow/system@0.0.76': + '@xyflow/system@0.0.77': dependencies: '@types/d3-drag': 3.0.7 '@types/d3-interpolate': 3.0.4 @@ -3796,22 +3772,22 @@ snapshots: react-is@18.3.1: {} - react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.17)(react@19.2.7)(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) optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 redux: 5.0.1 react@19.2.7: {} readdirp@5.0.0: {} - recharts@3.8.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1): + recharts@3.8.1(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1))(react@19.2.7) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1))(react@19.2.7) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.45.1 @@ -3820,7 +3796,7 @@ snapshots: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) react-is: 18.3.1 - react-redux: 9.2.0(@types/react@19.2.16)(react@19.2.7)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 use-sync-external-store: 1.6.0(react@19.2.7) @@ -4143,10 +4119,10 @@ snapshots: zod@4.4.3: {} - zustand@4.5.7(@types/react@19.2.16)(immer@11.1.4)(react@19.2.7): + zustand@4.5.7(@types/react@19.2.17)(immer@11.1.4)(react@19.2.7): dependencies: use-sync-external-store: 1.6.0(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 immer: 11.1.4 react: 19.2.7 From db933c054ffd4dc6ac51e5fb24507cbe30517a8d Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Sun, 21 Jun 2026 11:15:28 +0200 Subject: [PATCH 34/51] chore: update vulnerable brace-expansion, esbuild, @babel/core package versions --- package.json | 10 +- pnpm-lock.yaml | 427 +++++++++++++++++++++++++++++-------------------- 2 files changed, 259 insertions(+), 178 deletions(-) diff --git a/package.json b/package.json index 85e6718..2ae72c7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,15 @@ "allowedVersions": { "eslint-plugin-react-hooks>eslint": ">=10" } - } + }, + "overrides": { + "brace-expansion": "^5.0.6", + "esbuild": "^0.28.1", + "@babel/core": "^7.29.7" + }, + "onlyBuiltDependencies": [ + "esbuild" + ] }, "devDependencies": { "conventional-changelog-conventionalcommits": "^9.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67e946e..ed4d0fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,11 @@ catalogs: specifier: ^4.1.8 version: 4.1.8 +overrides: + brace-expansion: ^5.0.6 + esbuild: ^0.28.1 + '@babel/core': ^7.29.7 + importers: .: @@ -43,7 +48,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/server: dependencies: @@ -89,7 +94,7 @@ importers: version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/web: dependencies: @@ -132,7 +137,7 @@ importers: version: 1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/router-vite-plugin': specifier: ^1.167.18 - version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -147,7 +152,7 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^6.0.2 - version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.8(vitest@4.1.8) @@ -168,10 +173,10 @@ importers: version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) vite: specifier: ^8.0.14 - version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages: @@ -201,40 +206,52 @@ packages: resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} '@babel/generator@7.29.1': resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0 + '@babel/core': ^7.29.7 '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} @@ -243,12 +260,12 @@ packages: resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} '@babel/parser@7.29.2': @@ -256,6 +273,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -268,14 +290,26 @@ packages: resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.0': resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -347,158 +381,158 @@ packages: '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - '@esbuild/aix-ppc64@0.28.0': - resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.28.0': - resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.28.0': - resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.28.0': - resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.28.0': - resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.28.0': - resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.28.0': - resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.0': - resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.28.0': - resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.28.0': - resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.28.0': - resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.28.0': - resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.28.0': - resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.28.0': - resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.28.0': - resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.28.0': - resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.28.0': - resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.28.0': - resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.0': - resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.28.0': - resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.0': - resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.28.0': - resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.28.0': - resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.28.0': - resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.28.0': - resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.28.0': - resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1116,8 +1150,8 @@ packages: bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - brace-expansion@5.0.5: - resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} browserslist@4.28.2: @@ -1326,8 +1360,8 @@ packages: es-toolkit@1.45.1: resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} - esbuild@0.28.0: - resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} hasBin: true @@ -2065,7 +2099,7 @@ packages: peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 '@vitejs/devtools': ^0.1.18 - esbuild: ^0.27.0 || ^0.28.0 + esbuild: ^0.28.1 jiti: '>=1.21.0' less: ^4.0.0 sass: ^1.70.0 @@ -2262,19 +2296,19 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.0': {} + '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.0': + '@babel/core@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@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/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -2292,49 +2326,65 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.28.6': + '@babel/generator@7.29.7': dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 '@babel/helper-globals@7.28.0': {} - '@babel/helper-module-imports@7.28.6': + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-option@7.27.1': {} + '@babel/helper-validator-option@7.29.7': {} - '@babel/helpers@7.29.2': + '@babel/helpers@7.29.7': dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 '@babel/parser@7.29.2': dependencies: '@babel/types': 7.29.0 + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + '@babel/runtime@7.29.2': {} '@babel/runtime@7.29.7': {} @@ -2345,6 +2395,12 @@ snapshots: '@babel/parser': 7.29.2 '@babel/types': 7.29.0 + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@babel/traverse@7.29.0': dependencies: '@babel/code-frame': 7.29.0 @@ -2357,11 +2413,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.29.7 + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@bcoe/v8-coverage@1.0.2': {} '@bramus/specificity@2.4.2': @@ -2423,82 +2496,82 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.28.0': + '@esbuild/aix-ppc64@0.28.1': optional: true - '@esbuild/android-arm64@0.28.0': + '@esbuild/android-arm64@0.28.1': optional: true - '@esbuild/android-arm@0.28.0': + '@esbuild/android-arm@0.28.1': optional: true - '@esbuild/android-x64@0.28.0': + '@esbuild/android-x64@0.28.1': optional: true - '@esbuild/darwin-arm64@0.28.0': + '@esbuild/darwin-arm64@0.28.1': optional: true - '@esbuild/darwin-x64@0.28.0': + '@esbuild/darwin-x64@0.28.1': optional: true - '@esbuild/freebsd-arm64@0.28.0': + '@esbuild/freebsd-arm64@0.28.1': optional: true - '@esbuild/freebsd-x64@0.28.0': + '@esbuild/freebsd-x64@0.28.1': optional: true - '@esbuild/linux-arm64@0.28.0': + '@esbuild/linux-arm64@0.28.1': optional: true - '@esbuild/linux-arm@0.28.0': + '@esbuild/linux-arm@0.28.1': optional: true - '@esbuild/linux-ia32@0.28.0': + '@esbuild/linux-ia32@0.28.1': optional: true - '@esbuild/linux-loong64@0.28.0': + '@esbuild/linux-loong64@0.28.1': optional: true - '@esbuild/linux-mips64el@0.28.0': + '@esbuild/linux-mips64el@0.28.1': optional: true - '@esbuild/linux-ppc64@0.28.0': + '@esbuild/linux-ppc64@0.28.1': optional: true - '@esbuild/linux-riscv64@0.28.0': + '@esbuild/linux-riscv64@0.28.1': optional: true - '@esbuild/linux-s390x@0.28.0': + '@esbuild/linux-s390x@0.28.1': optional: true - '@esbuild/linux-x64@0.28.0': + '@esbuild/linux-x64@0.28.1': optional: true - '@esbuild/netbsd-arm64@0.28.0': + '@esbuild/netbsd-arm64@0.28.1': optional: true - '@esbuild/netbsd-x64@0.28.0': + '@esbuild/netbsd-x64@0.28.1': optional: true - '@esbuild/openbsd-arm64@0.28.0': + '@esbuild/openbsd-arm64@0.28.1': optional: true - '@esbuild/openbsd-x64@0.28.0': + '@esbuild/openbsd-x64@0.28.1': optional: true - '@esbuild/openharmony-arm64@0.28.0': + '@esbuild/openharmony-arm64@0.28.1': optional: true - '@esbuild/sunos-x64@0.28.0': + '@esbuild/sunos-x64@0.28.1': optional: true - '@esbuild/win32-arm64@0.28.0': + '@esbuild/win32-arm64@0.28.1': optional: true - '@esbuild/win32-ia32@0.28.0': + '@esbuild/win32-ia32@0.28.1': optional: true - '@esbuild/win32-x64@0.28.0': + '@esbuild/win32-x64@0.28.1': optional: true '@eslint-community/eslint-utils@4.9.1(eslint@10.4.1(jiti@2.7.0))': @@ -2728,9 +2801,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/template': 7.28.6 '@babel/types': 7.29.0 '@tanstack/router-core': 1.171.13 @@ -2741,7 +2814,7 @@ snapshots: zod: 4.4.3 optionalDependencies: '@tanstack/react-router': 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -2758,9 +2831,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -2971,10 +3044,10 @@ snapshots: '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) '@vitest/coverage-v8@4.1.8(vitest@4.1.8)': dependencies: @@ -2988,7 +3061,7 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/expect@4.1.8': dependencies: @@ -2999,13 +3072,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) '@vitest/pretty-format@4.1.8': dependencies: @@ -3103,7 +3176,7 @@ snapshots: babel-dead-code-elimination@1.0.12: dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/parser': 7.29.2 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 @@ -3118,7 +3191,7 @@ snapshots: dependencies: require-from-string: 2.0.2 - brace-expansion@5.0.5: + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 @@ -3303,34 +3376,34 @@ snapshots: es-toolkit@1.45.1: {} - esbuild@0.28.0: + esbuild@0.28.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.28.0 - '@esbuild/android-arm': 0.28.0 - '@esbuild/android-arm64': 0.28.0 - '@esbuild/android-x64': 0.28.0 - '@esbuild/darwin-arm64': 0.28.0 - '@esbuild/darwin-x64': 0.28.0 - '@esbuild/freebsd-arm64': 0.28.0 - '@esbuild/freebsd-x64': 0.28.0 - '@esbuild/linux-arm': 0.28.0 - '@esbuild/linux-arm64': 0.28.0 - '@esbuild/linux-ia32': 0.28.0 - '@esbuild/linux-loong64': 0.28.0 - '@esbuild/linux-mips64el': 0.28.0 - '@esbuild/linux-ppc64': 0.28.0 - '@esbuild/linux-riscv64': 0.28.0 - '@esbuild/linux-s390x': 0.28.0 - '@esbuild/linux-x64': 0.28.0 - '@esbuild/netbsd-arm64': 0.28.0 - '@esbuild/netbsd-x64': 0.28.0 - '@esbuild/openbsd-arm64': 0.28.0 - '@esbuild/openbsd-x64': 0.28.0 - '@esbuild/openharmony-arm64': 0.28.0 - '@esbuild/sunos-x64': 0.28.0 - '@esbuild/win32-arm64': 0.28.0 - '@esbuild/win32-ia32': 0.28.0 - '@esbuild/win32-x64': 0.28.0 + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 escalade@3.2.0: {} @@ -3338,7 +3411,7 @@ snapshots: eslint-plugin-react-hooks@7.1.1(eslint@10.4.1(jiti@2.7.0)): dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 '@babel/parser': 7.29.2 eslint: 10.4.1(jiti@2.7.0) hermes-parser: 0.25.1 @@ -3696,7 +3769,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.5 + brace-expansion: 5.0.6 ms@2.1.3: {} @@ -3953,7 +4026,7 @@ snapshots: tsx@4.22.4: dependencies: - esbuild: 0.28.0 + esbuild: 0.28.1 optionalDependencies: fsevents: 2.3.3 @@ -4017,7 +4090,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): + vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -4026,16 +4099,16 @@ snapshots: tinyglobby: 0.2.17 optionalDependencies: '@types/node': 25.9.1 - esbuild: 0.28.0 + esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 tsx: 4.22.4 yaml: 2.9.0 - vitest@4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): + vitest@4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.8 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.8 '@vitest/runner': 4.1.8 '@vitest/snapshot': 4.1.8 @@ -4052,7 +4125,7 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.9.1 From 219389f454c79e9c2734e3234116f38fe64e1fe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 28 Jun 2026 14:46:02 +0200 Subject: [PATCH 35/51] chore(server):(deps): bump the version-all group in /packages/server with 2 updates (#50) * chore(server):(deps): bump the version-all group Bumps the version-all group in /packages/server with 2 updates: [@hono/node-server](https://github.com/honojs/node-server) and [hono](https://github.com/honojs/hono). Updates `@hono/node-server` from 2.0.4 to 2.0.5 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v2.0.4...v2.0.5) Updates `hono` from 4.12.25 to 4.12.26 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.25...v4.12.26) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: hono dependency-version: 4.12.26 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- packages/server/package.json | 4 ++-- pnpm-lock.yaml | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index b8b5d82..107fe2e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -15,8 +15,8 @@ "clean": "rm -rf dist" }, "dependencies": { - "@hono/node-server": "^2.0.1", - "hono": "^4.12.25", + "@hono/node-server": "^2.0.5", + "hono": "^4.12.26", "jose": "^6.2.3", "js-yaml": "^4.2.0", "lru-cache": "^11.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed4d0fe..144efb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,11 +53,11 @@ importers: packages/server: dependencies: '@hono/node-server': - specifier: ^2.0.1 - version: 2.0.4(hono@4.12.25) + specifier: ^2.0.5 + version: 2.0.6(hono@4.12.27) hono: - specifier: ^4.12.25 - version: 4.12.25 + specifier: ^4.12.26 + version: 4.12.27 jose: specifier: ^6.2.3 version: 6.2.3 @@ -576,8 +576,8 @@ packages: '@noble/hashes': optional: true - '@hono/node-server@2.0.4': - resolution: {integrity: sha512-Ut3y0dMMPWy6bZ2kVfx25EOVbZlm15dhF4mOsezMlhpNHy+4MkU1qN9Y6lnruYi4wPmFzimGX2X7LF/FwHli4A==} + '@hono/node-server@2.0.6': + resolution: {integrity: sha512-7DeRlKG57JDBNZ5Qj2jwVdgwQy4b0tLubRLl3zCf91/rCf9i7p1V5FtW/yWibm1uUHE493ts9ZXH/7g/LQWl+g==} engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -1496,8 +1496,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.25: - resolution: {integrity: sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==} + hono@4.12.27: + resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -2606,9 +2606,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.4(hono@4.12.25)': + '@hono/node-server@2.0.6(hono@4.12.27)': dependencies: - hono: 4.12.25 + hono: 4.12.27 '@humanfs/core@0.19.1': {} @@ -3543,7 +3543,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.25: {} + hono@4.12.27: {} html-encoding-sniffer@6.0.0: dependencies: From 53359854933f5baba0f4a51932494484d4b1fa1a Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Sat, 4 Jul 2026 01:50:56 +0200 Subject: [PATCH 36/51] refactor(ci): simplify release workflow to manual version control (#51) Replace the conventional-commits-based auto-versioning pipeline with a simpler workflow gated on the version field in package.json. Removes custom scripts (compute-next-version, bump-versions), their tests, and two devDependencies. Release notes are now auto-generated by GitHub. --- .github/workflows/release.yml | 147 +++++----------- package.json | 2 - pnpm-lock.yaml | 137 +-------------- scripts/__tests__/bump-versions.test.mjs | 58 ------- .../__tests__/compute-next-version.test.mjs | 157 ------------------ scripts/bump-versions.mjs | 37 ----- scripts/compute-next-version.mjs | 88 ---------- 7 files changed, 49 insertions(+), 577 deletions(-) delete mode 100644 scripts/__tests__/bump-versions.test.mjs delete mode 100644 scripts/__tests__/compute-next-version.test.mjs delete mode 100644 scripts/bump-versions.mjs delete mode 100644 scripts/compute-next-version.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a51cc24..3f1fef5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,6 +3,7 @@ name: Release on: push: branches: [main] + paths: [package.json] workflow_dispatch: # Never cancel a release mid-flight; queue instead. @@ -13,126 +14,70 @@ concurrency: permissions: {} jobs: - # ── 1. Compute the next version ───────────────────────────────────────────── - # - # Two guards prevent double-releasing: - # a) Commit-message guard: the release workflow pushes a bump commit - # ("chore: release vX.Y.Z") back to main, which re-triggers this - # workflow. The message check exits early without touching the tag. - # b) Tag-existence guard: secondary safety net in case the commit message - # ever differs (e.g. manual push). - version: - name: Compute version + release: + name: Create release runs-on: ubuntu-latest permissions: - contents: read - outputs: - next_version: ${{ steps.compute.outputs.version }} - tag: ${{ steps.compute.outputs.tag }} - skip: ${{ steps.compute.outputs.skip }} + contents: write steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - fetch-depth: 0 # full history required by conventional-recommended-bump - - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - with: - version: 10 - - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 24 - cache: pnpm - - - name: Install dependencies - run: pnpm install --frozen-lockfile + fetch-depth: 0 - - name: Compute next version - id: compute + - name: Check for new version + id: check run: | - # Guard (a): skip the bump commit pushed by this workflow itself. - COMMIT_MSG=$(git log -1 --pretty=%s) - if [[ "$COMMIT_MSG" == "chore: release v"* ]]; then - echo "skip=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - - if ! VERSION=$(node scripts/compute-next-version.mjs) || [[ -z "$VERSION" ]]; then - echo "::error::compute-next-version.mjs failed or returned empty output" - exit 1 - fi + VERSION=$(node -p "require('./package.json').version") TAG="v${VERSION}" - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - echo "tag=${TAG}" >> "$GITHUB_OUTPUT" - - # Guard (b): skip if the tag already exists. if git tag --list "${TAG}" | grep -q "${TAG}"; then - echo "skip=true" >> "$GITHUB_OUTPUT" + echo "skip=true" >> "$GITHUB_OUTPUT" else - echo "skip=false" >> "$GITHUB_OUTPUT" + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + + # Mark pre-release versions (e.g. 1.0.0-rc.2, 2.0.0-beta.1) + if [[ "$VERSION" == *-* ]]; then + echo "prerelease=true" >> "$GITHUB_OUTPUT" + else + echo "prerelease=false" >> "$GITHUB_OUTPUT" + fi fi - # ── 2. Bump versions, update changelog, tag, GitHub Release ───────────────── - release: - name: Create release - runs-on: ubuntu-latest - needs: version - if: needs.version.outputs.skip == 'false' - permissions: - contents: write - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - fetch-depth: 0 - - - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - with: - version: 10 - - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 24 - cache: pnpm - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Bump versions in package.json files - run: node scripts/bump-versions.mjs ${{ needs.version.outputs.next_version }} - - - name: Update CHANGELOG.md - # -p conventionalcommits use the conventionalcommits preset - # -i / -s update CHANGELOG.md in place - # (no -r flag) prepend only the latest release section - run: pnpm dlx conventional-changelog-cli -p conventionalcommits -i CHANGELOG.md -s + - name: Sync sub-package versions + if: steps.check.outputs.skip == 'false' + env: + VERSION: ${{ steps.check.outputs.version }} + run: | + for pkg in packages/server/package.json packages/web/package.json; do + node -e " + const fs = require('fs'); + const p = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); + p.version = process.env.VERSION; + fs.writeFileSync(process.argv[1], JSON.stringify(p, null, 2) + '\n'); + " "$pkg" + done - name: Commit, tag, and push + if: steps.check.outputs.skip == 'false' run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add package.json packages/server/package.json packages/web/package.json CHANGELOG.md - git commit -m "chore: release ${{ needs.version.outputs.tag }}" - # Annotated tags (-a) are required for --follow-tags to include the tag - # in the same push as the bump commit. - git tag -a ${{ needs.version.outputs.tag }} -m "Release ${{ needs.version.outputs.tag }}" - # --follow-tags pushes the commit and the tag in a single round-trip. - git push origin HEAD:main --follow-tags - - name: Extract release notes from CHANGELOG - id: notes - run: | - # Grab everything between the first and second "## [" headings. - BODY=$(awk '/^## \[/{i++} i==1{print} i==2{exit}' CHANGELOG.md) - { - echo "body<> "$GITHUB_OUTPUT" + # Commit only if sub-packages needed syncing + if ! git diff --quiet packages/server/package.json packages/web/package.json; then + git add packages/server/package.json packages/web/package.json + git commit -m "chore: sync package versions to ${{ steps.check.outputs.tag }}" + fi + + git tag -a "${{ steps.check.outputs.tag }}" -m "Release ${{ steps.check.outputs.tag }}" + git push origin HEAD:main --follow-tags - name: Create GitHub Release + if: steps.check.outputs.skip == 'false' uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 with: - tag_name: ${{ needs.version.outputs.tag }} - name: ${{ needs.version.outputs.tag }} - body: ${{ steps.notes.outputs.body }} - + tag_name: ${{ steps.check.outputs.tag }} + name: ${{ steps.check.outputs.tag }} + prerelease: ${{ steps.check.outputs.prerelease }} + generate_release_notes: true diff --git a/package.json b/package.json index 2ae72c7..63bef20 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,6 @@ ] }, "devDependencies": { - "conventional-changelog-conventionalcommits": "^9.3.1", - "conventional-recommended-bump": "^11.2.0", "husky": "^9.1.7", "lint-staged": "^17.0.2", "typescript": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 144efb4..caadfb6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,18 +6,9 @@ settings: catalogs: default: - '@vitest/coverage-v8': - specifier: ^4.1.7 - version: 4.1.8 - eslint: - specifier: ^10.4.0 - version: 10.4.1 typescript: specifier: ^6.0.3 version: 6.0.3 - typescript-eslint: - specifier: ^8.59.4 - version: 8.60.1 vitest: specifier: ^4.1.8 version: 4.1.8 @@ -31,12 +22,6 @@ importers: .: devDependencies: - conventional-changelog-conventionalcommits: - specifier: ^9.3.1 - version: 9.3.1 - conventional-recommended-bump: - specifier: ^11.2.0 - version: 11.2.0 husky: specifier: ^9.1.7 version: 9.1.7 @@ -318,18 +303,6 @@ packages: resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true - '@conventional-changelog/git-client@2.7.0': - resolution: {integrity: sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==} - engines: {node: '>=18'} - peerDependencies: - conventional-commits-filter: ^5.0.0 - conventional-commits-parser: ^6.4.0 - peerDependenciesMeta: - conventional-commits-filter: - optional: true - conventional-commits-parser: - optional: true - '@csstools/color-helpers@6.0.2': resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} engines: {node: '>=20.19.0'} @@ -732,14 +705,6 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@simple-libs/child-process-utils@1.0.2': - resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==} - engines: {node: '>=18'} - - '@simple-libs/stream-utils@1.2.0': - resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} - engines: {node: '>=18'} - '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -1125,9 +1090,6 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} - array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1185,31 +1147,6 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - - conventional-changelog-conventionalcommits@9.3.1: - resolution: {integrity: sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==} - engines: {node: '>=18'} - - conventional-changelog-preset-loader@5.0.0: - resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==} - engines: {node: '>=18'} - - conventional-commits-filter@5.0.0: - resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} - engines: {node: '>=18'} - - conventional-commits-parser@6.4.0: - resolution: {integrity: sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==} - engines: {node: '>=18'} - hasBin: true - - conventional-recommended-bump@11.2.0: - resolution: {integrity: sha512-lqIdmw330QdMBgfL0e6+6q5OMKyIpy4OZNmepit6FS3GldhkG+70drZjuZ0A5NFpze5j85dlYs3GabQXl6sMHw==} - engines: {node: '>=18'} - hasBin: true - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -1336,10 +1273,6 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - electron-to-chromium@1.5.339: resolution: {integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==} @@ -1553,10 +1486,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -1746,10 +1675,6 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - meow@13.2.0: - resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} - engines: {node: '>=18'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -1776,9 +1701,6 @@ packages: node-releases@2.0.37: resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - obug@2.1.3: resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} @@ -2441,15 +2363,6 @@ snapshots: dependencies: css-tree: 3.2.1 - '@conventional-changelog/git-client@2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': - dependencies: - '@simple-libs/child-process-utils': 1.0.2 - '@simple-libs/stream-utils': 1.2.0 - semver: 7.7.4 - optionalDependencies: - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.4.0 - '@csstools/color-helpers@6.0.2': {} '@csstools/css-calc@3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': @@ -2712,12 +2625,6 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@simple-libs/child-process-utils@1.0.2': - dependencies: - '@simple-libs/stream-utils': 1.2.0 - - '@simple-libs/stream-utils@1.2.0': {} - '@standard-schema/spec@1.1.0': {} '@standard-schema/utils@0.3.0': {} @@ -3058,7 +2965,7 @@ snapshots: istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 magicast: 0.5.2 - obug: 2.1.1 + obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 vitest: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) @@ -3164,8 +3071,6 @@ snapshots: aria-query@5.3.2: {} - array-ify@1.0.0: {} - assertion-error@2.0.1: {} ast-v8-to-istanbul@1.0.0: @@ -3224,32 +3129,6 @@ snapshots: clsx@2.1.1: {} - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - - conventional-changelog-conventionalcommits@9.3.1: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-preset-loader@5.0.0: {} - - conventional-commits-filter@5.0.0: {} - - conventional-commits-parser@6.4.0: - dependencies: - '@simple-libs/stream-utils': 1.2.0 - meow: 13.2.0 - - conventional-recommended-bump@11.2.0: - dependencies: - '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - conventional-changelog-preset-loader: 5.0.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.4.0 - meow: 13.2.0 - convert-source-map@2.0.0: {} cookie-es@3.1.1: {} @@ -3360,10 +3239,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - electron-to-chromium@1.5.339: {} emoji-regex@10.6.0: {} @@ -3581,8 +3456,6 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-obj@2.0.0: {} - is-potential-custom-element-name@1.0.1: {} isbot@5.1.38: {} @@ -3751,8 +3624,8 @@ snapshots: magicast@0.5.2: dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 source-map-js: 1.2.1 make-dir@4.0.0: @@ -3761,8 +3634,6 @@ snapshots: mdn-data@2.27.1: {} - meow@13.2.0: {} - mimic-function@5.0.1: {} min-indent@1.0.1: {} @@ -3779,8 +3650,6 @@ snapshots: node-releases@2.0.37: {} - obug@2.1.1: {} - obug@2.1.3: {} onetime@7.0.0: diff --git a/scripts/__tests__/bump-versions.test.mjs b/scripts/__tests__/bump-versions.test.mjs deleted file mode 100644 index f950b65..0000000 --- a/scripts/__tests__/bump-versions.test.mjs +++ /dev/null @@ -1,58 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; - -vi.mock("fs"); - -import { readFileSync, writeFileSync } from "fs"; -import { bumpVersions } from "../bump-versions.mjs"; - -const BASE_PKG = { - name: "dashlight", - version: "0.1.0", - private: true, - scripts: { build: "tsc" }, -}; - -beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(readFileSync).mockReturnValue(JSON.stringify(BASE_PKG)); -}); - -describe("bumpVersions", () => { - it("writes the new version to every provided file", () => { - bumpVersions("0.2.0", ["a/package.json", "b/package.json"]); - - expect(writeFileSync).toHaveBeenCalledTimes(2); - const [fileA, contentA] = vi.mocked(writeFileSync).mock.calls[0]; - const [fileB] = vi.mocked(writeFileSync).mock.calls[1]; - expect(fileA).toBe("a/package.json"); - expect(fileB).toBe("b/package.json"); - expect(JSON.parse(contentA).version).toBe("0.2.0"); - }); - - it("preserves all existing fields", () => { - bumpVersions("1.0.0", ["package.json"]); - - const written = JSON.parse(vi.mocked(writeFileSync).mock.calls[0][1]); - expect(written.name).toBe("dashlight"); - expect(written.private).toBe(true); - expect(written.scripts).toEqual({ build: "tsc" }); - }); - - it("appends a trailing newline", () => { - bumpVersions("0.2.0", ["package.json"]); - - const content = vi.mocked(writeFileSync).mock.calls[0][1]; - expect(content.endsWith("\n")).toBe(true); - }); - - it("uses the three monorepo package.json files by default", () => { - bumpVersions("0.2.0"); - - const writtenPaths = vi.mocked(writeFileSync).mock.calls.map((c) => c[0]); - expect(writtenPaths).toEqual([ - "package.json", - "packages/server/package.json", - "packages/web/package.json", - ]); - }); -}); diff --git a/scripts/__tests__/compute-next-version.test.mjs b/scripts/__tests__/compute-next-version.test.mjs deleted file mode 100644 index 1c73e31..0000000 --- a/scripts/__tests__/compute-next-version.test.mjs +++ /dev/null @@ -1,157 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; - -// vi.hoisted lets us reference mock instances both inside the vi.mock factory -// and in test bodies, which is required when mocking classes. -const mockBump = vi.hoisted(() => vi.fn()); - -vi.mock("conventional-recommended-bump", () => ({ - // Must use a regular function (not arrow) so it can be called with `new`. - Bumper: vi.fn(function () { - return { loadPreset: vi.fn(), bump: mockBump }; - }), -})); -vi.mock("fs"); -vi.mock("child_process"); - -import { Bumper } from "conventional-recommended-bump"; -import { readFileSync } from "fs"; -import { execSync } from "child_process"; -import { - readVersion, - getLastTag, - applyBump, - computeNextVersion, -} from "../compute-next-version.mjs"; - -// ── readVersion ────────────────────────────────────────────────────────────── - -describe("readVersion", () => { - it("returns the version field from package.json", () => { - vi.mocked(readFileSync).mockReturnValue( - JSON.stringify({ name: "dashlight", version: "1.2.3" }), - ); - expect(readVersion()).toBe("1.2.3"); - }); - - it("forwards a custom file path to readFileSync", () => { - vi.mocked(readFileSync).mockReturnValue(JSON.stringify({ version: "0.0.1" })); - readVersion("packages/server/package.json"); - expect(readFileSync).toHaveBeenCalledWith("packages/server/package.json", "utf8"); - }); -}); - -// ── getLastTag ─────────────────────────────────────────────────────────────── - -describe("getLastTag", () => { - it("returns the trimmed tag when git describe succeeds", () => { - vi.mocked(execSync).mockReturnValue(Buffer.from("v1.2.3\n")); - expect(getLastTag()).toBe("v1.2.3"); - }); - - it("returns null when no tags exist (first release)", () => { - vi.mocked(execSync).mockImplementation(() => { - throw new Error("fatal: No names found, cannot describe anything."); - }); - expect(getLastTag()).toBeNull(); - }); -}); - -// ── applyBump ──────────────────────────────────────────────────────────────── - -describe("applyBump", () => { - it("increments major and resets minor + patch", () => { - expect(applyBump("1.2.3", "major")).toBe("2.0.0"); - }); - - it("increments minor and resets patch", () => { - expect(applyBump("1.2.3", "minor")).toBe("1.3.0"); - }); - - it("increments patch only", () => { - expect(applyBump("1.2.3", "patch")).toBe("1.2.4"); - }); - - it("falls back to patch for an unrecognised release type", () => { - expect(applyBump("1.2.3", "unknown")).toBe("1.2.4"); - }); - - // Pre-release versions — always bump the counter, ignore bump type - it("increments rc counter for a patch bump (rc.1 → rc.2)", () => { - expect(applyBump("1.0.0-rc.1", "patch")).toBe("1.0.0-rc.2"); - }); - - it("increments rc counter for a minor bump — does not jump to stable", () => { - expect(applyBump("1.0.0-rc.1", "minor")).toBe("1.0.0-rc.2"); - }); - - it("increments rc counter for a major bump — does not jump to stable", () => { - expect(applyBump("1.0.0-rc.1", "major")).toBe("1.0.0-rc.2"); - }); - - it("handles rc counter larger than 9", () => { - expect(applyBump("1.0.0-rc.9", "patch")).toBe("1.0.0-rc.10"); - }); - - it("preserves the base version digits for pre-release", () => { - expect(applyBump("2.3.4-rc.1", "minor")).toBe("2.3.4-rc.2"); - }); - - it("works with alpha and beta labels", () => { - expect(applyBump("1.0.0-alpha.1", "patch")).toBe("1.0.0-alpha.2"); - expect(applyBump("1.0.0-beta.3", "minor")).toBe("1.0.0-beta.4"); - }); - - it("never produces NaN for a pre-release version", () => { - expect(applyBump("1.0.0-rc.1", "patch")).not.toContain("NaN"); - }); -}); - -// ── computeNextVersion ─────────────────────────────────────────────────────── - -describe("computeNextVersion", () => { - beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(readFileSync).mockReturnValue(JSON.stringify({ version: "0.1.0" })); - mockBump.mockResolvedValue({ releaseType: "patch" }); - }); - - it("returns the declared version unchanged when no tags exist (first release)", async () => { - vi.mocked(execSync).mockImplementation(() => { - throw new Error("No tags"); - }); - expect(await computeNextVersion()).toBe("0.1.0"); - }); - - it("does not instantiate Bumper on the first release", async () => { - vi.mocked(execSync).mockImplementation(() => { - throw new Error("No tags"); - }); - await computeNextVersion(); - expect(Bumper).not.toHaveBeenCalled(); - }); - - it("bumps patch when all commits are fixes", async () => { - vi.mocked(execSync).mockReturnValue(Buffer.from("v0.1.0\n")); - mockBump.mockResolvedValue({ releaseType: "patch" }); - expect(await computeNextVersion()).toBe("0.1.1"); - }); - - it("bumps minor when commits include a feat", async () => { - vi.mocked(execSync).mockReturnValue(Buffer.from("v0.1.0\n")); - mockBump.mockResolvedValue({ releaseType: "minor" }); - expect(await computeNextVersion()).toBe("0.2.0"); - }); - - it("bumps major for a breaking change", async () => { - vi.mocked(execSync).mockReturnValue(Buffer.from("v0.1.0\n")); - mockBump.mockResolvedValue({ releaseType: "major" }); - expect(await computeNextVersion()).toBe("1.0.0"); - }); - - it("increments rc counter when current version is a pre-release (feat commits do not skip to stable)", async () => { - vi.mocked(readFileSync).mockReturnValue(JSON.stringify({ version: "1.0.0-rc.1" })); - vi.mocked(execSync).mockReturnValue(Buffer.from("v1.0.0-rc.1\n")); - mockBump.mockResolvedValue({ releaseType: "minor" }); - expect(await computeNextVersion()).toBe("1.0.0-rc.2"); - }); -}); diff --git a/scripts/bump-versions.mjs b/scripts/bump-versions.mjs deleted file mode 100644 index 8109a02..0000000 --- a/scripts/bump-versions.mjs +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Write a new version string into every package.json in the monorepo. - * - * All packages are versioned in lockstep — one call updates root, - * packages/server, and packages/web simultaneously. - */ - -import { readFileSync, writeFileSync } from "fs"; -import { fileURLToPath } from "url"; - -const DEFAULT_FILES = [ - "package.json", - "packages/server/package.json", - "packages/web/package.json", -]; - -/** - * Update the `version` field in each of the given package.json files. - * Preserves all other fields and appends a trailing newline. - */ -export function bumpVersions(version, files = DEFAULT_FILES) { - for (const file of files) { - const pkg = JSON.parse(readFileSync(file, "utf8")); - pkg.version = version; - writeFileSync(file, JSON.stringify(pkg, null, 2) + "\n"); - } -} - -// CLI entry point. -if (process.argv[1] === fileURLToPath(import.meta.url)) { - const version = process.argv[2]; - if (!version) { - console.error("Usage: node scripts/bump-versions.mjs "); - process.exit(1); - } - bumpVersions(version); -} diff --git a/scripts/compute-next-version.mjs b/scripts/compute-next-version.mjs deleted file mode 100644 index 75221c5..0000000 --- a/scripts/compute-next-version.mjs +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Computes the next semver version from conventional commits. - * - * First-release behaviour (no git tags exist): - * Returns the version currently declared in the root package.json unchanged. - * The release workflow will create that tag (e.g. v0.1.0) on its first run — - * no manual bootstrap step required. - * - * Subsequent releases: - * Reads all commits since the last tag and delegates bump-type detection to - * conventional-recommended-bump (v11 Bumper API) using the - * conventionalcommits preset: - * feat: → minor - * fix: / perf: / … → patch - * BREAKING CHANGE → major - */ - -import { Bumper } from "conventional-recommended-bump"; -import { readFileSync } from "fs"; -import { execSync } from "child_process"; -import { fileURLToPath } from "url"; - -/** Read the `version` field from a package.json file. */ -export function readVersion(file = "package.json") { - return JSON.parse(readFileSync(file, "utf8")).version; -} - -/** - * Return the most recent git tag, or `null` when no tags exist. - * A `null` return value signals "first release". - */ -export function getLastTag() { - try { - return execSync("git describe --tags --abbrev=0", { stdio: "pipe" }) - .toString() - .trim(); - } catch { - return null; - } -} - -/** - * Apply a semver bump type to a version string. - * Any unrecognised type falls back to `patch`. - * - * Pre-release versions (e.g. 1.0.0-rc.1) always bump the pre-release counter - * (→ 1.0.0-rc.2) regardless of the commit-derived release type. Promoting a - * pre-release to a stable version must be done by manually updating - * package.json before the release is triggered. - */ -export function applyBump(version, releaseType) { - const preMatch = version.match(/^(\d+\.\d+\.\d+)-(.+?)\.(\d+)$/); - if (preMatch) { - const [, base, label, num] = preMatch; - return `${base}-${label}.${Number(num) + 1}`; - } - const [major, minor, patch] = version.split(".").map(Number); - if (releaseType === "major") return `${major + 1}.0.0`; - if (releaseType === "minor") return `${major}.${minor + 1}.0`; - return `${major}.${minor}.${patch + 1}`; -} - -/** - * Compute and return the next version string. - * - * When called with no git tags the function returns the version already - * declared in package.json so the release workflow can create the first tag - * automatically without any manual bootstrapping. - */ -export async function computeNextVersion() { - const current = readVersion(); - const lastTag = getLastTag(); - - if (!lastTag) { - // No tags exist yet — treat the declared version as the first release. - return current; - } - - const bumper = new Bumper(process.cwd()); - bumper.loadPreset("conventionalcommits"); - const { releaseType } = await bumper.bump(); - return applyBump(current, releaseType); -} - -// Run only when executed directly (not when imported in tests). -if (process.argv[1] === fileURLToPath(import.meta.url)) { - process.stdout.write(await computeNextVersion()); -} From 18cbcbb4dceaa8fe1088145cc21ec53de2f78366 Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Sat, 4 Jul 2026 01:56:49 +0200 Subject: [PATCH 37/51] release: 1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63bef20..66954e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dashlight", - "version": "1.0.0-rc.2", + "version": "1.0.0", "private": true, "scripts": { "prepare": "husky", From c6f5f1b4ec3002c9c212dbf2a8aac773d63dd772 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Sat, 4 Jul 2026 02:10:33 +0200 Subject: [PATCH 38/51] chore: merge main into develop after v1.0.0 release (#53) * release: 1.0.0 (#52) * docs: add CHANGELOG for 1.0.0-rc.1 * fix: remove paths-ignore in release workflow * feat: replace runtime ca cert vars with build-time EXTRA_CA_CERTS_B64 injection * fix: docker ca & npmrc handling, cert env generation, switch from corepack to npm install (#21) * feat-usability-updates (#22) * feat: add sortable column headers, runs by workflow and unified search placeholder to runs views * feat: run detail rework * feat: add test * feat: github token auth support, optional password protection (#23) * fix: parallel job in run detail dag (#24) * fix: copy public folder in docker web to include favicon (#25) * feat: optional workflow health dashboard section (#26) * feat: workflow health section for dashboard * fix: build activity align agenda * fix: repository healt table cell overflow, card borders * fix: repositories list sorting * fix: applyBump in compute next version script * fix: bump hono to 4.12.18 to patch bodyLimit bypass (#28) * feat: repository runner, workflow health section ui adjustments (#29) * feat: workflow names as subheading for workflow health * feat: repository detail runner section * feat: workflow health section use reponame without owner as default, show only when different owners with same reponame * feat: dependabot config (#30) * fix: remove registries from dependabot config, dockerfile directories * fix: dependebaot dockerfile path * fix: dependebaot dockerfile only path * chore(gha): bump the version-all group across 1 directory with 6 updates (#31) Bumps the version-all group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4.3.1` | `6.0.3` | | [pnpm/action-setup](https://github.com/pnpm/action-setup) | `5.0.0` | `6.0.8` | | [actions/setup-node](https://github.com/actions/setup-node) | `4.4.0` | `6.4.0` | | [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `2.6.2` | `3.0.0` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.12.0` | `4.1.0` | | [docker/build-push-action](https://github.com/docker/build-push-action) | `6.19.2` | `7.2.0` | Updates `actions/checkout` from 4.3.1 to 6.0.3 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/34e114876b0b11c390a56381ad16ebd13914f8d5...df4cb1c069e1874edd31b4311f1884172cec0e10) Updates `pnpm/action-setup` from 5.0.0 to 6.0.8 - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/fc06bc1257f339d1d5d8b3a19a8cae5388b55320...0e279bb959325dab635dd2c09392533439d90093) Updates `actions/setup-node` from 4.4.0 to 6.4.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/49933ea5288caeca8642d1e84afbd3f7d6820020...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e) Updates `softprops/action-gh-release` from 2.6.2 to 3.0.0 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/3bb12739c298aeb8a4eeaf626c5b8d85266b0e65...b4309332981a82ec1c5618f44dd2e27cc8bfbfda) Updates `docker/setup-buildx-action` from 3.12.0 to 4.1.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/8d2750c68a42422c14e847fe6c8ac0403b4cbd6f...d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5) Updates `docker/build-push-action` from 6.19.2 to 7.2.0 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/10e90e3645eae34f1e60eeb005ba3a3d33f178e8...f9f3042f7e2789586610d6e8b85c8f03e5195baf) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: actions/setup-node dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: docker/build-push-action dependency-version: 7.2.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: docker/setup-buildx-action dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: pnpm/action-setup dependency-version: 6.0.8 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: softprops/action-gh-release dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: dependabot grouping for dev dependencies * fix: dependabot root entry for resolve and update catalog from pnpm-workspace.yaml, reduce pr limits * chore(server):(deps): bump the version-all group across 1 directory with 7 updates (#32) * chore(server):(deps): bump the version-all group across 1 directory with 7 updates Bumps the version-all group with 7 updates in the /packages/server directory: | Package | From | To | | --- | --- | --- | | [@hono/node-server](https://github.com/honojs/node-server) | `1.19.14` | `2.0.1` | | [hono](https://github.com/honojs/hono) | `4.12.18` | `4.12.23` | | [jose](https://github.com/panva/jose) | `6.2.2` | `6.2.3` | | [lru-cache](https://github.com/isaacs/node-lru-cache) | `11.3.5` | `11.5.0` | | [undici](https://github.com/nodejs/undici) | `8.1.0` | `8.3.0` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.6.0` | `25.9.1` | | [tsx](https://github.com/privatenumber/tsx) | `4.21.0` | `4.22.3` | Updates `@hono/node-server` from 1.19.14 to 2.0.1 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v1.19.14...v2.0.1) Updates `hono` from 4.12.18 to 4.12.23 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.18...v4.12.23) Updates `jose` from 6.2.2 to 6.2.3 - [Release notes](https://github.com/panva/jose/releases) - [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md) - [Commits](https://github.com/panva/jose/compare/v6.2.2...v6.2.3) Updates `lru-cache` from 11.3.5 to 11.5.0 - [Changelog](https://github.com/isaacs/node-lru-cache/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-lru-cache/compare/v11.3.5...v11.5.0) Updates `undici` from 8.1.0 to 8.3.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.1.0...v8.3.0) Updates `@types/node` from 25.6.0 to 25.9.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `tsx` from 4.21.0 to 4.22.3 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.3) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: "@types/node" dependency-version: 25.9.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: hono dependency-version: 4.12.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: jose dependency-version: 6.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: lru-cache dependency-version: 11.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: tsx dependency-version: 4.22.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: undici dependency-version: 8.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(server): update pnpm.lock, add peer dep rules --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * chore(web):(deps): bump the version-all group across 1 directory with 16 updates (#33) * chore(web):(deps): bump the version-all group across 1 directory with 16 updates Bumps the version-all group with 16 updates in the /packages/web directory: | Package | From | To | | --- | --- | --- | | [@tanstack/query-async-storage-persister](https://github.com/TanStack/query/tree/HEAD/packages/query-async-storage-persister) | `5.99.0` | `5.100.11` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.99.0` | `5.100.11` | | [@tanstack/react-query-persist-client](https://github.com/TanStack/query/tree/HEAD/packages/react-query-persist-client) | `5.99.0` | `5.100.11` | | [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router) | `1.168.22` | `1.170.6` | | [@dagrejs/dagre](https://github.com/dagrejs/dagre) | `1.1.8` | `3.0.0` | | [idb-keyval](https://github.com/jakearchibald/idb-keyval) | `6.2.2` | `6.2.4` | | [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.2.5` | `19.2.6` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.14` | `19.2.15` | | [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.2.5` | `19.2.6` | | [zod](https://github.com/colinhacks/zod) | `4.3.6` | `4.4.3` | | [@tanstack/react-router-devtools](https://github.com/TanStack/router/tree/HEAD/packages/react-router-devtools) | `1.166.13` | `1.167.0` | | [@tanstack/router-vite-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-vite-plugin) | `1.166.37` | `1.167.9` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.1` | `6.0.2` | | [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) | `7.0.1` | `7.1.1` | | [jsdom](https://github.com/jsdom/jsdom) | `29.0.2` | `29.1.1` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.0.8` | `8.0.14` | Updates `@tanstack/query-async-storage-persister` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/query-async-storage-persister/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/query-async-storage-persister@5.100.11/packages/query-async-storage-persister) Updates `@tanstack/react-query` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.100.11/packages/react-query) Updates `@tanstack/react-query-persist-client` from 5.99.0 to 5.100.11 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-persist-client/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-persist-client@5.100.11/packages/react-query-persist-client) Updates `@tanstack/react-router` from 1.168.22 to 1.170.6 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.6/packages/react-router) Updates `@dagrejs/dagre` from 1.1.8 to 3.0.0 - [Release notes](https://github.com/dagrejs/dagre/releases) - [Changelog](https://github.com/dagrejs/dagre/blob/master/changelog.md) - [Commits](https://github.com/dagrejs/dagre/compare/v1.1.8...v3.0.0) Updates `idb-keyval` from 6.2.2 to 6.2.4 - [Changelog](https://github.com/jakearchibald/idb-keyval/blob/main/CHANGELOG.md) - [Commits](https://github.com/jakearchibald/idb-keyval/compare/v6.2.2...v6.2.4) Updates `react` from 19.2.5 to 19.2.6 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react) Updates `@types/react` from 19.2.14 to 19.2.15 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `react-dom` from 19.2.5 to 19.2.6 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react-dom) Updates `zod` from 4.3.6 to 4.4.3 - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v4.3.6...v4.4.3) Updates `@tanstack/react-router-devtools` from 1.166.13 to 1.167.0 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router-devtools/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router-devtools@1.167.0/packages/react-router-devtools) Updates `@tanstack/router-vite-plugin` from 1.166.37 to 1.167.9 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/router-vite-plugin/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/router-vite-plugin@1.167.9/packages/router-vite-plugin) Updates `@vitejs/plugin-react` from 6.0.1 to 6.0.2 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.2/packages/plugin-react) Updates `eslint-plugin-react-hooks` from 7.0.1 to 7.1.1 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/eslint-plugin-react-hooks@7.1.1/packages/eslint-plugin-react-hooks) Updates `jsdom` from 29.0.2 to 29.1.1 - [Release notes](https://github.com/jsdom/jsdom/releases) - [Commits](https://github.com/jsdom/jsdom/compare/v29.0.2...v29.1.1) Updates `vite` from 8.0.8 to 8.0.14 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.0.14/packages/vite) --- updated-dependencies: - dependency-name: "@dagrejs/dagre" dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: "@tanstack/query-async-storage-persister" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-query" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-query-persist-client" dependency-version: 5.100.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-router" dependency-version: 1.170.6 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/react-router-devtools" dependency-version: 1.167.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/router-vite-plugin" dependency-version: 1.167.9 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@types/react" dependency-version: 19.2.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: eslint-plugin-react-hooks dependency-version: 7.1.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: idb-keyval dependency-version: 6.2.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: jsdom dependency-version: 29.1.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: react dependency-version: 19.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: react-dom dependency-version: 19.2.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: vite dependency-version: 8.0.14 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: zod dependency-version: 4.4.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(web): pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * chore(deps):(deps): bump the tooling group across 1 directory with 5 updates (#36) * chore(deps):(deps): bump the tooling group across 1 directory with 5 updates Bumps the tooling group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.4` | `4.1.7` | | [eslint](https://github.com/eslint/eslint) | `10.2.0` | `10.4.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.58.2` | `8.59.4` | | [typescript](https://github.com/microsoft/TypeScript) | `6.0.2` | `6.0.3` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.4` | `4.1.7` | Updates `@vitest/coverage-v8` from 4.1.4 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/coverage-v8) Updates `eslint` from 10.2.0 to 10.4.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.2.0...v10.4.0) Updates `typescript-eslint` from 8.58.2 to 8.59.4 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/typescript-eslint) Updates `typescript` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3) Updates `vitest` from 4.1.4 to 4.1.7 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/vitest) --- updated-dependencies: - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling - dependency-name: eslint dependency-version: 10.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: typescript dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling - dependency-name: typescript-eslint dependency-version: 8.59.4 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: vitest dependency-version: 4.1.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling ... Signed-off-by: dependabot[bot] * chore(web): pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * chore(docker): bump node from 24-alpine to 26-alpine in /packages/server (#34) Bumps node from 24-alpine to 26-alpine. --- updated-dependencies: - dependency-name: node dependency-version: 26-alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(docker): bump node from 24-alpine to 26-alpine in /packages/web (#35) Bumps node from 24-alpine to 26-alpine. --- updated-dependencies: - dependency-name: node dependency-version: 26-alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(docker): bump nginx in /packages/web (#37) Bumps nginx from 1.29.8-alpine to 1.31.1-alpine. --- updated-dependencies: - dependency-name: nginx dependency-version: 1.31.1-alpine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: add docker compose labels * chore(deps):(deps-dev): bump lint-staged in the version-all group (#38) Bumps the version-all group with 1 update: [lint-staged](https://github.com/lint-staged/lint-staged). Updates `lint-staged` from 16.4.0 to 17.0.2 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v16.4.0...v17.0.2) --- updated-dependencies: - dependency-name: lint-staged dependency-version: 17.0.2 dependency-type: direct:development update-type: version-update:semver-major dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(gha): bump the version-all group with 3 updates (#46) Bumps the version-all group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [pnpm/action-setup](https://github.com/pnpm/action-setup) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `actions/checkout` from 6.0.3 to 7.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) Updates `pnpm/action-setup` from 6.0.8 to 6.0.9 - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/0e279bb959325dab635dd2c09392533439d90093...0ebf47130e4866e96fce0953f49152a61190b271) Updates `softprops/action-gh-release` from 3.0.0 to 3.0.1 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/b4309332981a82ec1c5618f44dd2e27cc8bfbfda...718ea10b132b3b2eba29c1007bb80653f286566b) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: pnpm/action-setup dependency-version: 6.0.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: softprops/action-gh-release dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(docker): bump nginx in /packages/web (#45) Bumps nginx from 1.31.1-alpine to 1.31.2-alpine. --- updated-dependencies: - dependency-name: nginx dependency-version: 1.31.2-alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps):(deps): bump hono (#42) Bumps the security-all group with 1 update in the / directory: [hono](https://github.com/honojs/hono). Updates `hono` from 4.12.23 to 4.12.25 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.23...v4.12.25) --- updated-dependencies: - dependency-name: hono dependency-version: 4.12.25 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps):(deps): bump the security-all group across 1 directory with 2 updates (#47) Bumps the security-all group with 2 updates in the / directory: [js-yaml](https://github.com/nodeca/js-yaml) and [undici](https://github.com/nodejs/undici). Updates `js-yaml` from 4.1.1 to 4.2.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.1...4.2.0) Updates `undici` from 8.3.0 to 8.5.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.3.0...v8.5.0) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.2.0 dependency-type: direct:production dependency-group: security-all - dependency-name: undici dependency-version: 8.5.0 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps):(deps): bump vitest from 4.1.7 to 4.1.8 in the tooling group (#39) * chore(deps):(deps): bump vitest from 4.1.7 to 4.1.8 in the tooling group Bumps the tooling group with 1 update: [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). Updates `vitest` from 4.1.7 to 4.1.8 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 4.1.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling ... Signed-off-by: dependabot[bot] * chore(deps): update pnpm-lock --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * chore(web):(deps): bump the version-all group across 1 directory with 4 updates (#44) * chore(web):(deps): bump the version-all group across 1 directory with 4 updates Bumps the version-all group with 4 updates in the /packages/web directory: [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router), [@xyflow/react](https://github.com/xyflow/xyflow/tree/HEAD/packages/react), [@tanstack/router-vite-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-vite-plugin) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). Updates `@tanstack/react-router` from 1.170.11 to 1.170.15 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.15/packages/react-router) Updates `@xyflow/react` from 12.10.2 to 12.11.0 - [Release notes](https://github.com/xyflow/xyflow/releases) - [Changelog](https://github.com/xyflow/xyflow/blob/main/packages/react/CHANGELOG.md) - [Commits](https://github.com/xyflow/xyflow/commits/@xyflow/react@12.11.0/packages/react) Updates `@tanstack/router-vite-plugin` from 1.167.14 to 1.167.18 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/router-vite-plugin/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/router-vite-plugin@1.167.18/packages/router-vite-plugin) Updates `@types/react` from 19.2.16 to 19.2.17 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@tanstack/react-router" dependency-version: 1.170.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@xyflow/react" dependency-version: 12.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: "@tanstack/router-vite-plugin" dependency-version: 1.167.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@types/react" dependency-version: 19.2.17 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore(web) update pnpm-lock --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * chore: update vulnerable brace-expansion, esbuild, @babel/core package versions * chore(server):(deps): bump the version-all group in /packages/server with 2 updates (#50) * chore(server):(deps): bump the version-all group Bumps the version-all group in /packages/server with 2 updates: [@hono/node-server](https://github.com/honojs/node-server) and [hono](https://github.com/honojs/hono). Updates `@hono/node-server` from 2.0.4 to 2.0.5 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v2.0.4...v2.0.5) Updates `hono` from 4.12.25 to 4.12.26 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.25...v4.12.26) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: hono dependency-version: 4.12.26 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein * refactor(ci): simplify release workflow to manual version control (#51) Replace the conventional-commits-based auto-versioning pipeline with a simpler workflow gated on the version field in package.json. Removes custom scripts (compute-next-version, bump-versions), their tests, and two devDependencies. Release notes are now auto-generated by GitHub. * release: 1.0.0 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: sync package versions to v1.0.0 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- packages/server/package.json | 2 +- packages/web/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 107fe2e..9f94ae7 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@dashlight/server", - "version": "1.0.0-rc.2", + "version": "1.0.0", "private": true, "type": "module", "main": "dist/index.js", diff --git a/packages/web/package.json b/packages/web/package.json index 25e988f..d3a626b 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,6 +1,6 @@ { "name": "@dashlight/web", - "version": "1.0.0-rc.2", + "version": "1.0.0", "private": true, "type": "module", "scripts": { From 8d491dfd7aa0244eadd7fde7e0378d033acc9e13 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:02:57 +0200 Subject: [PATCH 39/51] fix: pagination loop for GitHub api requests, web ui workflow truncation (#58) * fix: pagination for server-side repo fetching, remove frontend truncation for repos * release: 1.0.1 --- package.json | 2 +- packages/server/src/routes/repos.test.ts | 106 +++++++++++++++++- packages/server/src/routes/repos.ts | 32 +++++- .../web/src/components/ui/TruncatingTitle.tsx | 1 - packages/web/src/routes/_app/index.tsx | 2 +- 5 files changed, 135 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 66954e1..d7706ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dashlight", - "version": "1.0.0", + "version": "1.0.1", "private": true, "scripts": { "prepare": "husky", diff --git a/packages/server/src/routes/repos.test.ts b/packages/server/src/routes/repos.test.ts index dd73c46..d964a64 100644 --- a/packages/server/src/routes/repos.test.ts +++ b/packages/server/src/routes/repos.test.ts @@ -37,7 +37,7 @@ vi.mock("../lib/logger.js", () => ({ import { githubFetch, GitHubNotFoundError, GitHubApiError } from "../lib/github.js" import { cacheGet, cacheSet } from "../lib/cache.js" -import reposRouter from "./repos.js" +import reposRouter, { fetchAllPages } from "./repos.js" const mockGithubFetch = vi.mocked(githubFetch) const mockCacheGet = vi.mocked(cacheGet) @@ -59,6 +59,11 @@ function githubResult(data: unknown) { return { data, rateLimitRemaining: 100, rateLimitReset: null, status: 200, etag: null, grantedScopes: null } } +/** Create an array of N repo objects for pagination tests. */ +function makeRepos(count: number, prefix = "org/repo") { + return Array.from({ length: count }, (_, i) => repoData(`${prefix}-${i}`)) +} + beforeEach(() => { vi.clearAllMocks() mockCacheGet.mockReturnValue(undefined) @@ -71,10 +76,73 @@ afterEach(() => { delete process.env["GITHUB_ORG"] }) +// ── fetchAllPages (unit) ───────────────────────────────────────────────────── + +describe("fetchAllPages", () => { + it("returns all items from a single page when count < perPage", async () => { + const repos = makeRepos(50) + mockGithubFetch.mockResolvedValueOnce(githubResult(repos)) + + const result = await fetchAllPages("tok", "/user/repos?sort=pushed", 100) + + expect(result).toHaveLength(50) + expect(mockGithubFetch).toHaveBeenCalledTimes(1) + expect(mockGithubFetch).toHaveBeenCalledWith("tok", "/user/repos?sort=pushed&per_page=100&page=1") + }) + + it("fetches multiple pages until a partial page is returned", async () => { + const page1 = makeRepos(100, "org/a") + const page2 = makeRepos(100, "org/b") + const page3 = makeRepos(30, "org/c") // partial → last page + mockGithubFetch + .mockResolvedValueOnce(githubResult(page1)) + .mockResolvedValueOnce(githubResult(page2)) + .mockResolvedValueOnce(githubResult(page3)) + + const result = await fetchAllPages("tok", "/orgs/myorg/repos?sort=pushed", 100) + + expect(result).toHaveLength(230) + expect(mockGithubFetch).toHaveBeenCalledTimes(3) + expect(mockGithubFetch).toHaveBeenCalledWith("tok", "/orgs/myorg/repos?sort=pushed&per_page=100&page=1") + expect(mockGithubFetch).toHaveBeenCalledWith("tok", "/orgs/myorg/repos?sort=pushed&per_page=100&page=2") + expect(mockGithubFetch).toHaveBeenCalledWith("tok", "/orgs/myorg/repos?sort=pushed&per_page=100&page=3") + }) + + it("stops after an empty page", async () => { + const page1 = makeRepos(100) + mockGithubFetch + .mockResolvedValueOnce(githubResult(page1)) + .mockResolvedValueOnce(githubResult([])) + + const result = await fetchAllPages("tok", "/user/repos?sort=pushed", 100) + + expect(result).toHaveLength(100) + expect(mockGithubFetch).toHaveBeenCalledTimes(2) + }) + + it("respects the maxPages safety cap", async () => { + // Always return a full page to simulate infinite pagination + mockGithubFetch.mockResolvedValue(githubResult(makeRepos(100))) + + const result = await fetchAllPages("tok", "/user/repos?sort=pushed", 100, 3) + + expect(result).toHaveLength(300) + expect(mockGithubFetch).toHaveBeenCalledTimes(3) + }) + + it("appends query params correctly when basePath has no existing params", async () => { + mockGithubFetch.mockResolvedValueOnce(githubResult([])) + + await fetchAllPages("tok", "/user/repos", 100) + + expect(mockGithubFetch).toHaveBeenCalledWith("tok", "/user/repos?per_page=100&page=1") + }) +}) + // ── Default mode (no env vars) ──────────────────────────────────────────────── describe("GET /api/repos — default mode (no env vars)", () => { - it("fetches /user/repos and returns data", async () => { + it("fetches /user/repos with pagination and returns data", async () => { const data = [repoData("owner/repo1"), repoData("owner/repo2")] mockGithubFetch.mockResolvedValueOnce(githubResult(data)) @@ -105,6 +173,21 @@ describe("GET /api/repos — default mode (no env vars)", () => { expect(mockCacheSet).toHaveBeenCalledWith(expect.any(String), data, expect.any(Number)) }) + + it("paginates through all user repos", async () => { + const page1 = makeRepos(100, "owner/a") + const page2 = makeRepos(20, "owner/b") + mockGithubFetch + .mockResolvedValueOnce(githubResult(page1)) + .mockResolvedValueOnce(githubResult(page2)) + + const res = await makeApp().request("/api/repos") + + expect(res.status).toBe(200) + const body = await res.json() as unknown[] + expect(body).toHaveLength(120) + expect(mockGithubFetch).toHaveBeenCalledTimes(2) + }) }) // ── GITHUB_ORG mode ──────────────────────────────────────────────────────────── @@ -112,7 +195,7 @@ describe("GET /api/repos — default mode (no env vars)", () => { describe("GET /api/repos — GITHUB_ORG mode", () => { beforeEach(() => { process.env["GITHUB_ORG"] = "myorg" }) - it("fetches /orgs/myorg/repos and returns data", async () => { + it("fetches /orgs/myorg/repos with pagination and returns data", async () => { const data = [repoData("myorg/alpha"), repoData("myorg/beta")] mockGithubFetch.mockResolvedValueOnce(githubResult(data)) @@ -147,6 +230,23 @@ describe("GET /api/repos — GITHUB_ORG mode", () => { // Falls through to default mode — must fetch /user/repos expect(mockGithubFetch).toHaveBeenCalledWith("tok", expect.stringContaining("/user/repos")) }) + + it("paginates through all org repos", async () => { + const page1 = makeRepos(100, "myorg/a") + const page2 = makeRepos(100, "myorg/b") + const page3 = makeRepos(50, "myorg/c") + mockGithubFetch + .mockResolvedValueOnce(githubResult(page1)) + .mockResolvedValueOnce(githubResult(page2)) + .mockResolvedValueOnce(githubResult(page3)) + + const res = await makeApp().request("/api/repos") + + expect(res.status).toBe(200) + const body = await res.json() as unknown[] + expect(body).toHaveLength(250) + expect(mockGithubFetch).toHaveBeenCalledTimes(3) + }) }) // ── GITHUB_REPOS mode ────────────────────────────────────────────────────────── diff --git a/packages/server/src/routes/repos.ts b/packages/server/src/routes/repos.ts index eeca606..4940df0 100644 --- a/packages/server/src/routes/repos.ts +++ b/packages/server/src/routes/repos.ts @@ -9,6 +9,9 @@ const repos = new Hono() repos.use("/*", authMiddleware) +/** Max pages to fetch when paginating (safety cap: 100 pages × 100 per_page = 10 000 repos). */ +const MAX_PAGES = 100 + function getRepoFilter(): string[] | null { const raw = process.env["GITHUB_REPOS"] if (!raw?.trim()) return null @@ -20,6 +23,31 @@ function getOrgFilter(): string | null { return raw?.trim() || null } +/** + * Fetch all pages of a GitHub list endpoint that returns an array. + * Stops when a page returns fewer items than per_page (last page). + */ +export async function fetchAllPages( + token: string, + basePath: string, + perPage = 100, + maxPages = MAX_PAGES, +): Promise { + const all: T[] = [] + const separator = basePath.includes("?") ? "&" : "?" + + for (let page = 1; page <= maxPages; page++) { + const { data } = await githubFetch( + token, + `${basePath}${separator}per_page=${perPage}&page=${page}`, + ) + all.push(...data) + if (data.length < perPage) break + } + + return all +} + /** * GET /api/repos * Returns repositories scoped by env config: @@ -76,7 +104,7 @@ repos.get("/", async (c) => { return c.json(cached) } c.header("X-Cache", "MISS") - const { data } = await githubFetch(token, `/orgs/${orgFilter}/repos?sort=pushed&per_page=100`) + const data = await fetchAllPages(token, `/orgs/${orgFilter}/repos?sort=pushed`) cacheSet(key, data, TTL.repos) return c.json(data) } @@ -89,7 +117,7 @@ repos.get("/", async (c) => { return c.json(cached) } c.header("X-Cache", "MISS") - const { data } = await githubFetch(token, "/user/repos?sort=pushed&per_page=100") + const data = await fetchAllPages(token, "/user/repos?sort=pushed") cacheSet(key, data, TTL.repos) return c.json(data) } catch (err) { diff --git a/packages/web/src/components/ui/TruncatingTitle.tsx b/packages/web/src/components/ui/TruncatingTitle.tsx index 90106f0..b0b46ff 100644 --- a/packages/web/src/components/ui/TruncatingTitle.tsx +++ b/packages/web/src/components/ui/TruncatingTitle.tsx @@ -67,7 +67,6 @@ export function TruncatingTitle({ } } - // eslint-disable-next-line react-hooks/set-state-in-effect -- useLayoutEffect+setState is the recommended React pattern for pre-paint DOM measurement setVisibleCount(count) }, [prefix, items, _isOverflowing, sizeTrigger]) diff --git a/packages/web/src/routes/_app/index.tsx b/packages/web/src/routes/_app/index.tsx index d66862f..987c1d7 100644 --- a/packages/web/src/routes/_app/index.tsx +++ b/packages/web/src/routes/_app/index.tsx @@ -28,7 +28,7 @@ function Dashboard() { staleTime: Infinity, }) - const repoList = (repos ?? []).slice(0, 10) + const repoList = repos ?? [] // useQueries handles a dynamic-length array without violating Rules of Hooks const runResults = useQueries({ From 5f677094269c1c84b7a60673c58108a9089524ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 00:03:37 +0200 Subject: [PATCH 40/51] chore(gha): bump the version-all group with 2 updates (#57) Bumps the version-all group with 2 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) and [docker/build-push-action](https://github.com/docker/build-push-action). Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c) Updates `docker/build-push-action` from 7.2.0 to 7.3.0 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/f9f3042f7e2789586610d6e8b85c8f03e5195baf...53b7df96c91f9c12dcc8a07bcb9ccacbed38856a) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: docker/build-push-action dependency-version: 7.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index ba102f0..ca930a1 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -109,10 +109,10 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - name: Build ${{ matrix.image }} - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 with: context: . file: ${{ matrix.dockerfile }} From 11d5aedd8c2a12c995c3fb353528cd0a1cf39eb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 00:14:22 +0200 Subject: [PATCH 41/51] chore(web):(deps): bump the version-all group in /packages/web with 5 updates (#56) * chore(web):(deps): bump the version-all group Bumps the version-all group in /packages/web with 5 updates: | Package | From | To | | --- | --- | --- | | [@tanstack/query-async-storage-persister](https://github.com/TanStack/query/tree/HEAD/packages/query-async-storage-persister) | `5.101.0` | `5.101.2` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.0` | `5.101.2` | | [@tanstack/react-query-persist-client](https://github.com/TanStack/query/tree/HEAD/packages/react-query-persist-client) | `5.101.0` | `5.101.2` | | [@xyflow/react](https://github.com/xyflow/xyflow/tree/HEAD/packages/react) | `12.11.0` | `12.11.1` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.2` | `6.0.3` | Updates `@tanstack/query-async-storage-persister` from 5.101.0 to 5.101.2 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/query-async-storage-persister/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/query-async-storage-persister@5.101.2/packages/query-async-storage-persister) Updates `@tanstack/react-query` from 5.101.0 to 5.101.2 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.2/packages/react-query) Updates `@tanstack/react-query-persist-client` from 5.101.0 to 5.101.2 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-persist-client/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-persist-client@5.101.2/packages/react-query-persist-client) Updates `@xyflow/react` from 12.11.0 to 12.11.1 - [Release notes](https://github.com/xyflow/xyflow/releases) - [Changelog](https://github.com/xyflow/xyflow/blob/main/packages/react/CHANGELOG.md) - [Commits](https://github.com/xyflow/xyflow/commits/@xyflow/react@12.11.1/packages/react) Updates `@vitejs/plugin-react` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.3/packages/plugin-react) --- updated-dependencies: - dependency-name: "@tanstack/query-async-storage-persister" dependency-version: 5.101.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/react-query" dependency-version: 5.101.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/react-query-persist-client" dependency-version: 5.101.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@xyflow/react" dependency-version: 12.11.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- packages/web/package.json | 10 ++-- pnpm-lock.yaml | 102 ++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/packages/web/package.json b/packages/web/package.json index d3a626b..d37ad0f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -14,11 +14,11 @@ "clean": "rm -rf dist" }, "dependencies": { - "@tanstack/query-async-storage-persister": "^5.100.11", - "@tanstack/react-query": "^5.100.11", - "@tanstack/react-query-persist-client": "^5.100.11", + "@tanstack/query-async-storage-persister": "^5.101.2", + "@tanstack/react-query": "^5.101.2", + "@tanstack/react-query-persist-client": "^5.101.2", "@tanstack/react-router": "^1.170.15", - "@xyflow/react": "^12.11.0", + "@xyflow/react": "^12.11.1", "@dagrejs/dagre": "^3.0.0", "idb-keyval": "^6.2.4", "react": "^19.2.6", @@ -33,7 +33,7 @@ "@testing-library/react": "^16.3.2", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.2", + "@vitejs/plugin-react": "^6.0.3", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", "eslint-plugin-react-hooks": "^7.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index caadfb6..1b7d25e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,9 +6,18 @@ settings: catalogs: default: + '@vitest/coverage-v8': + specifier: ^4.1.7 + version: 4.1.8 + eslint: + specifier: ^10.4.0 + version: 10.4.1 typescript: specifier: ^6.0.3 version: 6.0.3 + typescript-eslint: + specifier: ^8.59.4 + version: 8.60.1 vitest: specifier: ^4.1.8 version: 4.1.8 @@ -87,20 +96,20 @@ importers: specifier: ^3.0.0 version: 3.0.0 '@tanstack/query-async-storage-persister': - specifier: ^5.100.11 - version: 5.101.0 + specifier: ^5.101.2 + version: 5.101.2 '@tanstack/react-query': - specifier: ^5.100.11 - version: 5.101.0(react@19.2.7) + specifier: ^5.101.2 + version: 5.101.2(react@19.2.7) '@tanstack/react-query-persist-client': - specifier: ^5.100.11 - version: 5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7) + specifier: ^5.101.2 + version: 5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7) '@tanstack/react-router': specifier: ^1.170.15 version: 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@xyflow/react': - specifier: ^12.11.0 - version: 12.11.0(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^12.11.1 + version: 12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) idb-keyval: specifier: ^6.2.4 version: 6.2.5 @@ -136,8 +145,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': - specifier: ^6.0.2 - version: 6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^6.0.3 + version: 6.0.3(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.8(vitest@4.1.8) @@ -715,23 +724,23 @@ packages: resolution: {integrity: sha512-79pf/RkhteYZTRgcR4F9kbk84P2N8rugQJswxfIqovlbRiT3yI7eBE+5QorIrZaOKktsgzRlXh1l/du/xpl4iA==} engines: {node: '>=20.19'} - '@tanstack/query-async-storage-persister@5.101.0': - resolution: {integrity: sha512-8Y8pwMVPh4kqU9m+MhbDYBuub+i5T2M9P/0+Ae3KccX1BwMIp6AdFAx3zDgLoZcEVI830mbJYf0sjAgsawCWVw==} + '@tanstack/query-async-storage-persister@5.101.2': + resolution: {integrity: sha512-jf7zvVKZ5q2j/xuhbTIBUpw5xt6cw/ioOFQquxK7fRY0AmMQP8A0JVMOgYoeQLA4PKdeT7RxsuLAF0Lft9oJ8Q==} - '@tanstack/query-core@5.101.0': - resolution: {integrity: sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==} + '@tanstack/query-core@5.101.2': + resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} - '@tanstack/query-persist-client-core@5.101.0': - resolution: {integrity: sha512-LH99WepGVLwlLfuOcQcPK7f3Xg/Gf+xlMMIj9xWu/8oQ3egnDzjr+a4HvEmi6PGob5SmGXvmDKZaH5+In9dzjw==} + '@tanstack/query-persist-client-core@5.101.2': + resolution: {integrity: sha512-rgMsbvBVpSPDUsprC9FYxojdG0Q1LH6yq1i3DXz2aps4VEqv2l4Msj3YDqIifU3xkl/DrYe9YWntZAJLrM6xTg==} - '@tanstack/react-query-persist-client@5.101.0': - resolution: {integrity: sha512-AUcdBgz8V6sM9axzdqkVmWjYSOETkhr6yAZSBnEFyZT2jo6vkFq3UrpRuxGs6fmhKMWv8FA+ZJGcbaKPaoAElQ==} + '@tanstack/react-query-persist-client@5.101.2': + resolution: {integrity: sha512-19UpaRtf0lvB2QAJ2MoixxtGf3osMOd508g99EsttUj4+3eLs+ulnNgYjB7AkQMHrRlcbVXqpVNqWkB4a7g8Zw==} peerDependencies: - '@tanstack/react-query': ^5.101.0 + '@tanstack/react-query': ^5.101.2 react: ^18 || ^19 - '@tanstack/react-query@5.101.0': - resolution: {integrity: sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==} + '@tanstack/react-query@5.101.2': + resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} peerDependencies: react: ^18 || ^19 @@ -891,9 +900,6 @@ packages: '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} @@ -976,8 +982,8 @@ packages: resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@6.0.2': - resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==} + '@vitejs/plugin-react@6.0.3': + resolution: {integrity: sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 @@ -1027,8 +1033,8 @@ packages: '@vitest/utils@4.1.8': resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} - '@xyflow/react@12.11.0': - resolution: {integrity: sha512-na4IO33FSs2OS72hASgZDmTYwFAkef7Z74uBUVrong3ARmQQHfnRUVaCFn1kTt5LbS6pK03TbYjCPGLjLFfziA==} + '@xyflow/react@12.11.2': + resolution: {integrity: sha512-eLAlDWJfWnQEhJwGMjlWdAXO9eYllKpliUmPQlAmOLxz6mExXuzMVDUKLMquixgkrtmMFFtug3jGKmYYld12cA==} peerDependencies: '@types/react': '>=17' '@types/react-dom': '>=17' @@ -1040,8 +1046,8 @@ packages: '@types/react-dom': optional: true - '@xyflow/system@0.0.77': - resolution: {integrity: sha512-qCDCMCQAAgUu8yHnhloHG9F5mwPX5E+Wl8McpYIOPSSXfzFJJoZcwOcsDiAjitVKIg2de1WmJbCHfpcvxprsgg==} + '@xyflow/system@0.0.79': + resolution: {integrity: sha512-czLyOh91NF0hIzbNzwi8I6GlqG23BHh2435OddfI6uiaLH3xdrdygO93gqgH1Bv9mhy8XPFQJOBn1FTq4LvEWA==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -2631,26 +2637,26 @@ snapshots: '@tanstack/history@1.162.0': {} - '@tanstack/query-async-storage-persister@5.101.0': + '@tanstack/query-async-storage-persister@5.101.2': dependencies: - '@tanstack/query-core': 5.101.0 - '@tanstack/query-persist-client-core': 5.101.0 + '@tanstack/query-core': 5.101.2 + '@tanstack/query-persist-client-core': 5.101.2 - '@tanstack/query-core@5.101.0': {} + '@tanstack/query-core@5.101.2': {} - '@tanstack/query-persist-client-core@5.101.0': + '@tanstack/query-persist-client-core@5.101.2': dependencies: - '@tanstack/query-core': 5.101.0 + '@tanstack/query-core': 5.101.2 - '@tanstack/react-query-persist-client@5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7)': + '@tanstack/react-query-persist-client@5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/query-persist-client-core': 5.101.0 - '@tanstack/react-query': 5.101.0(react@19.2.7) + '@tanstack/query-persist-client-core': 5.101.2 + '@tanstack/react-query': 5.101.2(react@19.2.7) react: 19.2.7 - '@tanstack/react-query@5.101.0(react@19.2.7)': + '@tanstack/react-query@5.101.2(react@19.2.7)': dependencies: - '@tanstack/query-core': 5.101.0 + '@tanstack/query-core': 5.101.2 react: 19.2.7 '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': @@ -2838,8 +2844,6 @@ snapshots: '@types/esrecurse@4.3.1': {} - '@types/estree@1.0.8': {} - '@types/estree@1.0.9': {} '@types/js-yaml@4.0.9': {} @@ -2951,7 +2955,7 @@ snapshots: '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.3(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) @@ -3011,9 +3015,9 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@xyflow/react@12.11.0(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@xyflow/react@12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@xyflow/system': 0.0.77 + '@xyflow/system': 0.0.79 classcat: 5.0.5 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -3024,7 +3028,7 @@ snapshots: transitivePeerDependencies: - immer - '@xyflow/system@0.0.77': + '@xyflow/system@0.0.79': dependencies: '@types/d3-drag': 3.0.7 '@types/d3-interpolate': 3.0.4 @@ -3298,7 +3302,7 @@ snapshots: eslint-scope@9.1.2: dependencies: '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3317,7 +3321,7 @@ snapshots: '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 ajv: 6.14.0 cross-spawn: 7.0.6 debug: 4.4.3 From 80e656e0f2165ceca602b300180c366020eb9327 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:29:31 +0200 Subject: [PATCH 42/51] chore(deps):(deps): bump the tooling group across 1 directory with 4 updates (#54) * chore(deps):(deps): bump the tooling group across 1 directory with 4 updates Bumps the tooling group with 4 updates in the / directory: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [eslint](https://github.com/eslint/eslint), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). Updates `@vitest/coverage-v8` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/coverage-v8) Updates `eslint` from 10.4.1 to 10.5.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.4.1...v10.5.0) Updates `typescript-eslint` from 8.60.1 to 8.62.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.62.0/packages/typescript-eslint) Updates `vitest` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/vitest) --- updated-dependencies: - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling - dependency-name: eslint dependency-version: 10.6.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: typescript-eslint dependency-version: 8.62.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: tooling - dependency-name: vitest dependency-version: 4.1.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: tooling ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- pnpm-lock.yaml | 328 ++++++++++++++++++++++---------------------- pnpm-workspace.yaml | 8 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b7d25e..ea3c7d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,20 +7,20 @@ settings: catalogs: default: '@vitest/coverage-v8': - specifier: ^4.1.7 - version: 4.1.8 + specifier: ^4.1.9 + version: 4.1.10 eslint: - specifier: ^10.4.0 - version: 10.4.1 + specifier: ^10.5.0 + version: 10.7.0 typescript: specifier: ^6.0.3 version: 6.0.3 typescript-eslint: - specifier: ^8.59.4 - version: 8.60.1 + specifier: ^8.62.0 + version: 8.63.0 vitest: - specifier: ^4.1.8 - version: 4.1.8 + specifier: ^4.1.9 + version: 4.1.10 overrides: brace-expansion: ^5.0.6 @@ -42,7 +42,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/server: dependencies: @@ -70,13 +70,13 @@ importers: version: 4.0.9 '@types/node': specifier: ^25.9.1 - version: 25.9.1 + version: 25.9.5 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) eslint: specifier: 'catalog:' - version: 10.4.1(jiti@2.7.0) + version: 10.7.0(jiti@2.7.0) tsx: specifier: ^4.22.3 version: 4.22.4 @@ -85,10 +85,10 @@ importers: version: 6.0.3 typescript-eslint: specifier: 'catalog:' - version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages/web: dependencies: @@ -131,7 +131,7 @@ importers: version: 1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/router-vite-plugin': specifier: ^1.167.18 - version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -146,16 +146,16 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^6.0.3 - version: 6.0.3(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 6.0.3(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) eslint: specifier: 'catalog:' - version: 10.4.1(jiti@2.7.0) + version: 10.7.0(jiti@2.7.0) eslint-plugin-react-hooks: specifier: ^7.1.1 - version: 7.1.1(eslint@10.4.1(jiti@2.7.0)) + version: 7.1.1(eslint@10.7.0(jiti@2.7.0)) jsdom: specifier: ^29.1.1 version: 29.1.1 @@ -164,13 +164,13 @@ importers: version: 6.0.3 typescript-eslint: specifier: 'catalog:' - version: 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vite: specifier: ^8.0.14 - version: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + version: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) packages: @@ -909,8 +909,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.9.1': - resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} + '@types/node@25.9.5': + resolution: {integrity: sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -923,63 +923,63 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@typescript-eslint/eslint-plugin@8.60.1': - resolution: {integrity: sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==} + '@typescript-eslint/eslint-plugin@8.63.0': + resolution: {integrity: sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.60.1 + '@typescript-eslint/parser': ^8.63.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.60.1': - resolution: {integrity: sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==} + '@typescript-eslint/parser@8.63.0': + resolution: {integrity: sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==} 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.60.1': - resolution: {integrity: sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==} + '@typescript-eslint/project-service@8.63.0': + resolution: {integrity: sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.60.1': - resolution: {integrity: sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==} + '@typescript-eslint/scope-manager@8.63.0': + resolution: {integrity: sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.60.1': - resolution: {integrity: sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==} + '@typescript-eslint/tsconfig-utils@8.63.0': + resolution: {integrity: sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.60.1': - resolution: {integrity: sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==} + '@typescript-eslint/type-utils@8.63.0': + resolution: {integrity: sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==} 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.60.1': - resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} + '@typescript-eslint/types@8.63.0': + resolution: {integrity: sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.60.1': - resolution: {integrity: sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==} + '@typescript-eslint/typescript-estree@8.63.0': + resolution: {integrity: sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.60.1': - resolution: {integrity: sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==} + '@typescript-eslint/utils@8.63.0': + resolution: {integrity: sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==} 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.60.1': - resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} + '@typescript-eslint/visitor-keys@8.63.0': + resolution: {integrity: sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@6.0.3': @@ -995,20 +995,20 @@ packages: babel-plugin-react-compiler: optional: true - '@vitest/coverage-v8@4.1.8': - resolution: {integrity: sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw==} + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} peerDependencies: - '@vitest/browser': 4.1.8 - vitest: 4.1.8 + '@vitest/browser': 4.1.10 + vitest: 4.1.10 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.8': - resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@4.1.8': - resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1018,20 +1018,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.8': - resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@4.1.8': - resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@4.1.8': - resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - '@vitest/spy@4.1.8': - resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - '@vitest/utils@4.1.8': - resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@xyflow/react@12.11.2': resolution: {integrity: sha512-eLAlDWJfWnQEhJwGMjlWdAXO9eYllKpliUmPQlAmOLxz6mExXuzMVDUKLMquixgkrtmMFFtug3jGKmYYld12cA==} @@ -1330,8 +1330,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.4.1: - resolution: {integrity: sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==} + eslint@10.7.0: + resolution: {integrity: sha512-GVTD7s1vdIl6UYvAfriOPeY1Df8LIZjfofLvHwde+erDHGGuHyuM6xoxRxmHiebhYuD2p1vN4wWh0XzPARSGDQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1976,8 +1976,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.60.1: - resolution: {integrity: sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==} + typescript-eslint@8.63.0: + resolution: {integrity: sha512-xgwXyzG4sK9ALkBxbyGkTMMOS+imnW65iPhxCQMK83KhxyoDNW7l+IDqEf9vMdoUidHpOoS967RCq4eMiTexwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -2063,20 +2063,20 @@ packages: yaml: optional: true - vitest@4.1.8: - resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} 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.1.8 - '@vitest/browser-preview': 4.1.8 - '@vitest/browser-webdriverio': 4.1.8 - '@vitest/coverage-istanbul': 4.1.8 - '@vitest/coverage-v8': 4.1.8 - '@vitest/ui': 4.1.8 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2493,9 +2493,9 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.4.1(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.7.0(jiti@2.7.0))': dependencies: - eslint: 10.4.1(jiti@2.7.0) + eslint: 10.7.0(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2714,7 +2714,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/template': 7.28.6 @@ -2727,7 +2727,7 @@ snapshots: zod: 4.4.3 optionalDependencies: '@tanstack/react-router': 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) transitivePeerDependencies: - supports-color @@ -2744,9 +2744,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) transitivePeerDependencies: - '@rsbuild/core' - '@tanstack/react-router' @@ -2850,7 +2850,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.9.1': + '@types/node@25.9.5': dependencies: undici-types: 7.24.6 @@ -2864,15 +2864,15 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@typescript-eslint/eslint-plugin@8.60.1(@typescript-eslint/parser@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': + '@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)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.60.1 - '@typescript-eslint/type-utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.60.1 - eslint: 10.4.1(jiti@2.7.0) + '@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.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) @@ -2880,56 +2880,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.60.1(eslint@10.4.1(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)': dependencies: - '@typescript-eslint/scope-manager': 8.60.1 - '@typescript-eslint/types': 8.60.1 - '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.60.1 + '@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 debug: 4.4.3 - eslint: 10.4.1(jiti@2.7.0) + eslint: 10.7.0(jiti@2.7.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.60.1(typescript@6.0.3)': + '@typescript-eslint/project-service@8.63.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@6.0.3) - '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/tsconfig-utils': 8.63.0(typescript@6.0.3) + '@typescript-eslint/types': 8.63.0 debug: 4.4.3 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.60.1': + '@typescript-eslint/scope-manager@8.63.0': dependencies: - '@typescript-eslint/types': 8.60.1 - '@typescript-eslint/visitor-keys': 8.60.1 + '@typescript-eslint/types': 8.63.0 + '@typescript-eslint/visitor-keys': 8.63.0 - '@typescript-eslint/tsconfig-utils@8.60.1(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.63.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.60.1 - '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) + '@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) debug: 4.4.3 - eslint: 10.4.1(jiti@2.7.0) + eslint: 10.7.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.60.1': {} + '@typescript-eslint/types@8.63.0': {} - '@typescript-eslint/typescript-estree@8.60.1(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.63.0(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.60.1(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@6.0.3) - '@typescript-eslint/types': 8.60.1 - '@typescript-eslint/visitor-keys': 8.60.1 + '@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 debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 @@ -2939,31 +2939,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.60.1(eslint@10.4.1(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)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.60.1 - '@typescript-eslint/types': 8.60.1 - '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) - eslint: 10.4.1(jiti@2.7.0) + '@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) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.60.1': + '@typescript-eslint/visitor-keys@8.63.0': dependencies: - '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/types': 8.63.0 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.3(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.3(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) - '@vitest/coverage-v8@4.1.8(vitest@4.1.8)': + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.8 + '@vitest/utils': 4.1.10 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -2972,46 +2972,46 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - '@vitest/expect@4.1.8': + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.8 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) - '@vitest/pretty-format@4.1.8': + '@vitest/pretty-format@4.1.10': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.8': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 4.1.8 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - '@vitest/snapshot@4.1.8': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.8': {} + '@vitest/spy@4.1.10': {} - '@vitest/utils@4.1.8': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.8 + '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -3288,11 +3288,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@7.1.1(eslint@10.4.1(jiti@2.7.0)): + eslint-plugin-react-hooks@7.1.1(eslint@10.7.0(jiti@2.7.0)): dependencies: '@babel/core': 7.29.7 '@babel/parser': 7.29.2 - eslint: 10.4.1(jiti@2.7.0) + eslint: 10.7.0(jiti@2.7.0) hermes-parser: 0.25.1 zod: 4.4.3 zod-validation-error: 4.0.2(zod@4.4.3) @@ -3310,9 +3310,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.4.1(jiti@2.7.0): + eslint@10.7.0(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.1(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.7.0(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.6.0 @@ -3907,13 +3907,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3): + typescript-eslint@8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.60.1(@typescript-eslint/parser@8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/parser': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.60.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.60.1(eslint@10.4.1(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.4.1(jiti@2.7.0) + '@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: 6.0.3 transitivePeerDependencies: - supports-color @@ -3963,7 +3963,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): + vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -3971,22 +3971,22 @@ snapshots: rolldown: 1.0.3 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 25.9.1 + '@types/node': 25.9.5 esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 tsx: 4.22.4 yaml: 2.9.0 - vitest@4.1.8(@types/node@25.9.1)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): + vitest@4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.8 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.8 - '@vitest/runner': 4.1.8 - '@vitest/snapshot': 4.1.8 - '@vitest/spy': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -3998,11 +3998,11 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@25.9.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.9.1 - '@vitest/coverage-v8': 4.1.8(vitest@4.1.8) + '@types/node': 25.9.5 + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) jsdom: 29.1.1 transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 390f20f..6f3a74f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,7 +3,7 @@ packages: catalog: typescript: "^6.0.3" - eslint: "^10.4.0" - typescript-eslint: "^8.59.4" - vitest: "^4.1.8" - "@vitest/coverage-v8": "^4.1.7" + eslint: "^10.5.0" + typescript-eslint: "^8.62.0" + vitest: "^4.1.9" + "@vitest/coverage-v8": "^4.1.9" From 46eaff4e417ebd74d4bdf61dff3fdef566e3f5d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:18:17 +0200 Subject: [PATCH 43/51] chore(docker): bump nginx in /packages/web (#65) Bumps nginx from 1.31.2-alpine to 1.31.3-alpine. --- updated-dependencies: - dependency-name: nginx dependency-version: 1.31.3-alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/web/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index 5d2d571..c5b1005 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -54,7 +54,7 @@ RUN pnpm --filter @dashlight/web build # ── Runtime stage (Nginx) ───────────────────────────────────────────────────── # The nginx runner serves only static files — no outbound HTTPS, no cert bundle needed. -FROM nginx:1.31.2-alpine AS runner +FROM nginx:1.31.3-alpine AS runner COPY --from=builder /app/packages/web/dist /usr/share/nginx/html COPY packages/web/nginx.conf /etc/nginx/conf.d/default.conf From 4f35e2c699711d02a4fe4e5529c865668bb71be3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:24:52 +0200 Subject: [PATCH 44/51] chore(gha): bump the version-all group across 1 directory with 3 updates (#69) Bumps the version-all group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release). Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020) Updates `softprops/action-gh-release` from 3.0.1 to 3.0.2 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/718ea10b132b3b2eba29c1007bb80653f286566b...3d0d9888cb7fd7b750713d6e236d1fcb99157228) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: softprops/action-gh-release dependency-version: 3.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly-deps.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- .github/workflows/test-build.yml | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/nightly-deps.yml b/.github/workflows/nightly-deps.yml index 7d649ab..4b3478f 100644 --- a/.github/workflows/nightly-deps.yml +++ b/.github/workflows/nightly-deps.yml @@ -18,13 +18,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 cache: pnpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3f1fef5..ad298a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 @@ -75,7 +75,7 @@ jobs: - name: Create GitHub Release if: steps.check.outputs.skip == 'false' - uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: tag_name: ${{ steps.check.outputs.tag }} name: ${{ steps.check.outputs.tag }} diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index ca930a1..31a8bc8 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -23,13 +23,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 cache: pnpm @@ -49,13 +49,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 cache: pnpm @@ -76,13 +76,13 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: version: 10 - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 cache: pnpm @@ -107,7 +107,7 @@ jobs: - image: web dockerfile: packages/web/Dockerfile steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 From c65d24690791ea80af5bd479aed19fecabc763c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:29:01 +0200 Subject: [PATCH 45/51] chore(deps):(deps): bump @hono/node-server (#70) Bumps the security-all group with 1 update in the / directory: [@hono/node-server](https://github.com/honojs/node-server). Updates `@hono/node-server` from 2.0.6 to 2.0.10 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v2.0.6...v2.0.10) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.10 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/server/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 9f94ae7..b9666d1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -15,7 +15,7 @@ "clean": "rm -rf dist" }, "dependencies": { - "@hono/node-server": "^2.0.5", + "@hono/node-server": "^2.0.10", "hono": "^4.12.26", "jose": "^6.2.3", "js-yaml": "^4.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea3c7d6..0a9437c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,8 +47,8 @@ importers: packages/server: dependencies: '@hono/node-server': - specifier: ^2.0.5 - version: 2.0.6(hono@4.12.27) + specifier: ^2.0.10 + version: 2.0.10(hono@4.12.27) hono: specifier: ^4.12.26 version: 4.12.27 @@ -558,8 +558,8 @@ packages: '@noble/hashes': optional: true - '@hono/node-server@2.0.6': - resolution: {integrity: sha512-7DeRlKG57JDBNZ5Qj2jwVdgwQy4b0tLubRLl3zCf91/rCf9i7p1V5FtW/yWibm1uUHE493ts9ZXH/7g/LQWl+g==} + '@hono/node-server@2.0.10': + resolution: {integrity: sha512-ZcnNVhKTmyDJeg0UlnZjvM73JBsTAuhrH/J4fjwGOw59PwOW51r4J+p6CsKZWXdKSme4MFqU62CZMOsdDrU4CA==} engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -2525,7 +2525,7 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.6(hono@4.12.27)': + '@hono/node-server@2.0.10(hono@4.12.27)': dependencies: hono: 4.12.27 From b78de442e048b9695fb674de51aa998feab9dcfa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:42:42 +0200 Subject: [PATCH 46/51] chore(deps):(deps): bump the version-all group across 1 directory with 20 updates (#71) Bumps the version-all group with 20 updates in the / directory: | Package | From | To | | --- | --- | --- | | [lint-staged](https://github.com/lint-staged/lint-staged) | `17.0.2` | `17.1.1` | | [@hono/node-server](https://github.com/honojs/node-server) | `2.0.10` | `2.0.12` | | [hono](https://github.com/honojs/hono) | `4.12.27` | `4.12.32` | | [jose](https://github.com/panva/jose) | `6.2.3` | `6.2.4` | | [js-yaml](https://github.com/nodeca/js-yaml) | `4.2.0` | `5.2.1` | | [lru-cache](https://github.com/isaacs/node-lru-cache) | `11.5.1` | `11.5.2` | | [undici](https://github.com/nodejs/undici) | `8.5.0` | `8.8.0` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.5` | `26.1.0` | | [tsx](https://github.com/privatenumber/tsx) | `4.22.4` | `4.23.1` | | [@tanstack/query-async-storage-persister](https://github.com/TanStack/query/tree/HEAD/packages/query-async-storage-persister) | `5.101.2` | `5.101.4` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.2` | `5.101.4` | | [@tanstack/react-query-persist-client](https://github.com/TanStack/query/tree/HEAD/packages/react-query-persist-client) | `5.101.2` | `5.101.4` | | [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router) | `1.170.16` | `1.170.18` | | [idb-keyval](https://github.com/jakearchibald/idb-keyval) | `6.2.5` | `6.3.0` | | [react](https://github.com/react/react/tree/HEAD/packages/react) | `19.2.7` | `19.2.8` | | [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) | `19.2.7` | `19.2.8` | | [recharts](https://github.com/recharts/recharts) | `3.8.1` | `3.10.0` | | [@tanstack/router-vite-plugin](https://github.com/TanStack/router/tree/HEAD/packages/router-vite-plugin) | `1.167.18` | `1.167.23` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.3` | `6.0.4` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.0.16` | `8.1.5` | Updates `lint-staged` from 17.0.2 to 17.1.1 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v17.0.2...v17.1.1) Updates `@hono/node-server` from 2.0.10 to 2.0.12 - [Release notes](https://github.com/honojs/node-server/releases) - [Commits](https://github.com/honojs/node-server/compare/v2.0.10...v2.0.12) Updates `hono` from 4.12.27 to 4.12.32 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.27...v4.12.32) Updates `jose` from 6.2.3 to 6.2.4 - [Release notes](https://github.com/panva/jose/releases) - [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md) - [Commits](https://github.com/panva/jose/compare/v6.2.3...v6.2.4) Updates `js-yaml` from 4.2.0 to 5.2.1 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.2.0...5.2.1) Updates `lru-cache` from 11.5.1 to 11.5.2 - [Changelog](https://github.com/isaacs/node-lru-cache/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-lru-cache/compare/v11.5.1...v11.5.2) Updates `undici` from 8.5.0 to 8.8.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.5.0...v8.8.0) Updates `@types/node` from 25.9.5 to 26.1.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `tsx` from 4.22.4 to 4.23.1 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.22.4...v4.23.1) Updates `@tanstack/query-async-storage-persister` from 5.101.2 to 5.101.4 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/query-async-storage-persister/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/query-async-storage-persister@5.101.4/packages/query-async-storage-persister) Updates `@tanstack/react-query` from 5.101.2 to 5.101.4 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.4/packages/react-query) Updates `@tanstack/react-query-persist-client` from 5.101.2 to 5.101.4 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-persist-client/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-persist-client@5.101.4/packages/react-query-persist-client) Updates `@tanstack/react-router` from 1.170.16 to 1.170.18 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.170.18/packages/react-router) Updates `idb-keyval` from 6.2.5 to 6.3.0 - [Changelog](https://github.com/jakearchibald/idb-keyval/blob/main/CHANGELOG.md) - [Commits](https://github.com/jakearchibald/idb-keyval/compare/v6.2.5...v6.3.0) Updates `react` from 19.2.7 to 19.2.8 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.2.8/packages/react) Updates `react-dom` from 19.2.7 to 19.2.8 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.2.8/packages/react-dom) Updates `recharts` from 3.8.1 to 3.10.0 - [Release notes](https://github.com/recharts/recharts/releases) - [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md) - [Commits](https://github.com/recharts/recharts/compare/v3.8.1...v3.10.0) Updates `@tanstack/router-vite-plugin` from 1.167.18 to 1.167.23 - [Release notes](https://github.com/TanStack/router/releases) - [Changelog](https://github.com/TanStack/router/blob/main/packages/router-vite-plugin/CHANGELOG.md) - [Commits](https://github.com/TanStack/router/commits/@tanstack/router-vite-plugin@1.167.23/packages/router-vite-plugin) Updates `@vitejs/plugin-react` from 6.0.3 to 6.0.4 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.4/packages/plugin-react) Updates `vite` from 8.0.16 to 8.1.5 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.1.5/packages/vite) --- updated-dependencies: - dependency-name: "@hono/node-server" dependency-version: 2.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/query-async-storage-persister" dependency-version: 5.101.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/react-query" dependency-version: 5.101.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/react-query-persist-client" dependency-version: 5.101.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/react-router" dependency-version: 1.170.18 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@tanstack/router-vite-plugin" dependency-version: 1.167.23 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: "@types/node" dependency-version: 26.1.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: version-all - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all - dependency-name: hono dependency-version: 4.12.32 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: idb-keyval dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: jose dependency-version: 6.2.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: js-yaml dependency-version: 5.2.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: version-all - dependency-name: lint-staged dependency-version: 17.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: lru-cache dependency-version: 11.5.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: react dependency-version: 19.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: react-dom dependency-version: 19.2.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all - dependency-name: recharts dependency-version: 3.9.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: tsx dependency-version: 4.23.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all - dependency-name: undici dependency-version: 8.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-all - dependency-name: vite dependency-version: 8.1.5 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- packages/server/package.json | 16 +- packages/web/package.json | 22 +- pnpm-lock.yaml | 1253 +++++++++++++++------------------- 4 files changed, 553 insertions(+), 740 deletions(-) diff --git a/package.json b/package.json index d7706ad..d7019f6 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "devDependencies": { "husky": "^9.1.7", - "lint-staged": "^17.0.2", + "lint-staged": "^17.1.1", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/server/package.json b/packages/server/package.json index b9666d1..065e302 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -15,19 +15,19 @@ "clean": "rm -rf dist" }, "dependencies": { - "@hono/node-server": "^2.0.10", - "hono": "^4.12.26", - "jose": "^6.2.3", - "js-yaml": "^4.2.0", - "lru-cache": "^11.5.0", - "undici": "^8.5.0" + "@hono/node-server": "^2.0.12", + "hono": "^4.12.32", + "jose": "^6.2.4", + "js-yaml": "^5.2.1", + "lru-cache": "^11.5.2", + "undici": "^8.8.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@types/node": "^25.9.1", + "@types/node": "^26.1.0", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", - "tsx": "^4.22.3", + "tsx": "^4.23.1", "typescript": "catalog:", "typescript-eslint": "catalog:", "vitest": "catalog:" diff --git a/packages/web/package.json b/packages/web/package.json index d37ad0f..dec3dd4 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -14,33 +14,33 @@ "clean": "rm -rf dist" }, "dependencies": { - "@tanstack/query-async-storage-persister": "^5.101.2", - "@tanstack/react-query": "^5.101.2", - "@tanstack/react-query-persist-client": "^5.101.2", - "@tanstack/react-router": "^1.170.15", + "@tanstack/query-async-storage-persister": "^5.101.4", + "@tanstack/react-query": "^5.101.4", + "@tanstack/react-query-persist-client": "^5.101.4", + "@tanstack/react-router": "^1.170.18", "@xyflow/react": "^12.11.1", "@dagrejs/dagre": "^3.0.0", - "idb-keyval": "^6.2.4", - "react": "^19.2.6", - "react-dom": "^19.2.6", - "recharts": "^3.8.1", + "idb-keyval": "^6.3.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "recharts": "^3.10.0", "zod": "^4.4.3" }, "devDependencies": { "@tanstack/react-router-devtools": "^1.167.0", - "@tanstack/router-vite-plugin": "^1.167.18", + "@tanstack/router-vite-plugin": "^1.167.23", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.3", + "@vitejs/plugin-react": "^6.0.4", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", "eslint-plugin-react-hooks": "^7.1.1", "jsdom": "^29.1.1", "typescript": "catalog:", "typescript-eslint": "catalog:", - "vite": "^8.0.14", + "vite": "^8.1.5", "vitest": "catalog:" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a9437c..46df563 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,42 +35,42 @@ importers: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^17.0.2 - version: 17.0.2 + specifier: ^17.1.1 + version: 17.1.1 typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) packages/server: dependencies: '@hono/node-server': - specifier: ^2.0.10 - version: 2.0.10(hono@4.12.27) + specifier: ^2.0.12 + version: 2.0.12(hono@4.12.32) hono: - specifier: ^4.12.26 - version: 4.12.27 + specifier: ^4.12.32 + version: 4.12.32 jose: - specifier: ^6.2.3 - version: 6.2.3 + specifier: ^6.2.4 + version: 6.2.4 js-yaml: - specifier: ^4.2.0 - version: 4.2.0 + specifier: ^5.2.1 + version: 5.2.1 lru-cache: - specifier: ^11.5.0 - version: 11.5.1 + specifier: ^11.5.2 + version: 11.5.2 undici: - specifier: ^8.5.0 - version: 8.5.0 + specifier: ^8.8.0 + version: 8.8.0 devDependencies: '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 '@types/node': - specifier: ^25.9.1 - version: 25.9.5 + specifier: ^26.1.0 + version: 26.1.0 '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.10(vitest@4.1.10) @@ -78,8 +78,8 @@ importers: specifier: 'catalog:' version: 10.7.0(jiti@2.7.0) tsx: - specifier: ^4.22.3 - version: 4.22.4 + specifier: ^4.23.1 + version: 4.23.1 typescript: specifier: 'catalog:' version: 6.0.3 @@ -88,7 +88,7 @@ importers: version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) packages/web: dependencies: @@ -96,48 +96,48 @@ importers: specifier: ^3.0.0 version: 3.0.0 '@tanstack/query-async-storage-persister': - specifier: ^5.101.2 - version: 5.101.2 + specifier: ^5.101.4 + version: 5.101.4 '@tanstack/react-query': - specifier: ^5.101.2 - version: 5.101.2(react@19.2.7) + specifier: ^5.101.4 + version: 5.101.4(react@19.2.8) '@tanstack/react-query-persist-client': - specifier: ^5.101.2 - version: 5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7) + specifier: ^5.101.4 + version: 5.101.4(@tanstack/react-query@5.101.4(react@19.2.8))(react@19.2.8) '@tanstack/react-router': - specifier: ^1.170.15 - version: 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.170.18 + version: 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@xyflow/react': specifier: ^12.11.1 - version: 12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.15)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) idb-keyval: - specifier: ^6.2.4 - version: 6.2.5 + specifier: ^6.3.0 + version: 6.3.0 react: - specifier: ^19.2.6 - version: 19.2.7 + specifier: ^19.2.8 + version: 19.2.8 react-dom: - specifier: ^19.2.6 - version: 19.2.7(react@19.2.7) + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) recharts: - specifier: ^3.8.1 - version: 3.8.1(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1) + specifier: ^3.10.0 + version: 3.10.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1) zod: specifier: ^4.4.3 version: 4.4.3 devDependencies: '@tanstack/react-router-devtools': specifier: ^1.167.0 - version: 1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@tanstack/router-vite-plugin': - specifier: ^1.167.18 - version: 1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^1.167.23 + version: 1.167.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.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: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@types/react': specifier: ^19.2.17 version: 19.2.17 @@ -145,8 +145,8 @@ importers: specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': - specifier: ^6.0.3 - version: 6.0.3(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^6.0.4 + version: 6.0.4(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.10(vitest@4.1.10) @@ -166,11 +166,11 @@ importers: specifier: 'catalog:' version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vite: - specifier: ^8.0.14 - version: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + specifier: ^8.1.5 + version: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) packages: @@ -192,10 +192,6 @@ packages: '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -208,22 +204,14 @@ packages: resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - 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': resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.29.7': resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} @@ -238,18 +226,10 @@ packages: peerDependencies: '@babel/core': ^7.29.7 - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} @@ -272,6 +252,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -280,30 +265,22 @@ packages: resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@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==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -354,14 +331,14 @@ packages: '@dagrejs/graphlib@4.0.1': resolution: {integrity: sha512-IvcV6FduIIAmLwnH+yun+QtV36SC7mERqa86aClNqmMN09WhmPPYU8ckHrZBozErf+UvHPWOTJYaGYiIcs0DgA==} - '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} @@ -558,8 +535,8 @@ packages: '@noble/hashes': optional: true - '@hono/node-server@2.0.10': - resolution: {integrity: sha512-ZcnNVhKTmyDJeg0UlnZjvM73JBsTAuhrH/J4fjwGOw59PwOW51r4J+p6CsKZWXdKSme4MFqU62CZMOsdDrU4CA==} + '@hono/node-server@2.0.12': + resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -596,17 +573,18 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/wasm-runtime@1.1.4': - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + '@napi-rs/wasm-runtime@1.2.2': + resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + 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.3 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 - '@oxc-project/types@0.133.0': - resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} - '@reduxjs/toolkit@2.11.2': - resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} + '@reduxjs/toolkit@2.12.0': + resolution: {integrity: sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18 || ^19 react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 @@ -616,97 +594,97 @@ packages: react-redux: optional: true - '@rolldown/binding-android-arm64@1.0.3': - resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.3': - resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.3': - resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.3': - resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': - resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.3': - resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.3': - resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.0.3': - resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.0.3': - resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.0.3': - resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.3': - resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.3': - resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.3': - resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + '@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.0.3': - resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.3': - resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -724,23 +702,23 @@ packages: resolution: {integrity: sha512-79pf/RkhteYZTRgcR4F9kbk84P2N8rugQJswxfIqovlbRiT3yI7eBE+5QorIrZaOKktsgzRlXh1l/du/xpl4iA==} engines: {node: '>=20.19'} - '@tanstack/query-async-storage-persister@5.101.2': - resolution: {integrity: sha512-jf7zvVKZ5q2j/xuhbTIBUpw5xt6cw/ioOFQquxK7fRY0AmMQP8A0JVMOgYoeQLA4PKdeT7RxsuLAF0Lft9oJ8Q==} + '@tanstack/query-async-storage-persister@5.101.4': + resolution: {integrity: sha512-ROenNOVvxIZ1zKsBAiIvvslLo2xD8Me/vFz/tChdmuI7ciU+ET63yRrQ01W899Tx1ayQXdsGQJqYqjjVZk+OBQ==} - '@tanstack/query-core@5.101.2': - resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} + '@tanstack/query-core@5.101.4': + resolution: {integrity: sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==} - '@tanstack/query-persist-client-core@5.101.2': - resolution: {integrity: sha512-rgMsbvBVpSPDUsprC9FYxojdG0Q1LH6yq1i3DXz2aps4VEqv2l4Msj3YDqIifU3xkl/DrYe9YWntZAJLrM6xTg==} + '@tanstack/query-persist-client-core@5.101.4': + resolution: {integrity: sha512-Bmu+RfWhwYEyYZEwSeKC0gX4+KTkiEB3yO8oz9BfAY/Jfe3ndz9EnYVhihIZPmWIr8NXayF7JuraNQcrXQQCCg==} - '@tanstack/react-query-persist-client@5.101.2': - resolution: {integrity: sha512-19UpaRtf0lvB2QAJ2MoixxtGf3osMOd508g99EsttUj4+3eLs+ulnNgYjB7AkQMHrRlcbVXqpVNqWkB4a7g8Zw==} + '@tanstack/react-query-persist-client@5.101.4': + resolution: {integrity: sha512-CY5i7PPKS/5B8OR2zAs9nCbLpgqI4jN8eBhtAxKRMNHyGcQhmyOy4PkkJrAAXT+ecGj++fBJTgQw6OpyCt/2SQ==} peerDependencies: - '@tanstack/react-query': ^5.101.2 + '@tanstack/react-query': ^5.101.4 react: ^18 || ^19 - '@tanstack/react-query@5.101.2': - resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} + '@tanstack/react-query@5.101.4': + resolution: {integrity: sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==} peerDependencies: react: ^18 || ^19 @@ -756,8 +734,8 @@ packages: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.170.16': - resolution: {integrity: sha512-w6eq1IJklujs1tESazaK/FxH0+H2l8vm/QPuu1cD3oRW/ubgKneQpd7b64ti/8gUyEimzimJQZDmJr6YHfP5+g==} + '@tanstack/react-router@1.170.18': + resolution: {integrity: sha512-wpbGYZEp/fmz1q4bn7BD8VZ+/VZ7GBqSJv5V969pU+chP8y7dquWDmKTFMohvUegb9lg12m1uPVvD6kB2wORvQ==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -769,8 +747,8 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.171.13': - resolution: {integrity: sha512-+NOwEj1kO/6IGmpHRIZHasYxYWpyBQGNIZAST9aNrk9Q3YlU9SgqVnl1pbLa9qAKfeNdXQIRve0RQb/0kyDeDA==} + '@tanstack/router-core@1.171.15': + resolution: {integrity: sha512-IILCDcLaItMZQ2jEmCABHY1Nhjjn5XUvwpQp3e4Nmu+vfg0BgYFuu/QASz2SwE2ZNbVMrvt8X/wxa+Gg5aErxA==} engines: {node: '>=20.19'} '@tanstack/router-devtools-core@1.168.0': @@ -783,16 +761,16 @@ packages: csstype: optional: true - '@tanstack/router-generator@1.167.17': - resolution: {integrity: sha512-xtB9tB2Ws0tWR6Pi7nc3Qk9IYgoh1mQCKWjHqIl9tf6BNUpKoqniJoPAQ4+LGrK8FeZYU0o0p/qlZEyj9FAulA==} + '@tanstack/router-generator@1.167.21': + resolution: {integrity: sha512-m3oXZyienj8owialdyoZ0txHQrnEx/Ra+D9kWtar5fC2cWZr5Pvxl86VY2mX5RRLC5QLKLeRGT1x4HV95wHVDQ==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.168.18': - resolution: {integrity: sha512-MofS28/axfnfnhOD2RSgJEaU882aX5RsAzhGz5Vc4XhAmvCjy919u9JrNs4QsTWFbTD1P7IJ8WFlFVsrg0pStg==} + '@tanstack/router-plugin@1.168.23': + resolution: {integrity: sha512-0+PIcvnaAimFwjoEIeV3h7LKjzC8zNnp7pH2UamdKwQ9QlY99WU9V0Xl0zbM0i9hrUa/mKgWPDAzELmPUu5fMA==} engines: {node: '>=20.19'} peerDependencies: '@rsbuild/core': '>=1.0.2 || ^2.0.0' - '@tanstack/react-router': ^1.170.15 + '@tanstack/react-router': ^1.170.18 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' @@ -812,8 +790,8 @@ packages: resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==} engines: {node: '>=20.19'} - '@tanstack/router-vite-plugin@1.167.18': - resolution: {integrity: sha512-JG5kSvzF1UJasJRLO3oXiuJp1F2OIrRJuZpJ6JAfU+k1gOStHFlSP/X9xArnhtEKvitYNCN+26yn4ku8X0DP7w==} + '@tanstack/router-vite-plugin@1.167.23': + resolution: {integrity: sha512-MnkK6OIwtMtEeThZTZFMsClQeZCL7apA9kmj8h3roRS+hws5ttGqmy2gkxRlK5EQIfz2ePbefRey0us/qA3hLQ==} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': @@ -846,8 +824,8 @@ packages: '@types/react-dom': optional: true - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -909,8 +887,8 @@ 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@26.1.0': + resolution: {integrity: sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -982,8 +960,8 @@ packages: resolution: {integrity: sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@6.0.3': - resolution: {integrity: sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==} + '@vitejs/plugin-react@6.0.4': + resolution: {integrity: sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 @@ -1062,28 +1040,16 @@ packages: ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ansi-escapes@7.3.0: - resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - ansis@4.2.0: - resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + ansis@4.3.1: + resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} engines: {node: '>=14'} argparse@2.0.1: @@ -1110,8 +1076,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.19: - resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==} + baseline-browser-mapping@2.11.12: + resolution: {integrity: sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==} engines: {node: '>=6.0.0'} hasBin: true @@ -1122,13 +1088,13 @@ packages: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} - browserslist@4.28.2: - resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - caniuse-lite@1.0.30001788: - resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} @@ -1141,14 +1107,6 @@ packages: classcat@5.0.5: resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1279,25 +1237,18 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - electron-to-chromium@1.5.339: - resolution: {integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==} - - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + electron-to-chromium@1.5.401: + resolution: {integrity: sha512-H6ViHN68nGYlChEvlIU67fn8O2/tpbWQPwck98yaJmh+08LSvHiydzDQ6oXNccLU3kNRVIRS9A4mA7CG+i6fLQ==} entities@8.0.0: resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} engines: {node: '>=20.19.0'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - es-toolkit@1.45.1: - resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} + es-toolkit@1.50.0: + resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} @@ -1412,10 +1363,6 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-east-asian-width@1.6.0: - resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} - engines: {node: '>=18'} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -1435,8 +1382,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.27: - resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} + hono@4.12.32: + resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -1451,8 +1398,8 @@ packages: engines: {node: '>=18'} hasBin: true - idb-keyval@6.2.5: - resolution: {integrity: sha512-eKQkTnS0relYsSOYomx8ozIbmdsQCKUdhyuIaQ2DZgKuaxtyQQMkyD/wlnQN32pO3yutN1b1L8uqwcDKaJd7/Q==} + idb-keyval@6.3.0: + resolution: {integrity: sha512-um+2dgAWmYsu615EXpWVwSmapJhON0G43t3Ka/EVaohzPQXSMqKEqeDK/oIW3Ow+BXaF2PvSc+oBTFp793A5Ow==} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} @@ -1462,11 +1409,8 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - immer@10.2.0: - resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} - - immer@11.1.4: - resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} + immer@11.1.15: + resolution: {integrity: sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ==} imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -1484,10 +1428,6 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1495,8 +1435,8 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - isbot@5.1.38: - resolution: {integrity: sha512-Cus2702JamTNMEY4zTP+TShgq/3qzjvGcBC4XMOV45BLaxD4iUFENkqu7ZhFeSzwNsCSZLjnGlihDQznnpnEEA==} + isbot@5.2.1: + resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==} engines: {node: '>=18'} isexe@2.0.0: @@ -1518,8 +1458,8 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - jose@6.2.3: - resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + jose@6.2.4: + resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==} js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -1527,8 +1467,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.2.0: - resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + js-yaml@5.2.1: + resolution: {integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==} hasBin: true jsdom@29.1.1: @@ -1566,99 +1506,91 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + 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==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} - lint-staged@17.0.2: - resolution: {integrity: sha512-Rbr6rdmbCn1fIDHBZpn0madg0hEkdlh+QwajnL3Qq0ZUq/icAJfLGj9BVBajAXi7657ZzKQ7kobGP9S5XOHYRw==} + lint-staged@17.1.1: + resolution: {integrity: sha512-FnHWpSe5cPRtrDG+soOuNdBxb4XQb2gN5EqpEWKdweyqyOfpl4QSjbrz3ilcIf0WXmkiNQGZZRQ23R5YtB3TEw==} engines: {node: '>=22.22.1'} hasBin: true - listr2@10.2.1: - resolution: {integrity: sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==} - engines: {node: '>=22.13.0'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - - lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -1681,10 +1613,6 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -1696,25 +1624,22 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.12: - resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - node-releases@2.0.37: - resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} + node-releases@2.0.52: + resolution: {integrity: sha512-MRlTqhAfoMx/4mhEbPo3Hi02g9LJZaJkka69V6h67Cb1gjrAG0jsTE4CZX1eptNx+VCAwJmfpnDIF4P0Nh1A7A==} + engines: {node: '>=18'} obug@2.1.3: resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1748,16 +1673,20 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} - postcss@8.5.15: - resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + postcss@8.5.25: + resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.8.3: - resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} engines: {node: '>=14'} hasBin: true @@ -1769,10 +1698,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - react-dom@19.2.7: - resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} peerDependencies: - react: ^19.2.7 + react: ^19.2.8 react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} @@ -1780,8 +1709,8 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-redux@9.2.0: - resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} + react-redux@9.3.0: + resolution: {integrity: sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==} peerDependencies: '@types/react': ^18.2.25 || ^19 react: ^18.0 || ^19 @@ -1792,16 +1721,16 @@ packages: redux: optional: true - react@19.2.7: - resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} readdirp@5.0.0: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} - recharts@3.8.1: - resolution: {integrity: sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==} + recharts@3.10.0: + resolution: {integrity: sha512-wulMvfncpIlmu2uFtRU/mE5/+NiVtASXkw2KdwJTdHs3WsASX0WxZlX+rpKgyn5BDbIhkPtCpUKkB9XNK5KE0w==} engines: {node: '>=18'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1824,18 +1753,11 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - reselect@5.1.1: - resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + reselect@5.2.0: + resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rolldown@1.0.3: - resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1855,14 +1777,14 @@ packages: engines: {node: '>=10'} hasBin: true - seroval-plugins@1.5.4: - resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} + seroval-plugins@1.6.2: + resolution: {integrity: sha512-TfxuUjlbBESzUOWdTkTKqvSmav0ABym+itetDXLK6mDz8SmrpdI30aF8RTXE8Bvq+tH/1yIDkvy3W0lfQb1ipQ==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.5.4: - resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} + seroval@1.6.2: + resolution: {integrity: sha512-mPT+SD2TrlB6wvte1KkYOYUkubaTbd6pZ/6Kk3C9nxzrHmCZyhxOO7XGAeL7f+yLKZglzGtM9odUVvg/EhO+vQ==} engines: {node: '>=10'} shebang-command@2.0.0: @@ -1876,18 +1798,6 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1902,18 +1812,6 @@ packages: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string-width@8.2.1: - resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} - engines: {node: '>=20'} - - strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -1935,6 +1833,10 @@ packages: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} + engines: {node: '>=18'} + tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -1967,8 +1869,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.22.4: - resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} + tsx@4.23.1: + resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -1988,20 +1890,49 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} - undici@8.5.0: - resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==} + undici@8.8.0: + resolution: {integrity: sha512-ubshXMXwF3MQIMF1y/WxZdNBnjEKeSg2wF5mcGUtU55YTw34tnVVpKRlLf7ruDXZ5344KokPVX4RBx1wJm64Bw==} engines: {node: '>=22.19.0'} - unplugin@3.0.0: - resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} + unplugin@3.3.0: + resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==} engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@farmfe/core': '*' + '@rspack/core': '*' + bun-types-no-globals: '*' + esbuild: ^0.28.1 + rolldown: '*' + rollup: '*' + unloader: '*' + vite: '*' + webpack: '*' + peerDependenciesMeta: + '@farmfe/core': + optional: true + '@rspack/core': + optional: true + bun-types-no-globals: + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + unloader: + optional: true + vite: + optional: true + webpack: + optional: true update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -2020,13 +1951,13 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite@8.0.16: - resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + vite@8.1.5: + resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.18 + '@vitejs/devtools': ^0.3.0 esbuild: ^0.28.1 jiti: '>=1.21.0' less: ^4.0.0 @@ -2137,14 +2068,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrap-ansi@10.0.0: - resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} - engines: {node: '>=20'} - - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -2212,12 +2135,6 @@ snapshots: '@asamuzakjp/nwsapi@2.3.9': {} - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -2229,14 +2146,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 @@ -2246,18 +2163,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@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 @@ -2266,18 +2175,16 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.2 + browserslist: 4.28.7 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-globals@7.28.0': {} - '@babel/helper-globals@7.29.7': {} '@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 @@ -2286,16 +2193,12 @@ 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 - '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@7.29.7': {} '@babel/helper-validator-option@7.29.7': {} @@ -2303,62 +2206,48 @@ 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.2': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.8 '@babel/parser@7.29.7': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 '@babel/runtime@7.29.2': {} '@babel/runtime@7.29.7': {} - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@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.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - '@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.0': + '@babel/types@7.29.7': dependencies: - '@babel/helper-string-parser': 7.27.1 + '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@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 @@ -2399,18 +2288,18 @@ snapshots: '@dagrejs/graphlib@4.0.1': {} - '@emnapi/core@1.10.0': + '@emnapi/core@1.11.1': dependencies: - '@emnapi/wasi-threads': 1.2.1 + '@emnapi/wasi-threads': 1.2.2 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.10.0': + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.2.1': + '@emnapi/wasi-threads@1.2.2': dependencies: tslib: 2.8.1 optional: true @@ -2525,9 +2414,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.10(hono@4.12.27)': + '@hono/node-server@2.0.12(hono@4.12.32)': dependencies: - hono: 4.12.27 + hono: 4.12.32 '@humanfs/core@0.19.1': {} @@ -2559,74 +2448,74 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 optional: true - '@oxc-project/types@0.133.0': {} + '@oxc-project/types@0.139.0': {} - '@reduxjs/toolkit@2.11.2(react-redux@9.2.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.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 - immer: 11.1.4 + immer: 11.1.15 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) - reselect: 5.1.1 + reselect: 5.2.0 optionalDependencies: - react: 19.2.7 - react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) + react: 19.2.8 + react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1) - '@rolldown/binding-android-arm64@1.0.3': + '@rolldown/binding-android-arm64@1.1.5': optional: true - '@rolldown/binding-darwin-arm64@1.0.3': + '@rolldown/binding-darwin-arm64@1.1.5': optional: true - '@rolldown/binding-darwin-x64@1.0.3': + '@rolldown/binding-darwin-x64@1.1.5': optional: true - '@rolldown/binding-freebsd-x64@1.0.3': + '@rolldown/binding-freebsd-x64@1.1.5': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.3': + '@rolldown/binding-linux-arm64-gnu@1.1.5': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.3': + '@rolldown/binding-linux-arm64-musl@1.1.5': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.3': + '@rolldown/binding-linux-ppc64-gnu@1.1.5': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.3': + '@rolldown/binding-linux-s390x-gnu@1.1.5': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.3': + '@rolldown/binding-linux-x64-gnu@1.1.5': optional: true - '@rolldown/binding-linux-x64-musl@1.0.3': + '@rolldown/binding-linux-x64-musl@1.1.5': optional: true - '@rolldown/binding-openharmony-arm64@1.0.3': + '@rolldown/binding-openharmony-arm64@1.1.5': optional: true - '@rolldown/binding-wasm32-wasi@1.0.3': + '@rolldown/binding-wasm32-wasi@1.1.5': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.3': + '@rolldown/binding-win32-arm64-msvc@1.1.5': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.3': + '@rolldown/binding-win32-x64-msvc@1.1.5': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -2637,106 +2526,113 @@ snapshots: '@tanstack/history@1.162.0': {} - '@tanstack/query-async-storage-persister@5.101.2': + '@tanstack/query-async-storage-persister@5.101.4': dependencies: - '@tanstack/query-core': 5.101.2 - '@tanstack/query-persist-client-core': 5.101.2 + '@tanstack/query-core': 5.101.4 + '@tanstack/query-persist-client-core': 5.101.4 - '@tanstack/query-core@5.101.2': {} + '@tanstack/query-core@5.101.4': {} - '@tanstack/query-persist-client-core@5.101.2': + '@tanstack/query-persist-client-core@5.101.4': dependencies: - '@tanstack/query-core': 5.101.2 + '@tanstack/query-core': 5.101.4 - '@tanstack/react-query-persist-client@5.101.2(@tanstack/react-query@5.101.2(react@19.2.7))(react@19.2.7)': + '@tanstack/react-query-persist-client@5.101.4(@tanstack/react-query@5.101.4(react@19.2.8))(react@19.2.8)': dependencies: - '@tanstack/query-persist-client-core': 5.101.2 - '@tanstack/react-query': 5.101.2(react@19.2.7) - react: 19.2.7 + '@tanstack/query-persist-client-core': 5.101.4 + '@tanstack/react-query': 5.101.4(react@19.2.8) + react: 19.2.8 - '@tanstack/react-query@5.101.2(react@19.2.7)': + '@tanstack/react-query@5.101.4(react@19.2.8)': dependencies: - '@tanstack/query-core': 5.101.2 - react: 19.2.7 + '@tanstack/query-core': 5.101.4 + react: 19.2.8 - '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@tanstack/router-core@1.171.13)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: - '@tanstack/react-router': 1.170.16(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.13)(csstype@3.2.3) - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-devtools-core': 1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) optionalDependencies: - '@tanstack/router-core': 1.171.13 + '@tanstack/router-core': 1.171.15 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': 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.13 - isbot: 5.1.38 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + '@tanstack/react-store': 0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-core': 1.171.15 + isbot: 5.2.1 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) - '@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.2.8(react@19.2.8))(react@19.2.8)': 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.2.8 + react-dom: 19.2.8(react@19.2.8) + use-sync-external-store: 1.6.0(react@19.2.8) - '@tanstack/router-core@1.171.13': + '@tanstack/router-core@1.171.15': dependencies: '@tanstack/history': 1.162.0 cookie-es: 3.1.1 - seroval: 1.5.4 - seroval-plugins: 1.5.4(seroval@1.5.4) + seroval: 1.6.2 + seroval-plugins: 1.6.2(seroval@1.6.2) - '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.13)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.171.13 + '@tanstack/router-core': 1.171.15 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.167.17': + '@tanstack/router-generator@1.167.21': dependencies: - '@babel/types': 7.29.0 - '@tanstack/router-core': 1.171.13 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.15 '@tanstack/router-utils': 1.162.2 '@tanstack/virtual-file-routes': 1.162.0 jiti: 2.7.0 magic-string: 0.30.21 - prettier: 3.8.3 + prettier: 3.9.6 zod: 4.4.3 transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - '@tanstack/router-core': 1.171.13 - '@tanstack/router-generator': 1.167.17 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.15 + '@tanstack/router-generator': 1.167.21 '@tanstack/router-utils': 1.162.2 chokidar: 5.0.0 - unplugin: 3.0.0 + unplugin: 3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) zod: 4.4.3 optionalDependencies: - '@tanstack/react-router': 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup - supports-color + - unloader '@tanstack/router-utils@1.162.2': dependencies: - '@babel/generator': 7.29.1 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - ansis: 4.2.0 + '@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 pathe: 2.0.3 @@ -2744,13 +2640,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@tanstack/router-vite-plugin@1.167.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.18(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) transitivePeerDependencies: + - '@farmfe/core' - '@rsbuild/core' + - '@rspack/core' - '@tanstack/react-router' + - bun-types-no-globals + - esbuild + - rolldown + - rollup - supports-color + - unloader - vite - vite-plugin-solid - webpack @@ -2779,17 +2682,17 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.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)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.2 '@testing-library/dom': 10.4.1 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@tybys/wasm-util@0.10.1': + '@tybys/wasm-util@0.10.3': dependencies: tslib: 2.8.1 optional: true @@ -2850,9 +2753,9 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.9.5': + '@types/node@26.1.0': dependencies: - undici-types: 7.24.6 + undici-types: 8.3.0 '@types/react-dom@19.2.3(@types/react@19.2.17)': dependencies: @@ -2955,10 +2858,10 @@ snapshots: '@typescript-eslint/types': 8.63.0 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.3(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.4(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: @@ -2972,7 +2875,7 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) '@vitest/expect@4.1.10': dependencies: @@ -2983,13 +2886,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -3015,13 +2918,13 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@xyflow/react@12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@xyflow/react@12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.15)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@xyflow/system': 0.0.79 classcat: 5.0.5 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - zustand: 4.5.7(@types/react@19.2.17)(immer@11.1.4)(react@19.2.7) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + zustand: 4.5.7(@types/react@19.2.17)(immer@11.1.15)(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) @@ -3053,19 +2956,11 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} - - ansis@4.2.0: {} + ansis@4.3.1: {} argparse@2.0.1: {} @@ -3086,15 +2981,15 @@ snapshots: babel-dead-code-elimination@1.0.12: dependencies: '@babel/core': 7.29.7 - '@babel/parser': 7.29.2 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.8 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.19: {} + baseline-browser-mapping@2.11.12: {} bidi-js@1.0.3: dependencies: @@ -3104,15 +2999,15 @@ snapshots: dependencies: balanced-match: 4.0.4 - browserslist@4.28.2: + browserslist@4.28.7: dependencies: - baseline-browser-mapping: 2.10.19 - caniuse-lite: 1.0.30001788 - electron-to-chromium: 1.5.339 - node-releases: 2.0.37 - update-browserslist-db: 1.2.3(browserslist@4.28.2) + baseline-browser-mapping: 2.11.12 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.401 + node-releases: 2.0.52 + update-browserslist-db: 1.2.3(browserslist@4.28.7) - caniuse-lite@1.0.30001788: {} + caniuse-lite@1.0.30001806: {} chai@6.2.2: {} @@ -3122,15 +3017,6 @@ snapshots: classcat@5.0.5: {} - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-truncate@5.2.0: - dependencies: - slice-ansi: 8.0.0 - string-width: 8.2.1 - clsx@2.1.1: {} convert-source-map@2.0.0: {} @@ -3243,17 +3129,13 @@ snapshots: dom-accessibility-api@0.6.3: {} - electron-to-chromium@1.5.339: {} - - emoji-regex@10.6.0: {} + electron-to-chromium@1.5.401: {} entities@8.0.0: {} - environment@1.1.0: {} - es-module-lexer@2.1.0: {} - es-toolkit@1.45.1: {} + es-toolkit@1.50.0: {} esbuild@0.28.1: optionalDependencies: @@ -3379,9 +3261,9 @@ snapshots: fast-levenshtein@2.0.6: {} - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.5 file-entry-cache@8.0.0: dependencies: @@ -3404,8 +3286,6 @@ snapshots: gensync@1.0.0-beta.2: {} - get-east-asian-width@1.6.0: {} - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -3422,7 +3302,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.27: {} + hono@4.12.32: {} html-encoding-sniffer@6.0.0: dependencies: @@ -3434,15 +3314,13 @@ snapshots: husky@9.1.7: {} - idb-keyval@6.2.5: {} + idb-keyval@6.3.0: {} ignore@5.3.2: {} ignore@7.0.5: {} - immer@10.2.0: {} - - immer@11.1.4: {} + immer@11.1.15: {} imurmurhash@0.1.4: {} @@ -3452,17 +3330,13 @@ snapshots: is-extglob@2.1.1: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.6.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-potential-custom-element-name@1.0.1: {} - isbot@5.1.38: {} + isbot@5.2.1: {} isexe@2.0.0: {} @@ -3481,13 +3355,13 @@ snapshots: jiti@2.7.0: {} - jose@6.2.3: {} + jose@6.2.4: {} js-tokens@10.0.0: {} js-tokens@4.0.0: {} - js-yaml@4.2.0: + js-yaml@5.2.1: dependencies: argparse: 2.0.1 @@ -3503,12 +3377,12 @@ snapshots: decimal.js: 10.6.0 html-encoding-sniffer: 6.0.0 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.1 + lru-cache: 11.5.2 parse5: 8.0.1 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.28.0 + undici: 7.29.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -3536,85 +3410,68 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 - - lint-staged@17.0.2: - dependencies: - listr2: 10.2.1 - picomatch: 4.0.4 + 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 + + lint-staged@17.1.1: + dependencies: + picomatch: 4.0.5 string-argv: 0.3.2 - tinyexec: 1.2.4 + tinyexec: 1.3.0 optionalDependencies: yaml: 2.9.0 - listr2@10.2.1: - dependencies: - cli-truncate: 5.2.0 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 10.0.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - - lru-cache@11.5.1: {} + lru-cache@11.5.2: {} lru-cache@5.1.1: dependencies: @@ -3638,8 +3495,6 @@ snapshots: mdn-data@2.27.1: {} - mimic-function@5.0.1: {} - min-indent@1.0.1: {} minimatch@10.2.5: @@ -3648,18 +3503,14 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.12: {} + nanoid@3.3.17: {} natural-compare@1.4.0: {} - node-releases@2.0.37: {} + node-releases@2.0.52: {} obug@2.1.3: {} - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3691,15 +3542,17 @@ snapshots: picomatch@4.0.4: {} - postcss@8.5.15: + picomatch@4.0.5: {} + + postcss@8.5.25: dependencies: - nanoid: 3.3.12 + nanoid: 3.3.17 picocolors: 1.1.1 source-map-js: 1.2.1 prelude-ls@1.2.1: {} - prettier@3.8.3: {} + prettier@3.9.6: {} pretty-format@27.5.1: dependencies: @@ -3709,43 +3562,43 @@ snapshots: punycode@2.3.1: {} - react-dom@19.2.7(react@19.2.7): + react-dom@19.2.8(react@19.2.8): dependencies: - react: 19.2.7 + react: 19.2.8 scheduler: 0.27.0 react-is@17.0.2: {} react-is@18.3.1: {} - react-redux@9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1): + react-redux@9.3.0(@types/react@19.2.17)(react@19.2.8)(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.2.8 + use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 redux: 5.0.1 - react@19.2.7: {} + react@19.2.8: {} readdirp@5.0.0: {} - recharts@3.8.1(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@18.3.1)(react@19.2.7)(redux@5.0.1): + recharts@3.10.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.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.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8) clsx: 2.1.1 decimal.js-light: 2.5.1 - es-toolkit: 1.45.1 + es-toolkit: 1.50.0 eventemitter3: 5.0.4 - immer: 10.2.0 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) + immer: 11.1.15 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) react-is: 18.3.1 - react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.7)(redux@5.0.1) - reselect: 5.1.1 + react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.8)(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.6.0(react@19.2.8) victory-vendor: 37.3.6 transitivePeerDependencies: - '@types/react' @@ -3764,35 +3617,28 @@ snapshots: require-from-string@2.0.2: {} - reselect@5.1.1: {} - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - rfdc@1.4.1: {} + reselect@5.2.0: {} - rolldown@1.0.3: + rolldown@1.1.5: dependencies: - '@oxc-project/types': 0.133.0 + '@oxc-project/types': 0.139.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.3 - '@rolldown/binding-darwin-arm64': 1.0.3 - '@rolldown/binding-darwin-x64': 1.0.3 - '@rolldown/binding-freebsd-x64': 1.0.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.3 - '@rolldown/binding-linux-arm64-musl': 1.0.3 - '@rolldown/binding-linux-ppc64-gnu': 1.0.3 - '@rolldown/binding-linux-s390x-gnu': 1.0.3 - '@rolldown/binding-linux-x64-gnu': 1.0.3 - '@rolldown/binding-linux-x64-musl': 1.0.3 - '@rolldown/binding-openharmony-arm64': 1.0.3 - '@rolldown/binding-wasm32-wasi': 1.0.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.3 - '@rolldown/binding-win32-x64-msvc': 1.0.3 + '@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 saxes@6.0.0: dependencies: @@ -3804,11 +3650,11 @@ snapshots: semver@7.7.4: {} - seroval-plugins@1.5.4(seroval@1.5.4): + seroval-plugins@1.6.2(seroval@1.6.2): dependencies: - seroval: 1.5.4 + seroval: 1.6.2 - seroval@1.5.4: {} + seroval@1.6.2: {} shebang-command@2.0.0: dependencies: @@ -3818,18 +3664,6 @@ snapshots: siginfo@2.0.0: {} - signal-exit@4.1.0: {} - - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - slice-ansi@8.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - source-map-js@1.2.1: {} stackback@0.0.2: {} @@ -3838,21 +3672,6 @@ snapshots: string-argv@0.3.2: {} - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - - string-width@8.2.1: - dependencies: - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -3869,10 +3688,12 @@ snapshots: tinyexec@1.2.4: {} + tinyexec@1.3.0: {} + tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 tinyrainbow@3.1.0: {} @@ -3897,7 +3718,7 @@ snapshots: tslib@2.8.1: optional: true - tsx@4.22.4: + tsx@4.23.1: dependencies: esbuild: 0.28.1 optionalDependencies: @@ -3920,21 +3741,25 @@ snapshots: typescript@6.0.3: {} - undici-types@7.24.6: {} + undici-types@8.3.0: {} - undici@7.28.0: {} + undici@7.29.0: {} - undici@8.5.0: {} + undici@8.8.0: {} - unplugin@3.0.0: + unplugin@3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@jridgewell/remapping': 2.3.5 - picomatch: 4.0.4 + picomatch: 4.0.5 webpack-virtual-modules: 0.6.2 + optionalDependencies: + esbuild: 0.28.1 + rolldown: 1.1.5 + vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) - update-browserslist-db@1.2.3(browserslist@4.28.2): + update-browserslist-db@1.2.3(browserslist@4.28.7): dependencies: - browserslist: 4.28.2 + browserslist: 4.28.7 escalade: 3.2.0 picocolors: 1.1.1 @@ -3942,9 +3767,9 @@ snapshots: dependencies: punycode: 2.3.1 - use-sync-external-store@1.6.0(react@19.2.7): + use-sync-external-store@1.6.0(react@19.2.8): dependencies: - react: 19.2.7 + react: 19.2.8 victory-vendor@37.3.6: dependencies: @@ -3963,25 +3788,25 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0): + vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.0.3 + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.25 + rolldown: 1.1.5 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 25.9.5 + '@types/node': 26.1.0 esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 - tsx: 4.22.4 + tsx: 4.23.1 yaml: 2.9.0 - vitest@4.1.10(@types/node@25.9.5)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -3998,10 +3823,10 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@25.9.5)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0) + vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.9.5 + '@types/node': 26.1.0 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) jsdom: 29.1.1 transitivePeerDependencies: @@ -4036,18 +3861,6 @@ snapshots: word-wrap@1.2.5: {} - wrap-ansi@10.0.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 8.2.1 - strip-ansi: 7.2.0 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} @@ -4065,10 +3878,10 @@ snapshots: zod@4.4.3: {} - zustand@4.5.7(@types/react@19.2.17)(immer@11.1.4)(react@19.2.7): + zustand@4.5.7(@types/react@19.2.17)(immer@11.1.15)(react@19.2.8): dependencies: - use-sync-external-store: 1.6.0(react@19.2.7) + use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 - immer: 11.1.4 - react: 19.2.7 + immer: 11.1.15 + react: 19.2.8 From aa6c742865888d43ed1b5d69d8750c6d5e311f2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:48:17 +0200 Subject: [PATCH 47/51] chore(deps):(deps): bump the security-all group across 1 directory with 3 updates (#74) Bumps the security-all group with 3 updates in the / directory: [hono](https://github.com/honojs/hono), [js-yaml](https://github.com/nodeca/js-yaml) and [undici](https://github.com/nodejs/undici). Updates `hono` from 4.12.32 to 4.12.34 - [Release notes](https://github.com/honojs/hono/releases) - [Commits](https://github.com/honojs/hono/compare/v4.12.32...v4.12.34) Updates `js-yaml` from 5.2.1 to 5.2.2 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/5.2.1...5.2.2) Updates `undici` from 8.8.0 to 8.9.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v8.8.0...v8.9.0) --- updated-dependencies: - dependency-name: hono dependency-version: 4.12.34 dependency-type: direct:production dependency-group: security-all - dependency-name: js-yaml dependency-version: 4.3.0 dependency-type: direct:production dependency-group: security-all - dependency-name: undici dependency-version: 8.9.0 dependency-type: direct:production dependency-group: security-all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/server/package.json | 6 +++--- pnpm-lock.yaml | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 065e302..d223fe2 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -16,11 +16,11 @@ }, "dependencies": { "@hono/node-server": "^2.0.12", - "hono": "^4.12.32", + "hono": "^4.12.34", "jose": "^6.2.4", - "js-yaml": "^5.2.1", + "js-yaml": "^5.2.2", "lru-cache": "^11.5.2", - "undici": "^8.8.0" + "undici": "^8.9.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46df563..d67533a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,22 +48,22 @@ importers: dependencies: '@hono/node-server': specifier: ^2.0.12 - version: 2.0.12(hono@4.12.32) + version: 2.0.12(hono@4.12.34) hono: - specifier: ^4.12.32 - version: 4.12.32 + specifier: ^4.12.34 + version: 4.12.34 jose: specifier: ^6.2.4 version: 6.2.4 js-yaml: - specifier: ^5.2.1 - version: 5.2.1 + specifier: ^5.2.2 + version: 5.2.2 lru-cache: specifier: ^11.5.2 version: 11.5.2 undici: - specifier: ^8.8.0 - version: 8.8.0 + specifier: ^8.9.0 + version: 8.9.0 devDependencies: '@types/js-yaml': specifier: ^4.0.9 @@ -1382,8 +1382,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.32: - resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} + hono@4.12.34: + resolution: {integrity: sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -1467,8 +1467,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@5.2.1: - resolution: {integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==} + js-yaml@5.2.2: + resolution: {integrity: sha512-dayzUzKkJ1MkuUtZglSebU43utNXH0OWQByK9rKOOuYIO8M5TV1y+n8ALMdG0rdzBnfNkOmZEqrURepb0ejqBw==} hasBin: true jsdom@29.1.1: @@ -1897,8 +1897,8 @@ packages: resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} - undici@8.8.0: - resolution: {integrity: sha512-ubshXMXwF3MQIMF1y/WxZdNBnjEKeSg2wF5mcGUtU55YTw34tnVVpKRlLf7ruDXZ5344KokPVX4RBx1wJm64Bw==} + undici@8.9.0: + resolution: {integrity: sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==} engines: {node: '>=22.19.0'} unplugin@3.3.0: @@ -2414,9 +2414,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.12(hono@4.12.32)': + '@hono/node-server@2.0.12(hono@4.12.34)': dependencies: - hono: 4.12.32 + hono: 4.12.34 '@humanfs/core@0.19.1': {} @@ -3302,7 +3302,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.32: {} + hono@4.12.34: {} html-encoding-sniffer@6.0.0: dependencies: @@ -3361,7 +3361,7 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@5.2.1: + js-yaml@5.2.2: dependencies: argparse: 2.0.1 @@ -3745,7 +3745,7 @@ snapshots: undici@7.29.0: {} - undici@8.8.0: {} + undici@8.9.0: {} unplugin@3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: From 2f5bb49014672cce0e16d06c0948a35e9995c27e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:08:53 +0200 Subject: [PATCH 48/51] chore(server):(deps-dev): bump @types/node from 26.1.0 to 26.1.2 in /packages/server in the version-all group across 1 directory (#77) * chore(server):(deps-dev): bump @types/node Bumps the version-all group with 1 update in the /packages/server directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 26.1.0 to 26.1.2 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.1.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein --- packages/server/package.json | 2 +- packages/web/src/routeTree.gen.ts | 76 ++-- pnpm-lock.yaml | 683 ++++++++++++------------------ 3 files changed, 316 insertions(+), 445 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index d223fe2..8dbc044 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "@types/node": "^26.1.0", + "@types/node": "^26.1.2", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", "tsx": "^4.23.1", diff --git a/packages/web/src/routeTree.gen.ts b/packages/web/src/routeTree.gen.ts index ac2ec6d..74aa8a3 100644 --- a/packages/web/src/routeTree.gen.ts +++ b/packages/web/src/routeTree.gen.ts @@ -9,57 +9,57 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' -import { Route as LoginRouteImport } from './routes/login' import { Route as AppRouteImport } from './routes/_app' +import { Route as LoginRouteImport } from './routes/login' import { Route as AppIndexRouteImport } from './routes/_app/index' -import { Route as AppRunsRouteImport } from './routes/_app/runs' import { Route as AppRepositoriesRouteImport } from './routes/_app/repositories' +import { Route as AppRunsRouteImport } from './routes/_app/runs' import { Route as AppRepositoriesOwnerRepoRouteImport } from './routes/_app/repositories.$owner.$repo' -import { Route as AppRunsOwnerRepoRunIdRouteImport } from './routes/_app/runs_.$owner.$repo.$runId' import { Route as AppRepositoriesOwnerRepoRunsRouteImport } from './routes/_app/repositories.$owner.$repo.runs' +import { Route as AppRunsOwnerRepoRunIdRouteImport } from './routes/_app/runs_.$owner.$repo.$runId' import { Route as AppRepositoriesOwnerRepoRunsRunIdRouteImport } from './routes/_app/repositories.$owner.$repo.runs.$runId' +const AppRoute = AppRouteImport.update({ + id: '/_app', + getParentRoute: () => rootRouteImport, +} as any) const LoginRoute = LoginRouteImport.update({ id: '/login', path: '/login', getParentRoute: () => rootRouteImport, } as any) -const AppRoute = AppRouteImport.update({ - id: '/_app', - getParentRoute: () => rootRouteImport, -} as any) const AppIndexRoute = AppIndexRouteImport.update({ id: '/', path: '/', getParentRoute: () => AppRoute, } as any) -const AppRunsRoute = AppRunsRouteImport.update({ - id: '/runs', - path: '/runs', - getParentRoute: () => AppRoute, -} as any) const AppRepositoriesRoute = AppRepositoriesRouteImport.update({ id: '/repositories', path: '/repositories', getParentRoute: () => AppRoute, } as any) +const AppRunsRoute = AppRunsRouteImport.update({ + id: '/runs', + path: '/runs', + getParentRoute: () => AppRoute, +} as any) const AppRepositoriesOwnerRepoRoute = AppRepositoriesOwnerRepoRouteImport.update({ id: '/$owner/$repo', path: '/$owner/$repo', getParentRoute: () => AppRepositoriesRoute, } as any) -const AppRunsOwnerRepoRunIdRoute = AppRunsOwnerRepoRunIdRouteImport.update({ - id: '/runs_/$owner/$repo/$runId', - path: '/runs/$owner/$repo/$runId', - getParentRoute: () => AppRoute, -} as any) const AppRepositoriesOwnerRepoRunsRoute = AppRepositoriesOwnerRepoRunsRouteImport.update({ id: '/runs', path: '/runs', getParentRoute: () => AppRepositoriesOwnerRepoRoute, } as any) +const AppRunsOwnerRepoRunIdRoute = AppRunsOwnerRepoRunIdRouteImport.update({ + id: '/runs_/$owner/$repo/$runId', + path: '/runs/$owner/$repo/$runId', + getParentRoute: () => AppRoute, +} as any) const AppRepositoriesOwnerRepoRunsRunIdRoute = AppRepositoriesOwnerRepoRunsRunIdRouteImport.update({ id: '/$runId', @@ -140,13 +140,6 @@ export interface RootRouteChildren { declare module '@tanstack/react-router' { interface FileRoutesByPath { - '/login': { - id: '/login' - path: '/login' - fullPath: '/login' - preLoaderRoute: typeof LoginRouteImport - parentRoute: typeof rootRouteImport - } '/_app': { id: '/_app' path: '' @@ -154,6 +147,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppRouteImport parentRoute: typeof rootRouteImport } + '/login': { + id: '/login' + path: '/login' + fullPath: '/login' + preLoaderRoute: typeof LoginRouteImport + parentRoute: typeof rootRouteImport + } '/_app/': { id: '/_app/' path: '/' @@ -161,13 +161,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppIndexRouteImport parentRoute: typeof AppRoute } - '/_app/runs': { - id: '/_app/runs' - path: '/runs' - fullPath: '/runs' - preLoaderRoute: typeof AppRunsRouteImport - parentRoute: typeof AppRoute - } '/_app/repositories': { id: '/_app/repositories' path: '/repositories' @@ -175,6 +168,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppRepositoriesRouteImport parentRoute: typeof AppRoute } + '/_app/runs': { + id: '/_app/runs' + path: '/runs' + fullPath: '/runs' + preLoaderRoute: typeof AppRunsRouteImport + parentRoute: typeof AppRoute + } '/_app/repositories/$owner/$repo': { id: '/_app/repositories/$owner/$repo' path: '/$owner/$repo' @@ -182,13 +182,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppRepositoriesOwnerRepoRouteImport parentRoute: typeof AppRepositoriesRoute } - '/_app/runs_/$owner/$repo/$runId': { - id: '/_app/runs_/$owner/$repo/$runId' - path: '/runs/$owner/$repo/$runId' - fullPath: '/runs/$owner/$repo/$runId' - preLoaderRoute: typeof AppRunsOwnerRepoRunIdRouteImport - parentRoute: typeof AppRoute - } '/_app/repositories/$owner/$repo/runs': { id: '/_app/repositories/$owner/$repo/runs' path: '/runs' @@ -196,6 +189,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppRepositoriesOwnerRepoRunsRouteImport parentRoute: typeof AppRepositoriesOwnerRepoRoute } + '/_app/runs_/$owner/$repo/$runId': { + id: '/_app/runs_/$owner/$repo/$runId' + path: '/runs/$owner/$repo/$runId' + fullPath: '/runs/$owner/$repo/$runId' + preLoaderRoute: typeof AppRunsOwnerRepoRunIdRouteImport + parentRoute: typeof AppRoute + } '/_app/repositories/$owner/$repo/runs/$runId': { id: '/_app/repositories/$owner/$repo/runs/$runId' path: '/$runId' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d67533a..de4b9b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,41 +36,41 @@ importers: version: 9.1.7 lint-staged: specifier: ^17.1.1 - version: 17.1.1 + version: 17.3.0 typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages/server: dependencies: '@hono/node-server': specifier: ^2.0.12 - version: 2.0.12(hono@4.12.34) + version: 2.1.0(hono@4.13.0) hono: specifier: ^4.12.34 - version: 4.12.34 + version: 4.13.0 jose: specifier: ^6.2.4 - version: 6.2.4 + version: 6.2.8 js-yaml: specifier: ^5.2.2 - version: 5.2.2 + version: 5.2.3 lru-cache: specifier: ^11.5.2 version: 11.5.2 undici: specifier: ^8.9.0 - version: 8.9.0 + version: 8.10.0 devDependencies: '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 '@types/node': - specifier: ^26.1.0 - version: 26.1.0 + specifier: ^26.1.2 + version: 26.1.2 '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.10(vitest@4.1.10) @@ -79,7 +79,7 @@ importers: version: 10.7.0(jiti@2.7.0) tsx: specifier: ^4.23.1 - version: 4.23.1 + version: 4.23.7 typescript: specifier: 'catalog:' version: 6.0.3 @@ -88,7 +88,7 @@ importers: version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages/web: dependencies: @@ -106,10 +106,10 @@ importers: version: 5.101.4(@tanstack/react-query@5.101.4(react@19.2.8))(react@19.2.8) '@tanstack/react-router': specifier: ^1.170.18 - version: 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + version: 1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@xyflow/react': specifier: ^12.11.1 - version: 12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.15)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + version: 12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.11)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) idb-keyval: specifier: ^6.3.0 version: 6.3.0 @@ -121,17 +121,17 @@ importers: version: 19.2.8(react@19.2.8) recharts: specifier: ^3.10.0 - version: 3.10.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1) + version: 3.10.1(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1) zod: specifier: ^4.4.3 version: 4.4.3 devDependencies: '@tanstack/react-router-devtools': specifier: ^1.167.0 - version: 1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + version: 1.167.0(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.16)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@tanstack/router-vite-plugin': specifier: ^1.167.23 - version: 1.167.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 1.167.24(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -146,7 +146,7 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^6.0.4 - version: 6.0.4(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 6.0.5(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 'catalog:' version: 4.1.10(vitest@4.1.10) @@ -167,10 +167,10 @@ importers: version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vite: specifier: ^8.1.5 - version: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + version: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages: @@ -204,8 +204,8 @@ packages: resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.8': - resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.29.7': @@ -226,6 +226,10 @@ packages: peerDependencies: '@babel/core': ^7.29.7 + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -252,11 +256,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.29.8': - resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -269,16 +268,16 @@ packages: resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.8': - resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.8': - resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -331,15 +330,6 @@ packages: '@dagrejs/graphlib@4.0.1': resolution: {integrity: sha512-IvcV6FduIIAmLwnH+yun+QtV36SC7mERqa86aClNqmMN09WhmPPYU8ckHrZBozErf+UvHPWOTJYaGYiIcs0DgA==} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - - '@emnapi/wasi-threads@1.2.2': - resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} @@ -535,8 +525,8 @@ packages: '@noble/hashes': optional: true - '@hono/node-server@2.0.12': - resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} + '@hono/node-server@2.1.0': + resolution: {integrity: sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==} engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -573,18 +563,11 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/wasm-runtime@1.2.2': - resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} - peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 - - '@oxc-project/types@0.139.0': - resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.142.0': + resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} - '@reduxjs/toolkit@2.12.0': - resolution: {integrity: sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==} + '@reduxjs/toolkit@2.11.2': + resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || ^18 || ^19 react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 @@ -594,97 +577,92 @@ packages: react-redux: optional: true - '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + '@rolldown/binding-android-arm64@1.2.2': + resolution: {integrity: sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==} 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.2': + resolution: {integrity: sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==} 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.2': + resolution: {integrity: sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==} 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.2': + resolution: {integrity: sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==} 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.2': + resolution: {integrity: sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==} 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.2': + resolution: {integrity: sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==} 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.2': + resolution: {integrity: sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==} 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.2': + resolution: {integrity: sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==} 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.2': + resolution: {integrity: sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==} 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.2': + resolution: {integrity: sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==} 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.2': + resolution: {integrity: sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==} 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.2': + resolution: {integrity: sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==} 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.2': + resolution: {integrity: sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==} 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.2': + resolution: {integrity: sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -734,8 +712,8 @@ packages: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.170.18': - resolution: {integrity: sha512-wpbGYZEp/fmz1q4bn7BD8VZ+/VZ7GBqSJv5V969pU+chP8y7dquWDmKTFMohvUegb9lg12m1uPVvD6kB2wORvQ==} + '@tanstack/react-router@1.170.19': + resolution: {integrity: sha512-cK7VUsc9+8gYZMqwJjCAhrmL9wPhkwxEcZ7cxlHdBjjmqHbZyNxXAml/KfLmSuxRDQGVk2iofpoHclDTSrkmmg==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -747,8 +725,8 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.171.15': - resolution: {integrity: sha512-IILCDcLaItMZQ2jEmCABHY1Nhjjn5XUvwpQp3e4Nmu+vfg0BgYFuu/QASz2SwE2ZNbVMrvt8X/wxa+Gg5aErxA==} + '@tanstack/router-core@1.171.16': + resolution: {integrity: sha512-/qwawP5a45puA9DQtG8syrChWCV7uGMYs1p5rwgrICgiS/0pHo7zNOFyfVI02J1azWhCfFc6w6+SuiivPESYAA==} engines: {node: '>=20.19'} '@tanstack/router-devtools-core@1.168.0': @@ -761,16 +739,16 @@ packages: csstype: optional: true - '@tanstack/router-generator@1.167.21': - resolution: {integrity: sha512-m3oXZyienj8owialdyoZ0txHQrnEx/Ra+D9kWtar5fC2cWZr5Pvxl86VY2mX5RRLC5QLKLeRGT1x4HV95wHVDQ==} + '@tanstack/router-generator@1.167.22': + resolution: {integrity: sha512-tiKrH6xuCdTfmm4UuHSpLsZ5q2pwmhNbGpExp5u/CCRObjQM5nxz8Dce/X3w86ST6VSZFQMBNjLcsUMnVlJw/Q==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.168.23': - resolution: {integrity: sha512-0+PIcvnaAimFwjoEIeV3h7LKjzC8zNnp7pH2UamdKwQ9QlY99WU9V0Xl0zbM0i9hrUa/mKgWPDAzELmPUu5fMA==} + '@tanstack/router-plugin@1.168.24': + resolution: {integrity: sha512-FfPW45gfZHDC25AHo4MJB3ZljXEKFJenEgIDTELwnI6FtS90vXTQXjOjdTVNs/7B4R8+wLf7nWVrPSvBMp7zWw==} engines: {node: '>=20.19'} peerDependencies: '@rsbuild/core': '>=1.0.2 || ^2.0.0' - '@tanstack/react-router': ^1.170.18 + '@tanstack/react-router': ^1.170.19 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' @@ -790,8 +768,8 @@ packages: resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==} engines: {node: '>=20.19'} - '@tanstack/router-vite-plugin@1.167.23': - resolution: {integrity: sha512-MnkK6OIwtMtEeThZTZFMsClQeZCL7apA9kmj8h3roRS+hws5ttGqmy2gkxRlK5EQIfz2ePbefRey0us/qA3hLQ==} + '@tanstack/router-vite-plugin@1.167.24': + resolution: {integrity: sha512-n6E+scCfwLGjBDlUoQtkSZR1M2UhRC4tNdODjf6wPfg1kKGuvM1mHcArqLE2wG/FP4+9xFcj+dPaF69eUZWXQw==} engines: {node: '>=20.19'} '@tanstack/store@0.9.3': @@ -824,9 +802,6 @@ packages: '@types/react-dom': optional: true - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} - '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -887,8 +862,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@26.1.0': - resolution: {integrity: sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==} + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -960,8 +935,8 @@ packages: resolution: {integrity: sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react@6.0.4': - resolution: {integrity: sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==} + '@vitejs/plugin-react@6.0.5': + resolution: {integrity: sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 @@ -1048,8 +1023,8 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansis@4.3.1: - resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} argparse@2.0.1: @@ -1076,8 +1051,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.11.12: - resolution: {integrity: sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==} + baseline-browser-mapping@2.10.19: + resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==} engines: {node: '>=6.0.0'} hasBin: true @@ -1088,13 +1063,13 @@ packages: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} - browserslist@4.28.7: - resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - caniuse-lite@1.0.30001806: - resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + caniuse-lite@1.0.30001788: + resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} @@ -1237,8 +1212,8 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - electron-to-chromium@1.5.401: - resolution: {integrity: sha512-H6ViHN68nGYlChEvlIU67fn8O2/tpbWQPwck98yaJmh+08LSvHiydzDQ6oXNccLU3kNRVIRS9A4mA7CG+i6fLQ==} + electron-to-chromium@1.5.339: + resolution: {integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==} entities@8.0.0: resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} @@ -1247,8 +1222,8 @@ packages: es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - es-toolkit@1.50.0: - resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} + es-toolkit@1.45.1: + resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} @@ -1382,8 +1357,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.34: - resolution: {integrity: sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==} + hono@4.13.0: + resolution: {integrity: sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -1409,8 +1384,8 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - immer@11.1.15: - resolution: {integrity: sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ==} + immer@11.1.11: + resolution: {integrity: sha512-qzXuyXAkPySAGYkfsAwodDPWT8Zm7/Uo5BNt4BjhMhG5WlWyZZ4wQqnWwdS8kjlQ1Cwu6gjw3A6+0gTQwlyYtw==} imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -1435,8 +1410,8 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - isbot@5.2.1: - resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==} + isbot@5.1.38: + resolution: {integrity: sha512-Cus2702JamTNMEY4zTP+TShgq/3qzjvGcBC4XMOV45BLaxD4iUFENkqu7ZhFeSzwNsCSZLjnGlihDQznnpnEEA==} engines: {node: '>=18'} isexe@2.0.0: @@ -1458,8 +1433,8 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - jose@6.2.4: - resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==} + jose@6.2.8: + resolution: {integrity: sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==} js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -1467,8 +1442,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@5.2.2: - resolution: {integrity: sha512-dayzUzKkJ1MkuUtZglSebU43utNXH0OWQByK9rKOOuYIO8M5TV1y+n8ALMdG0rdzBnfNkOmZEqrURepb0ejqBw==} + js-yaml@5.2.3: + resolution: {integrity: sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==} hasBin: true jsdom@29.1.1: @@ -1580,8 +1555,8 @@ packages: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} - lint-staged@17.1.1: - resolution: {integrity: sha512-FnHWpSe5cPRtrDG+soOuNdBxb4XQb2gN5EqpEWKdweyqyOfpl4QSjbrz3ilcIf0WXmkiNQGZZRQ23R5YtB3TEw==} + lint-staged@17.3.0: + resolution: {integrity: sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==} engines: {node: '>=22.22.1'} hasBin: true @@ -1632,9 +1607,8 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - node-releases@2.0.52: - resolution: {integrity: sha512-MRlTqhAfoMx/4mhEbPo3Hi02g9LJZaJkka69V6h67Cb1gjrAG0jsTE4CZX1eptNx+VCAwJmfpnDIF4P0Nh1A7A==} - engines: {node: '>=18'} + node-releases@2.0.37: + resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} obug@2.1.3: resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} @@ -1669,10 +1643,6 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} - picomatch@4.0.5: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} @@ -1685,8 +1655,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.9.6: - resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} + prettier@3.8.3: + resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} engines: {node: '>=14'} hasBin: true @@ -1709,8 +1679,8 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-redux@9.3.0: - resolution: {integrity: sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==} + react-redux@9.2.0: + resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} peerDependencies: '@types/react': ^18.2.25 || ^19 react: ^18.0 || ^19 @@ -1729,8 +1699,8 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} - recharts@3.10.0: - resolution: {integrity: sha512-wulMvfncpIlmu2uFtRU/mE5/+NiVtASXkw2KdwJTdHs3WsASX0WxZlX+rpKgyn5BDbIhkPtCpUKkB9XNK5KE0w==} + 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 @@ -1756,8 +1726,8 @@ packages: reselect@5.2.0: resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==} - rolldown@1.1.5: - resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + rolldown@1.2.2: + resolution: {integrity: sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1777,14 +1747,14 @@ packages: engines: {node: '>=10'} hasBin: true - seroval-plugins@1.6.2: - resolution: {integrity: sha512-TfxuUjlbBESzUOWdTkTKqvSmav0ABym+itetDXLK6mDz8SmrpdI30aF8RTXE8Bvq+tH/1yIDkvy3W0lfQb1ipQ==} + seroval-plugins@1.5.4: + resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.6.2: - resolution: {integrity: sha512-mPT+SD2TrlB6wvte1KkYOYUkubaTbd6pZ/6Kk3C9nxzrHmCZyhxOO7XGAeL7f+yLKZglzGtM9odUVvg/EhO+vQ==} + seroval@1.5.4: + resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} engines: {node: '>=10'} shebang-command@2.0.0: @@ -1833,10 +1803,6 @@ packages: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} - tinyexec@1.3.0: - resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} - engines: {node: '>=18'} - tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -1866,11 +1832,8 @@ packages: peerDependencies: typescript: '>=4.8.4' - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tsx@4.23.1: - resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + tsx@4.23.7: + resolution: {integrity: sha512-3f/u/+UDCNQ7iwUZW9FCMnNGIHzElGJYh0S/yy8IvWSsn5O7fEO/897FaG7FA2W8yryiRyuwXZ1PYLAKYaqSuQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -1893,46 +1856,17 @@ packages: undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - undici@7.29.0: - resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} - undici@8.9.0: - resolution: {integrity: sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==} + undici@8.10.0: + resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==} engines: {node: '>=22.19.0'} - unplugin@3.3.0: - resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==} + unplugin@3.0.0: + resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - '@farmfe/core': '*' - '@rspack/core': '*' - bun-types-no-globals: '*' - esbuild: ^0.28.1 - rolldown: '*' - rollup: '*' - unloader: '*' - vite: '*' - webpack: '*' - peerDependenciesMeta: - '@farmfe/core': - optional: true - '@rspack/core': - optional: true - bun-types-no-globals: - optional: true - esbuild: - optional: true - rolldown: - optional: true - rollup: - optional: true - unloader: - optional: true - vite: - optional: true - webpack: - optional: true update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -1951,13 +1885,13 @@ packages: victory-vendor@37.3.6: resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - vite@8.1.5: - resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} + vite@8.2.0: + resolution: {integrity: sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==} 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.4.0 esbuild: ^0.28.1 jiti: '>=1.21.0' less: ^4.0.0 @@ -2146,14 +2080,14 @@ snapshots: '@babel/core@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.8 + '@babel/generator': 7.29.7 '@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.8 + '@babel/parser': 7.29.7 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.8 - '@babel/types': 7.29.8 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -2163,10 +2097,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.8': + '@babel/generator@7.29.7': dependencies: - '@babel/parser': 7.29.8 - '@babel/types': 7.29.8 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -2175,7 +2109,7 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.7 + browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -2183,8 +2117,8 @@ snapshots: '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.8 - '@babel/types': 7.29.8 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -2193,10 +2127,12 @@ snapshots: '@babel/core': 7.29.7 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.8 + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -2206,19 +2142,15 @@ snapshots: '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/types': 7.29.8 + '@babel/types': 7.29.7 '@babel/parser@7.29.2': dependencies: - '@babel/types': 7.29.8 + '@babel/types': 7.29.0 '@babel/parser@7.29.7': dependencies: - '@babel/types': 7.29.8 - - '@babel/parser@7.29.8': - dependencies: - '@babel/types': 7.29.8 + '@babel/types': 7.29.7 '@babel/runtime@7.29.2': {} @@ -2227,27 +2159,27 @@ snapshots: '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.8 - '@babel/types': 7.29.8 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 - '@babel/traverse@7.29.8': + '@babel/traverse@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.8 + '@babel/generator': 7.29.7 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.8 + '@babel/parser': 7.29.7 '@babel/template': 7.29.7 - '@babel/types': 7.29.8 + '@babel/types': 7.29.7 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.29.7': + '@babel/types@7.29.0': dependencies: - '@babel/helper-string-parser': 7.29.7 + '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.29.7 - '@babel/types@7.29.8': + '@babel/types@7.29.7': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 @@ -2288,22 +2220,6 @@ snapshots: '@dagrejs/graphlib@4.0.1': {} - '@emnapi/core@1.11.1': - dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.11.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.2.2': - dependencies: - tslib: 2.8.1 - optional: true - '@esbuild/aix-ppc64@0.28.1': optional: true @@ -2414,9 +2330,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@2.0.12(hono@4.12.34)': + '@hono/node-server@2.1.0(hono@4.13.0)': dependencies: - hono: 4.12.34 + hono: 4.13.0 '@humanfs/core@0.19.1': {} @@ -2448,74 +2364,60 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@tybys/wasm-util': 0.10.3 - optional: true + '@oxc-project/types@0.142.0': {} - '@oxc-project/types@0.139.0': {} - - '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 - immer: 11.1.15 + immer: 11.1.11 redux: 5.0.1 redux-thunk: 3.1.0(redux@5.0.1) reselect: 5.2.0 optionalDependencies: react: 19.2.8 - react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1) - - '@rolldown/binding-android-arm64@1.1.5': - optional: true + react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1) - '@rolldown/binding-darwin-arm64@1.1.5': + '@rolldown/binding-android-arm64@1.2.2': optional: true - '@rolldown/binding-darwin-x64@1.1.5': + '@rolldown/binding-darwin-arm64@1.2.2': optional: true - '@rolldown/binding-freebsd-x64@1.1.5': + '@rolldown/binding-darwin-x64@1.2.2': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + '@rolldown/binding-freebsd-x64@1.2.2': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.5': + '@rolldown/binding-linux-arm-gnueabihf@1.2.2': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.5': + '@rolldown/binding-linux-arm64-gnu@1.2.2': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.5': + '@rolldown/binding-linux-arm64-musl@1.2.2': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.5': + '@rolldown/binding-linux-ppc64-gnu@1.2.2': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.5': + '@rolldown/binding-linux-s390x-gnu@1.2.2': optional: true - '@rolldown/binding-linux-x64-musl@1.1.5': + '@rolldown/binding-linux-x64-gnu@1.2.2': optional: true - '@rolldown/binding-openharmony-arm64@1.1.5': + '@rolldown/binding-linux-x64-musl@1.2.2': 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.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@rolldown/binding-openharmony-arm64@1.2.2': optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.5': + '@rolldown/binding-win32-arm64-msvc@1.2.2': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.5': + '@rolldown/binding-win32-x64-msvc@1.2.2': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -2548,23 +2450,23 @@ snapshots: '@tanstack/query-core': 5.101.4 react: 19.2.8 - '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.16)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: - '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - '@tanstack/router-devtools-core': 1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3) + '@tanstack/react-router': 1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-devtools-core': 1.168.0(@tanstack/router-core@1.171.16)(csstype@3.2.3) react: 19.2.8 react-dom: 19.2.8(react@19.2.8) optionalDependencies: - '@tanstack/router-core': 1.171.15 + '@tanstack/router-core': 1.171.16 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@tanstack/history': 1.162.0 '@tanstack/react-store': 0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - '@tanstack/router-core': 1.171.15 - isbot: 5.2.1 + '@tanstack/router-core': 1.171.16 + isbot: 5.1.38 react: 19.2.8 react-dom: 19.2.8(react@19.2.8) @@ -2575,64 +2477,57 @@ snapshots: react-dom: 19.2.8(react@19.2.8) use-sync-external-store: 1.6.0(react@19.2.8) - '@tanstack/router-core@1.171.15': + '@tanstack/router-core@1.171.16': dependencies: '@tanstack/history': 1.162.0 cookie-es: 3.1.1 - seroval: 1.6.2 - seroval-plugins: 1.6.2(seroval@1.6.2) + seroval: 1.5.4 + seroval-plugins: 1.5.4(seroval@1.5.4) - '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.16)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.171.15 + '@tanstack/router-core': 1.171.16 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.167.21': + '@tanstack/router-generator@1.167.22': dependencies: - '@babel/types': 7.29.8 - '@tanstack/router-core': 1.171.15 + '@babel/types': 7.29.7 + '@tanstack/router-core': 1.171.16 '@tanstack/router-utils': 1.162.2 '@tanstack/virtual-file-routes': 1.162.0 jiti: 2.7.0 magic-string: 0.30.21 - prettier: 3.9.6 + prettier: 3.8.3 zod: 4.4.3 transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + '@tanstack/router-plugin@1.168.24(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7 '@babel/template': 7.29.7 - '@babel/types': 7.29.8 - '@tanstack/router-core': 1.171.15 - '@tanstack/router-generator': 1.167.21 + '@babel/types': 7.29.7 + '@tanstack/router-core': 1.171.16 + '@tanstack/router-generator': 1.167.22 '@tanstack/router-utils': 1.162.2 chokidar: 5.0.0 - unplugin: 3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + unplugin: 3.0.0 zod: 4.4.3 optionalDependencies: - '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + '@tanstack/react-router': 1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) transitivePeerDependencies: - - '@farmfe/core' - - '@rspack/core' - - bun-types-no-globals - - esbuild - - rolldown - - rollup - supports-color - - unloader '@tanstack/router-utils@1.162.2': dependencies: - '@babel/generator': 7.29.8 - '@babel/parser': 7.29.8 - '@babel/types': 7.29.8 - ansis: 4.3.1 + '@babel/generator': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + ansis: 4.2.0 babel-dead-code-elimination: 1.0.12 diff: 8.0.4 pathe: 2.0.3 @@ -2640,20 +2535,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-vite-plugin@1.167.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + '@tanstack/router-vite-plugin@1.167.24(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0))': dependencies: - '@tanstack/router-plugin': 1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@tanstack/router-plugin': 1.168.24(@tanstack/react-router@1.170.19(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) transitivePeerDependencies: - - '@farmfe/core' - '@rsbuild/core' - - '@rspack/core' - '@tanstack/react-router' - - bun-types-no-globals - - esbuild - - rolldown - - rollup - supports-color - - unloader - vite - vite-plugin-solid - webpack @@ -2692,11 +2580,6 @@ snapshots: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@tybys/wasm-util@0.10.3': - dependencies: - tslib: 2.8.1 - optional: true - '@types/aria-query@5.0.4': {} '@types/chai@5.2.3': @@ -2753,7 +2636,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@26.1.0': + '@types/node@26.1.2': dependencies: undici-types: 8.3.0 @@ -2858,10 +2741,10 @@ snapshots: '@typescript-eslint/types': 8.63.0 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.4(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.5(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': dependencies: @@ -2875,7 +2758,7 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) '@vitest/expect@4.1.10': dependencies: @@ -2886,13 +2769,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -2918,13 +2801,13 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@xyflow/react@12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.15)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@xyflow/react@12.11.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(immer@11.1.11)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@xyflow/system': 0.0.79 classcat: 5.0.5 react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - zustand: 4.5.7(@types/react@19.2.17)(immer@11.1.15)(react@19.2.8) + zustand: 4.5.7(@types/react@19.2.17)(immer@11.1.11)(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) @@ -2960,7 +2843,7 @@ snapshots: ansi-styles@5.2.0: {} - ansis@4.3.1: {} + ansis@4.2.0: {} argparse@2.0.1: {} @@ -2981,15 +2864,15 @@ snapshots: babel-dead-code-elimination@1.0.12: dependencies: '@babel/core': 7.29.7 - '@babel/parser': 7.29.8 - '@babel/traverse': 7.29.8 - '@babel/types': 7.29.8 + '@babel/parser': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color balanced-match@4.0.4: {} - baseline-browser-mapping@2.11.12: {} + baseline-browser-mapping@2.10.19: {} bidi-js@1.0.3: dependencies: @@ -2999,15 +2882,15 @@ snapshots: dependencies: balanced-match: 4.0.4 - browserslist@4.28.7: + browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.11.12 - caniuse-lite: 1.0.30001806 - electron-to-chromium: 1.5.401 - node-releases: 2.0.52 - update-browserslist-db: 1.2.3(browserslist@4.28.7) + baseline-browser-mapping: 2.10.19 + caniuse-lite: 1.0.30001788 + electron-to-chromium: 1.5.339 + node-releases: 2.0.37 + update-browserslist-db: 1.2.3(browserslist@4.28.2) - caniuse-lite@1.0.30001806: {} + caniuse-lite@1.0.30001788: {} chai@6.2.2: {} @@ -3129,13 +3012,13 @@ snapshots: dom-accessibility-api@0.6.3: {} - electron-to-chromium@1.5.401: {} + electron-to-chromium@1.5.339: {} entities@8.0.0: {} es-module-lexer@2.1.0: {} - es-toolkit@1.50.0: {} + es-toolkit@1.45.1: {} esbuild@0.28.1: optionalDependencies: @@ -3302,7 +3185,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.34: {} + hono@4.13.0: {} html-encoding-sniffer@6.0.0: dependencies: @@ -3320,7 +3203,7 @@ snapshots: ignore@7.0.5: {} - immer@11.1.15: {} + immer@11.1.11: {} imurmurhash@0.1.4: {} @@ -3336,7 +3219,7 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - isbot@5.2.1: {} + isbot@5.1.38: {} isexe@2.0.0: {} @@ -3355,13 +3238,13 @@ snapshots: jiti@2.7.0: {} - jose@6.2.4: {} + jose@6.2.8: {} js-tokens@10.0.0: {} js-tokens@4.0.0: {} - js-yaml@5.2.2: + js-yaml@5.2.3: dependencies: argparse: 2.0.1 @@ -3382,7 +3265,7 @@ snapshots: saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.29.0 + undici: 7.28.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -3459,11 +3342,11 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 - lint-staged@17.1.1: + lint-staged@17.3.0: dependencies: picomatch: 4.0.5 string-argv: 0.3.2 - tinyexec: 1.3.0 + tinyexec: 1.2.4 optionalDependencies: yaml: 2.9.0 @@ -3507,7 +3390,7 @@ snapshots: natural-compare@1.4.0: {} - node-releases@2.0.52: {} + node-releases@2.0.37: {} obug@2.1.3: {} @@ -3540,8 +3423,6 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.4: {} - picomatch@4.0.5: {} postcss@8.5.25: @@ -3552,7 +3433,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.9.6: {} + prettier@3.8.3: {} pretty-format@27.5.1: dependencies: @@ -3571,7 +3452,7 @@ snapshots: react-is@18.3.1: {} - react-redux@9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 react: 19.2.8 @@ -3584,18 +3465,18 @@ snapshots: readdirp@5.0.0: {} - recharts@3.10.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1): + recharts@3.10.1(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1))(react@19.2.8) clsx: 2.1.1 decimal.js-light: 2.5.1 - es-toolkit: 1.50.0 + es-toolkit: 1.45.1 eventemitter3: 5.0.4 - immer: 11.1.15 + immer: 11.1.11 react: 19.2.8 react-dom: 19.2.8(react@19.2.8) react-is: 18.3.1 - react-redux: 9.3.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.17)(react@19.2.8)(redux@5.0.1) reselect: 5.2.0 tiny-invariant: 1.3.3 use-sync-external-store: 1.6.0(react@19.2.8) @@ -3619,26 +3500,25 @@ snapshots: reselect@5.2.0: {} - rolldown@1.1.5: + rolldown@1.2.2: dependencies: - '@oxc-project/types': 0.139.0 + '@oxc-project/types': 0.142.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 + '@rolldown/binding-android-arm64': 1.2.2 + '@rolldown/binding-darwin-arm64': 1.2.2 + '@rolldown/binding-darwin-x64': 1.2.2 + '@rolldown/binding-freebsd-x64': 1.2.2 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.2 + '@rolldown/binding-linux-arm64-gnu': 1.2.2 + '@rolldown/binding-linux-arm64-musl': 1.2.2 + '@rolldown/binding-linux-ppc64-gnu': 1.2.2 + '@rolldown/binding-linux-s390x-gnu': 1.2.2 + '@rolldown/binding-linux-x64-gnu': 1.2.2 + '@rolldown/binding-linux-x64-musl': 1.2.2 + '@rolldown/binding-openharmony-arm64': 1.2.2 + '@rolldown/binding-win32-arm64-msvc': 1.2.2 + '@rolldown/binding-win32-x64-msvc': 1.2.2 saxes@6.0.0: dependencies: @@ -3650,11 +3530,11 @@ snapshots: semver@7.7.4: {} - seroval-plugins@1.6.2(seroval@1.6.2): + seroval-plugins@1.5.4(seroval@1.5.4): dependencies: - seroval: 1.6.2 + seroval: 1.5.4 - seroval@1.6.2: {} + seroval@1.5.4: {} shebang-command@2.0.0: dependencies: @@ -3688,8 +3568,6 @@ snapshots: tinyexec@1.2.4: {} - tinyexec@1.3.0: {} - tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) @@ -3715,10 +3593,7 @@ snapshots: dependencies: typescript: 6.0.3 - tslib@2.8.1: - optional: true - - tsx@4.23.1: + tsx@4.23.7: dependencies: esbuild: 0.28.1 optionalDependencies: @@ -3743,23 +3618,19 @@ snapshots: undici-types@8.3.0: {} - undici@7.29.0: {} + undici@7.28.0: {} - undici@8.9.0: {} + undici@8.10.0: {} - unplugin@3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + unplugin@3.0.0: dependencies: '@jridgewell/remapping': 2.3.5 picomatch: 4.0.5 webpack-virtual-modules: 0.6.2 - optionalDependencies: - esbuild: 0.28.1 - rolldown: 1.1.5 - vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) - update-browserslist-db@1.2.3(browserslist@4.28.7): + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: - browserslist: 4.28.7 + browserslist: 4.28.2 escalade: 3.2.0 picocolors: 1.1.1 @@ -3788,25 +3659,25 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0): + vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 postcss: 8.5.25 - rolldown: 1.1.5 + rolldown: 1.2.2 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 26.1.0 + '@types/node': 26.1.2 esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 - tsx: 4.23.1 + tsx: 4.23.7 yaml: 2.9.0 - vitest@4.1.10(@types/node@26.1.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -3817,16 +3688,16 @@ snapshots: magic-string: 0.30.21 obug: 2.1.3 pathe: 2.0.3 - picomatch: 4.0.4 + picomatch: 4.0.5 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.1.5(@types/node@26.1.0)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 26.1.0 + '@types/node': 26.1.2 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) jsdom: 29.1.1 transitivePeerDependencies: @@ -3878,10 +3749,10 @@ snapshots: zod@4.4.3: {} - zustand@4.5.7(@types/react@19.2.17)(immer@11.1.15)(react@19.2.8): + zustand@4.5.7(@types/react@19.2.17)(immer@11.1.11)(react@19.2.8): dependencies: use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: '@types/react': 19.2.17 - immer: 11.1.15 + immer: 11.1.11 react: 19.2.8 From 530324fc3a8606a625fc5d0e39e189f82970adeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:41:01 +0200 Subject: [PATCH 49/51] chore(web):(deps): bump recharts from 3.10.0 to 3.10.1 in /packages/web in the version-all group across 1 directory (#76) * chore(web):(deps): bump recharts Bumps the version-all group with 1 update in the /packages/web directory: [recharts](https://github.com/recharts/recharts). Updates `recharts` from 3.10.0 to 3.10.1 - [Release notes](https://github.com/recharts/recharts/releases) - [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md) - [Commits](https://github.com/recharts/recharts/compare/v3.10.0...v3.10.1) --- updated-dependencies: - dependency-name: recharts dependency-version: 3.10.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-all ... Signed-off-by: dependabot[bot] * chore: update pnpm-lock.yaml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Epperlein Co-authored-by: Claude Opus 4.6 (1M context) --- packages/web/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web/package.json b/packages/web/package.json index dec3dd4..274b324 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -23,7 +23,7 @@ "idb-keyval": "^6.3.0", "react": "^19.2.8", "react-dom": "^19.2.8", - "recharts": "^3.10.0", + "recharts": "^3.10.1", "zod": "^4.4.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de4b9b9..dfb4584 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,7 +120,7 @@ importers: specifier: ^19.2.8 version: 19.2.8(react@19.2.8) recharts: - specifier: ^3.10.0 + specifier: ^3.10.1 version: 3.10.1(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@18.3.1)(react@19.2.8)(redux@5.0.1) zod: specifier: ^4.4.3 From 78cba429a8c474f05bfbb60fef4219ea24ab8ca7 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Wed, 5 Aug 2026 13:04:31 +0200 Subject: [PATCH 50/51] fix: brace-expansion-undici (#78) --- package.json | 2 +- packages/web/package.json | 2 +- pnpm-lock.yaml | 150 ++++++++++++++++++-------------------- 3 files changed, 74 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index d7019f6..8b157f9 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ } }, "overrides": { - "brace-expansion": "^5.0.6", + "brace-expansion": "^5.0.9", "esbuild": "^0.28.1", "@babel/core": "^7.29.7" }, diff --git a/packages/web/package.json b/packages/web/package.json index 274b324..bfffd62 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -37,7 +37,7 @@ "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", "eslint-plugin-react-hooks": "^7.1.1", - "jsdom": "^29.1.1", + "jsdom": "^30.0.1", "typescript": "catalog:", "typescript-eslint": "catalog:", "vite": "^8.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfb4584..c4955ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,7 +23,7 @@ catalogs: version: 4.1.10 overrides: - brace-expansion: ^5.0.6 + brace-expansion: ^5.0.9 esbuild: ^0.28.1 '@babel/core': ^7.29.7 @@ -42,7 +42,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@30.0.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages/server: dependencies: @@ -88,7 +88,7 @@ importers: version: 8.63.0(eslint@10.7.0(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@30.0.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages/web: dependencies: @@ -157,8 +157,8 @@ importers: specifier: ^7.1.1 version: 7.1.1(eslint@10.7.0(jiti@2.7.0)) jsdom: - specifier: ^29.1.1 - version: 29.1.1 + specifier: ^30.0.1 + version: 30.0.1 typescript: specifier: 'catalog:' version: 6.0.3 @@ -170,27 +170,20 @@ importers: version: 8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@30.0.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) packages: '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - '@asamuzakjp/css-color@5.1.11': - resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/dom-selector@7.1.1': - resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@asamuzakjp/css-color@6.0.5': + resolution: {integrity: sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==} + engines: {node: ^22.13.0 || >=24.0.0} - '@asamuzakjp/generational-cache@1.0.1': - resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@asamuzakjp/dom-selector@8.3.2': + resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==} + engines: {node: ^22.13.0 || >=24.0.0} '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} @@ -288,19 +281,19 @@ packages: resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true - '@csstools/color-helpers@6.0.2': - resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} engines: {node: '>=20.19.0'} - '@csstools/css-calc@3.2.0': - resolution: {integrity: sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==} + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-color-parser@4.1.0': - resolution: {integrity: sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==} + '@csstools/css-color-parser@4.1.10': + resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 @@ -312,8 +305,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.3': - resolution: {integrity: sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==} + '@csstools/css-syntax-patches-for-csstree@1.1.7': + resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: @@ -516,8 +509,8 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@exodus/bytes@1.15.0': - resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: '@noble/hashes': ^1.8.0 || ^2.0.0 @@ -1059,9 +1052,9 @@ packages: bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - 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.2: resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} @@ -1446,11 +1439,11 @@ packages: resolution: {integrity: sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==} hasBin: true - jsdom@29.1.1: - resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + jsdom@30.0.1: + resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} peerDependencies: - canvas: ^3.0.0 + canvas: ^3.2.3 peerDependenciesMeta: canvas: optional: true @@ -1818,8 +1811,8 @@ packages: resolution: {integrity: sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==} hasBin: true - tough-cookie@6.0.1: - resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} tr46@6.0.0: @@ -1856,10 +1849,6 @@ packages: undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} - engines: {node: '>=20.18.1'} - undici@8.10.0: resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==} engines: {node: '>=22.19.0'} @@ -1988,6 +1977,10 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@17.1.0: + resolution: {integrity: sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==} + engines: {node: ^22.14.0 || >=24.0.0} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2049,25 +2042,20 @@ snapshots: '@adobe/css-tools@4.4.4': {} - '@asamuzakjp/css-color@5.1.11': + '@asamuzakjp/css-color@6.0.5': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@csstools/css-calc': 3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.5.2 - '@asamuzakjp/dom-selector@7.1.1': + '@asamuzakjp/dom-selector@8.3.2': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@asamuzakjp/nwsapi': 2.3.9 bidi-js: 1.0.3 css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 - - '@asamuzakjp/generational-cache@1.0.1': {} - - '@asamuzakjp/nwsapi@2.3.9': {} + lru-cache: 11.5.2 '@babel/code-frame@7.29.7': dependencies: @@ -2190,17 +2178,17 @@ snapshots: dependencies: css-tree: 3.2.1 - '@csstools/color-helpers@6.0.2': {} + '@csstools/color-helpers@6.1.0': {} - '@csstools/css-calc@3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-color-parser@4.1.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/color-helpers': 6.0.2 - '@csstools/css-calc': 3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -2208,7 +2196,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.3(css-tree@3.2.1)': + '@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)': optionalDependencies: css-tree: 3.2.1 @@ -2328,7 +2316,7 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 - '@exodus/bytes@1.15.0': {} + '@exodus/bytes@1.15.1': {} '@hono/node-server@2.1.0(hono@4.13.0)': dependencies: @@ -2758,7 +2746,7 @@ snapshots: obug: 2.1.3 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) + vitest: 4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@30.0.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) '@vitest/expect@4.1.10': dependencies: @@ -2878,7 +2866,7 @@ snapshots: dependencies: require-from-string: 2.0.2 - brace-expansion@5.0.6: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -3189,7 +3177,7 @@ snapshots: html-encoding-sniffer@6.0.0: dependencies: - '@exodus/bytes': 1.15.0 + '@exodus/bytes': 1.15.1 transitivePeerDependencies: - '@noble/hashes' @@ -3248,13 +3236,13 @@ snapshots: dependencies: argparse: 2.0.1 - jsdom@29.1.1: + jsdom@30.0.1: dependencies: - '@asamuzakjp/css-color': 5.1.11 - '@asamuzakjp/dom-selector': 7.1.1 + '@asamuzakjp/css-color': 6.0.5 + '@asamuzakjp/dom-selector': 8.3.2 '@bramus/specificity': 2.4.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.3(css-tree@3.2.1) - '@exodus/bytes': 1.15.0 + '@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 css-tree: 3.2.1 data-urls: 7.0.0 decimal.js: 10.6.0 @@ -3264,12 +3252,12 @@ snapshots: parse5: 8.0.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 6.0.1 - undici: 7.28.0 + tough-cookie: 6.0.2 + undici: 8.10.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1 + whatwg-url: 17.1.0 xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' @@ -3382,7 +3370,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 5.0.9 ms@2.1.3: {} @@ -3581,7 +3569,7 @@ snapshots: dependencies: tldts-core: 7.0.28 - tough-cookie@6.0.1: + tough-cookie@6.0.2: dependencies: tldts: 7.0.28 @@ -3618,8 +3606,6 @@ snapshots: undici-types@8.3.0: {} - undici@7.28.0: {} - undici@8.10.0: {} unplugin@3.0.0: @@ -3674,7 +3660,7 @@ snapshots: tsx: 4.23.7 yaml: 2.9.0 - vitest@4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.1.2)(@vitest/coverage-v8@4.1.10)(jsdom@30.0.1)(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 '@vitest/mocker': 4.1.10(vite@8.2.0(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.7)(yaml@2.9.0)) @@ -3699,7 +3685,7 @@ snapshots: optionalDependencies: '@types/node': 26.1.2 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) - jsdom: 29.1.1 + jsdom: 30.0.1 transitivePeerDependencies: - msw @@ -3715,7 +3701,15 @@ snapshots: whatwg-url@16.0.1: dependencies: - '@exodus/bytes': 1.15.0 + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + whatwg-url@17.1.0: + dependencies: + '@exodus/bytes': 1.15.1 tr46: 6.0.0 webidl-conversions: 8.0.1 transitivePeerDependencies: From ac39e69df0ff3cee7200120c3bf57dac03484ab9 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Thu, 6 Aug 2026 11:46:13 +0200 Subject: [PATCH 51/51] feat: display-last-gh-api-refresh (#79) * feat: show last api fetch time * chore: bump version to 1.1.0 --- package.json | 2 +- packages/web/src/api/client.test.ts | 86 ++++++++++++++++++- packages/web/src/api/client.ts | 25 ++++++ .../web/src/components/layout/Header.test.tsx | 44 ++++++++++ packages/web/src/components/layout/Header.tsx | 12 ++- packages/web/src/lib/useLastFetchTime.ts | 27 ++++++ packages/web/src/lib/utils.test.ts | 33 +++++++ packages/web/src/lib/utils.ts | 10 +++ 8 files changed, 232 insertions(+), 7 deletions(-) create mode 100644 packages/web/src/lib/useLastFetchTime.ts diff --git a/package.json b/package.json index 8b157f9..35a016d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dashlight", - "version": "1.0.1", + "version": "1.1.0", "private": true, "scripts": { "prepare": "husky", diff --git a/packages/web/src/api/client.test.ts b/packages/web/src/api/client.test.ts index 1c72292..ba0a5b6 100644 --- a/packages/web/src/api/client.test.ts +++ b/packages/web/src/api/client.test.ts @@ -1,10 +1,16 @@ import { describe, it, expect, vi, beforeEach } from "vitest" -import { fetchApi, fetchApiText, ApiError } from "./client.js" +import { fetchApi, fetchApiText, ApiError, getLastGitHubFetchAt, subscribeLastGitHubFetchAt } from "./client.js" -function mockFetch(status: number, body: unknown, ok = status >= 200 && status < 300) { +function mockFetch( + status: number, + body: unknown, + ok = status >= 200 && status < 300, + headers?: Record, +) { return vi.fn().mockResolvedValue({ ok, status, + headers: new Headers(headers), json: () => Promise.resolve(body), text: () => Promise.resolve(typeof body === "string" ? body : JSON.stringify(body)), }) @@ -101,3 +107,79 @@ describe("fetchApiText", () => { await expect(fetchApiText("/api/logs")).rejects.toThrow("HTTP 404") }) }) + +// ── X-Cache tracking (lastGitHubFetchAt) ───────────────────────────────────── + +describe("lastGitHubFetchAt tracking", () => { + it("updates on X-Cache: MISS from fetchApi", async () => { + const before = Date.now() + vi.stubGlobal("fetch", mockFetch(200, { ok: true }, true, { "X-Cache": "MISS" })) + await fetchApi("/proxy/repos/owner/repo/actions/runs") + const ts = getLastGitHubFetchAt() + expect(ts).toBeGreaterThanOrEqual(before) + expect(ts).toBeLessThanOrEqual(Date.now()) + }) + + it("does not update on X-Cache: HIT from fetchApi", async () => { + // First set a baseline with a MISS + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "MISS" })) + await fetchApi("/proxy/repos/owner/repo") + const baseline = getLastGitHubFetchAt() + + // Wait a tick so any new timestamp would differ + await new Promise((r) => setTimeout(r, 5)) + + // HIT should not change the timestamp + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "HIT" })) + await fetchApi("/proxy/repos/owner/repo") + expect(getLastGitHubFetchAt()).toBe(baseline) + }) + + it("does not update when no X-Cache header is present", async () => { + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "MISS" })) + await fetchApi("/proxy/repos/owner/repo") + const baseline = getLastGitHubFetchAt() + + await new Promise((r) => setTimeout(r, 5)) + + // No X-Cache header (e.g. /auth/config) + vi.stubGlobal("fetch", mockFetch(200, {})) + await fetchApi("/auth/config") + expect(getLastGitHubFetchAt()).toBe(baseline) + }) + + it("updates on X-Cache: MISS from fetchApiText", async () => { + const before = Date.now() + vi.stubGlobal("fetch", mockFetch(200, "log data", true, { "X-Cache": "MISS" })) + await fetchApiText("/proxy/repos/owner/repo/actions/jobs/1/logs") + const ts = getLastGitHubFetchAt() + expect(ts).toBeGreaterThanOrEqual(before) + }) + + it("notifies subscribers on cache miss", async () => { + const listener = vi.fn() + const unsub = subscribeLastGitHubFetchAt(listener) + + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "MISS" })) + await fetchApi("/proxy/repos/owner/repo") + expect(listener).toHaveBeenCalledOnce() + + // HIT should not notify + listener.mockClear() + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "HIT" })) + await fetchApi("/proxy/repos/owner/repo") + expect(listener).not.toHaveBeenCalled() + + unsub() + }) + + it("unsubscribe stops notifications", async () => { + const listener = vi.fn() + const unsub = subscribeLastGitHubFetchAt(listener) + unsub() + + vi.stubGlobal("fetch", mockFetch(200, {}, true, { "X-Cache": "MISS" })) + await fetchApi("/proxy/repos/owner/repo") + expect(listener).not.toHaveBeenCalled() + }) +}) diff --git a/packages/web/src/api/client.ts b/packages/web/src/api/client.ts index 5cbe94d..ac64f9f 100644 --- a/packages/web/src/api/client.ts +++ b/packages/web/src/api/client.ts @@ -1,3 +1,21 @@ +// Tracks when the server last fetched fresh data from GitHub (X-Cache: MISS). +let _lastGitHubFetchAt: number | null = null +const _listeners = new Set<() => void>() + +export function getLastGitHubFetchAt(): number | null { + return _lastGitHubFetchAt +} + +export function subscribeLastGitHubFetchAt(listener: () => void): () => void { + _listeners.add(listener) + return () => _listeners.delete(listener) +} + +function recordCacheMiss(): void { + _lastGitHubFetchAt = Date.now() + for (const listener of _listeners) listener() +} + export class ApiError extends Error { constructor( message: string, @@ -36,6 +54,10 @@ export async function fetchApi( throw new ApiError(message, res.status, body) } + if (res.headers.get("X-Cache") === "MISS") { + recordCacheMiss() + } + if (res.status === 204) { return null as unknown as T } @@ -49,5 +71,8 @@ export async function fetchApiText(path: string, options?: RequestInit): Promise credentials: "include", }) if (!res.ok) throw new ApiError(`HTTP ${res.status}`, res.status) + if (res.headers.get("X-Cache") === "MISS") { + recordCacheMiss() + } return res.text() } diff --git a/packages/web/src/components/layout/Header.test.tsx b/packages/web/src/components/layout/Header.test.tsx index 16ea647..82b0aaf 100644 --- a/packages/web/src/components/layout/Header.test.tsx +++ b/packages/web/src/components/layout/Header.test.tsx @@ -22,6 +22,18 @@ vi.mock("../../context/ThemeContext.js", () => ({ useTheme: vi.fn(), })) +const { mockUseLastFetchTime } = vi.hoisted(() => ({ + mockUseLastFetchTime: vi.fn(() => ({ + lastFetchTime: null as number | null, + lastSyncTime: null as number | null, + recordSync: vi.fn(), + })), +})) + +vi.mock("../../lib/useLastFetchTime.js", () => ({ + useLastFetchTime: mockUseLastFetchTime, +})) + vi.mock("../ui/Button.js", () => ({ // eslint-disable-next-line @typescript-eslint/no-explicit-any Button: ({ children, onClick }: any) => , @@ -173,3 +185,35 @@ describe("authConfig not yet loaded (undefined)", () => { expect(screen.queryByText("Token")).toBeNull() }) }) + +// ── Last fetch / sync display ──────────────────────────────────────────────── + +describe("last fetch time display", () => { + it("shows nothing when no fetch has occurred", () => { + render(
) + expect(screen.queryByText(/Updated/)).toBeNull() + expect(screen.queryByText(/Synced/)).toBeNull() + }) + + it("shows 'Updated' when lastFetchTime is set", () => { + mockUseLastFetchTime.mockReturnValue({ + lastFetchTime: Date.now() - 30_000, + lastSyncTime: null, + recordSync: vi.fn(), + }) + render(
) + expect(screen.getByText(/Updated 30s ago/)).toBeInTheDocument() + expect(screen.queryByText(/Synced/)).toBeNull() + }) + + it("shows both 'Updated' and 'Synced' when both are set", () => { + mockUseLastFetchTime.mockReturnValue({ + lastFetchTime: Date.now() - 30_000, + lastSyncTime: Date.now() - 120_000, + recordSync: vi.fn(), + }) + render(
) + expect(screen.getByText(/Updated 30s ago/)).toBeInTheDocument() + expect(screen.getByText(/Synced 2m ago/)).toBeInTheDocument() + }) +}) diff --git a/packages/web/src/components/layout/Header.tsx b/packages/web/src/components/layout/Header.tsx index 144b149..7736a87 100644 --- a/packages/web/src/components/layout/Header.tsx +++ b/packages/web/src/components/layout/Header.tsx @@ -4,18 +4,20 @@ import { logout, clearServerCache, getAuthConfig } from "../../api/index.js" import { Button } from "../ui/Button.js" import { Spinner } from "../ui/Spinner.js" import { useTheme } from "../../context/ThemeContext.js" +import { useLastFetchTime } from "../../lib/useLastFetchTime.js" +import { formatRelativeTimeShort } from "../../lib/utils.js" import type { SessionUser } from "../../types/index.js" interface HeaderProps { user: SessionUser - lastUpdated?: number | null } -export function Header({ user, lastUpdated }: HeaderProps) { +export function Header({ user }: HeaderProps) { const isFetching = useIsFetching() const queryClient = useQueryClient() const [syncing, setSyncing] = useState(false) const { theme, toggleTheme } = useTheme() + const { lastFetchTime, lastSyncTime, recordSync } = useLastFetchTime() const { data: authConfig } = useQuery({ queryKey: ["auth", "config"], @@ -39,6 +41,7 @@ export function Header({ user, lastUpdated }: HeaderProps) { try { await clearServerCache() await queryClient.invalidateQueries() + recordSync() } finally { setSyncing(false) } @@ -51,9 +54,10 @@ export function Header({ user, lastUpdated }: HeaderProps) { {syncing ? "Syncing…" : "Refreshing…"} - ) : lastUpdated ? ( + ) : lastFetchTime ? ( - Updated {new Date(lastUpdated).toLocaleTimeString(undefined, { timeStyle: "short" })} + Updated {formatRelativeTimeShort(lastFetchTime)} + {lastSyncTime && <> · Synced {formatRelativeTimeShort(lastSyncTime)}} ) : null} diff --git a/packages/web/src/lib/useLastFetchTime.ts b/packages/web/src/lib/useLastFetchTime.ts new file mode 100644 index 0000000..be280ff --- /dev/null +++ b/packages/web/src/lib/useLastFetchTime.ts @@ -0,0 +1,27 @@ +import { useCallback, useEffect, useState, useSyncExternalStore } from "react" +import { getLastGitHubFetchAt, subscribeLastGitHubFetchAt } from "../api/client.js" + +interface LastFetchTime { + lastFetchTime: number | null + lastSyncTime: number | null + recordSync: () => void +} + +export function useLastFetchTime(): LastFetchTime { + const lastFetchTime = useSyncExternalStore(subscribeLastGitHubFetchAt, getLastGitHubFetchAt) + const [lastSyncTime, setLastSyncTime] = useState(null) + const [, setTick] = useState(0) + + // Tick every 15s so relative time display stays current + useEffect(() => { + if (lastFetchTime === null && lastSyncTime === null) return + const id = setInterval(() => setTick((t) => t + 1), 15_000) + return () => clearInterval(id) + }, [lastFetchTime !== null || lastSyncTime !== null]) // eslint-disable-line react-hooks/exhaustive-deps + + const recordSync = useCallback(() => { + setLastSyncTime(Date.now()) + }, []) + + return { lastFetchTime, lastSyncTime, recordSync } +} diff --git a/packages/web/src/lib/utils.test.ts b/packages/web/src/lib/utils.test.ts index 4839599..ceeea26 100644 --- a/packages/web/src/lib/utils.test.ts +++ b/packages/web/src/lib/utils.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" import { formatDuration, formatRelativeTime, + formatRelativeTimeShort, formatDateTime, runStatusVariant, runStatusLabel, @@ -96,6 +97,38 @@ describe("formatRelativeTime", () => { }) }) +// ── formatRelativeTimeShort ─────────────────────────────────────────────────── + +describe("formatRelativeTimeShort", () => { + beforeEach(() => vi.useFakeTimers()) + afterEach(() => vi.useRealTimers()) + + it("returns seconds for <60s", () => { + vi.setSystemTime(new Date("2024-01-01T00:00:30Z")) + expect(formatRelativeTimeShort(new Date("2024-01-01T00:00:00Z").getTime())).toBe("30s ago") + }) + + it("returns at least 1s", () => { + vi.setSystemTime(new Date("2024-01-01T00:00:00Z")) + expect(formatRelativeTimeShort(Date.now())).toBe("1s ago") + }) + + it("returns minutes for <60m", () => { + vi.setSystemTime(new Date("2024-01-01T00:05:00Z")) + expect(formatRelativeTimeShort(new Date("2024-01-01T00:00:00Z").getTime())).toBe("5m ago") + }) + + it("returns hours for <24h", () => { + vi.setSystemTime(new Date("2024-01-01T03:00:00Z")) + expect(formatRelativeTimeShort(new Date("2024-01-01T00:00:00Z").getTime())).toBe("3h ago") + }) + + it("returns days for >=24h", () => { + vi.setSystemTime(new Date("2024-01-03T00:00:00Z")) + expect(formatRelativeTimeShort(new Date("2024-01-01T00:00:00Z").getTime())).toBe("2d ago") + }) +}) + // ── formatDateTime ──────────────────────────────────────────────────────────── describe("formatDateTime", () => { diff --git a/packages/web/src/lib/utils.ts b/packages/web/src/lib/utils.ts index d1d1612..1e33488 100644 --- a/packages/web/src/lib/utils.ts +++ b/packages/web/src/lib/utils.ts @@ -41,6 +41,16 @@ export function formatDateTime(dateStr: string | null): string { }) } +export function formatRelativeTimeShort(timestamp: number): string { + const diffSec = Math.floor((Date.now() - timestamp) / 1000) + if (diffSec < 60) return `${Math.max(diffSec, 1)}s ago` + const diffMin = Math.floor(diffSec / 60) + if (diffMin < 60) return `${diffMin}m ago` + const diffHour = Math.floor(diffMin / 60) + if (diffHour < 24) return `${diffHour}h ago` + return `${Math.floor(diffHour / 24)}d ago` +} + // ── Status helpers ──────────────────────────────────────────────────────────── export type StatusVariant = "success" | "failure" | "running" | "pending" | "cancelled" | "neutral"
RepositoryRunBranch / CommitEventActorStatusDurationStarted
{owner}/ @@ -162,7 +248,8 @@ export function AllRunsTable({ runs }: { runs: RunWithRepo[] }) { {run.displayTitle} @@ -172,6 +259,7 @@ export function AllRunsTable({ runs }: { runs: RunWithRepo[] }) { )} {run.workflowName}
{run.headBranch} @@ -200,7 +290,7 @@ export function AllRunsTable({ runs }: { runs: RunWithRepo[] }) { {run.actor?.login ?? "—"}
- + {formatDuration(run.runStartedAt, run.updatedAt)} diff --git a/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx b/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx index 430006f..b6c735a 100644 --- a/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx +++ b/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx @@ -1,6 +1,6 @@ import { createFileRoute, Link } from "@tanstack/react-router" import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" -import { lazy, Suspense, useState, Fragment } from "react" +import { useState, Fragment } from "react" import { getRun, getRunJobs, getRuns, getRunArtifacts, getJobLogs, rerunWorkflow, rerunFailedJobs, cancelRun, @@ -9,13 +9,11 @@ import { StatusBadge } from "../../components/ui/Badge.js" import { EventBadge } from "../../components/ui/EventBadge.js" import { Button } from "../../components/ui/Button.js" import { Card, CardHeader } from "../../components/ui/Card.js" -import { PageSpinner, Spinner } from "../../components/ui/Spinner.js" +import { PageSpinner } from "../../components/ui/Spinner.js" import { formatRelativeTime, formatDuration, formatDateTime } from "../../lib/utils.js" import type { WorkflowRun, WorkflowJob, JobStep, RunArtifact } from "../../types/index.js" -const WorkflowDAG = lazy(() => - import("../../components/dag/WorkflowDAG.js").then((m) => ({ default: m.WorkflowDAG })) -) +import { WorkflowDAG } from "../../components/dag/WorkflowDAG.js" export const Route = createFileRoute("/_app/runs_/$owner/$repo/$runId")({ component: RunDetail, @@ -95,7 +93,9 @@ function RunDetail() {
Runs / - {owner}/{repo} + {owner} + / + {repo} / #{run.runNumber}
@@ -132,7 +132,7 @@ function RunDetail() { {!isActive && ( <> {hasFailed && ( + {authConfig?.mode === "pat" && ( + + Token + + )} {user.login} {user.login} - + {!isPATOpenAccess && ( + + )} ) diff --git a/packages/web/src/lib/queryClient.test.ts b/packages/web/src/lib/queryClient.test.ts new file mode 100644 index 0000000..9de1d63 --- /dev/null +++ b/packages/web/src/lib/queryClient.test.ts @@ -0,0 +1,80 @@ +import { describe, it, expect } from "vitest" +import { QueryClient, dehydrate } from "@tanstack/react-query" + +// The filter that main.tsx passes to PersistQueryClientProvider. +// Extracted here so it can be tested in isolation without mounting the full app. +function shouldDehydrateQuery(query: { queryKey: readonly unknown[] }): boolean { + return query.queryKey[0] !== "auth" +} + +// Build a QueryClient, seed it with data under a given key, dehydrate it through +// the filter, and return the dehydrated query keys. +function dehydratedKeys(queryKey: readonly unknown[], data: unknown): string[] { + const client = new QueryClient() + client.setQueryData(queryKey, data) + const state = dehydrate(client, { shouldDehydrateQuery }) + return state.queries.map((q) => JSON.stringify(q.queryKey)) +} + +// ── shouldDehydrateQuery ────────────────────────────────────────────────────── + +describe("shouldDehydrateQuery — auth exclusion filter", () => { + it("excludes [auth, me]", () => { + expect(shouldDehydrateQuery({ queryKey: ["auth", "me"] })).toBe(false) + }) + + it("excludes [auth, config]", () => { + expect(shouldDehydrateQuery({ queryKey: ["auth", "config"] })).toBe(false) + }) + + it("excludes any query whose first key segment is 'auth'", () => { + expect(shouldDehydrateQuery({ queryKey: ["auth", "anything", "nested"] })).toBe(false) + }) + + it("includes [repos, user]", () => { + expect(shouldDehydrateQuery({ queryKey: ["repos", "user"] })).toBe(true) + }) + + it("includes [runs, owner/repo, options]", () => { + expect(shouldDehydrateQuery({ queryKey: ["runs", "acme/api", { page: 1 }] })).toBe(true) + }) + + it("includes [score, owner, repo]", () => { + expect(shouldDehydrateQuery({ queryKey: ["score", "acme", "api"] })).toBe(true) + }) +}) + +// ── Integration: dehydrate through the filter ───────────────────────────────── + +describe("dehydrate with auth exclusion filter", () => { + it("auth queries are absent from the dehydrated state", () => { + const keys = dehydratedKeys(["auth", "me"], { login: "jan", name: "Jan", avatarUrl: "" }) + expect(keys).toHaveLength(0) + }) + + it("auth/config is absent from the dehydrated state", () => { + const keys = dehydratedKeys(["auth", "config"], { mode: "pat", passwordRequired: false }) + expect(keys).toHaveLength(0) + }) + + it("non-auth queries survive dehydration", () => { + const keys = dehydratedKeys(["repos", "user"], [{ id: 1 }]) + expect(keys).toContain(JSON.stringify(["repos", "user"])) + }) + + it("auth and non-auth queries coexist — only non-auth is dehydrated", () => { + const client = new QueryClient() + client.setQueryData(["auth", "me"], { login: "jan" }) + client.setQueryData(["repos", "user"], [{ id: 1 }]) + client.setQueryData(["auth", "config"], { mode: "oauth" }) + client.setQueryData(["runs", "acme/api", {}], { runs: [] }) + + const state = dehydrate(client, { shouldDehydrateQuery }) + const keys = state.queries.map((q) => JSON.stringify(q.queryKey)) + + expect(keys).not.toContain(JSON.stringify(["auth", "me"])) + expect(keys).not.toContain(JSON.stringify(["auth", "config"])) + expect(keys).toContain(JSON.stringify(["repos", "user"])) + expect(keys).toContain(JSON.stringify(["runs", "acme/api", {}])) + }) +}) diff --git a/packages/web/src/main.tsx b/packages/web/src/main.tsx index d549af6..72f2173 100644 --- a/packages/web/src/main.tsx +++ b/packages/web/src/main.tsx @@ -27,7 +27,21 @@ ReactDOM.createRoot(root).render( query.queryKey[0] !== "auth", + }, + }} > diff --git a/packages/web/src/routes/-login.test.tsx b/packages/web/src/routes/-login.test.tsx index 02da67d..44124d9 100644 --- a/packages/web/src/routes/-login.test.tsx +++ b/packages/web/src/routes/-login.test.tsx @@ -1,5 +1,5 @@ -import { describe, it, expect, vi } from "vitest" -import { render, screen } from "@testing-library/react" +import { describe, it, expect, vi, beforeEach } from "vitest" +import { render, screen, fireEvent, waitFor } from "@testing-library/react" import React from "react" // ── Mocks ───────────────────────────────────────────────────────────────────── @@ -9,10 +9,14 @@ vi.mock("@tanstack/react-router", () => ({ createFileRoute: () => (opts: any) => opts, redirect: vi.fn(), isRedirect: vi.fn(), + useNavigate: vi.fn(() => vi.fn()), + useLoaderData: vi.fn(), })) vi.mock("../api/index.js", () => ({ getMe: vi.fn(), + getAuthConfig: vi.fn(), + patLogin: vi.fn(), })) vi.mock("../components/ui/DashlightLogo.js", () => ({ @@ -21,38 +25,118 @@ vi.mock("../components/ui/DashlightLogo.js", () => ({ // ── Imports after mocks ─────────────────────────────────────────────────────── +import { useNavigate, useLoaderData } from "@tanstack/react-router" +import { patLogin } from "../api/index.js" import { Route } from "./login.js" +import type { AuthConfig } from "../types/index.js" const LoginPage = Route.component as React.FC -// ── Tests ───────────────────────────────────────────────────────────────────── +const mockNavigate = vi.fn() +const mockPatLogin = vi.mocked(patLogin) +const mockUseLoaderData = vi.mocked(useLoaderData) + +beforeEach(() => { + vi.clearAllMocks() + vi.mocked(useNavigate).mockReturnValue(mockNavigate) +}) + +// helper to render with a given auth config loaded +function renderWithConfig(config: AuthConfig) { + mockUseLoaderData.mockReturnValue(config) + render() +} + +// ── OAuth mode ──────────────────────────────────────────────────────────────── + +describe("OAuth mode", () => { + const oauthConfig: AuthConfig = { mode: "oauth", passwordRequired: false } -describe("LoginPage", () => { it("renders the Dashlight logo", () => { - render() + renderWithConfig(oauthConfig) expect(screen.getByTestId("dashlight-logo")).toBeInTheDocument() }) it("renders the 'Dashlight' brand name", () => { - render() + renderWithConfig(oauthConfig) expect(screen.getByText("Dashlight")).toBeInTheDocument() }) it("renders a 'Sign in with GitHub' link", () => { - render() + renderWithConfig(oauthConfig) expect(screen.getByRole("link", { name: /sign in with github/i })).toBeInTheDocument() }) it("sign-in link points to /auth/login", () => { - render() + renderWithConfig(oauthConfig) expect(screen.getByRole("link", { name: /sign in with github/i })) .toHaveAttribute("href", "/auth/login") }) - it("does not render a title or subtitle", () => { - render() - expect(screen.queryByRole("heading")).toBeNull() - expect(screen.queryByText(/monitor all/i)).toBeNull() - expect(screen.queryByText(/token is stored/i)).toBeNull() + it("does not render a password input", () => { + renderWithConfig(oauthConfig) + expect(screen.queryByPlaceholderText("Enter password")).toBeNull() + }) +}) + +// ── PAT + password mode ─────────────────────────────────────────────────────── + +describe("PAT + password mode", () => { + const patConfig: AuthConfig = { mode: "pat", passwordRequired: true } + + it("renders the Dashlight logo", () => { + renderWithConfig(patConfig) + expect(screen.getByTestId("dashlight-logo")).toBeInTheDocument() + }) + + it("renders a password input", () => { + renderWithConfig(patConfig) + expect(screen.getByPlaceholderText("Enter password")).toBeInTheDocument() + }) + + it("renders a 'Sign in' submit button", () => { + renderWithConfig(patConfig) + expect(screen.getByRole("button", { name: /sign in/i })).toBeInTheDocument() + }) + + it("does not render the GitHub OAuth link", () => { + renderWithConfig(patConfig) + expect(screen.queryByRole("link", { name: /sign in with github/i })).toBeNull() + }) + + it("submit button is disabled when password is empty", () => { + renderWithConfig(patConfig) + expect(screen.getByRole("button", { name: /sign in/i })).toBeDisabled() + }) + + it("submit button is enabled after typing a password", () => { + renderWithConfig(patConfig) + fireEvent.change(screen.getByPlaceholderText("Enter password"), { target: { value: "secret" } }) + expect(screen.getByRole("button", { name: /sign in/i })).not.toBeDisabled() + }) + + it("calls patLogin with the entered password on submit", async () => { + mockPatLogin.mockResolvedValue(undefined) + renderWithConfig(patConfig) + fireEvent.change(screen.getByPlaceholderText("Enter password"), { target: { value: "mypassword" } }) + fireEvent.click(screen.getByRole("button", { name: /sign in/i })) + await waitFor(() => expect(mockPatLogin).toHaveBeenCalledWith("mypassword")) + }) + + it("navigates to / on successful login", async () => { + mockPatLogin.mockResolvedValue(undefined) + renderWithConfig(patConfig) + fireEvent.change(screen.getByPlaceholderText("Enter password"), { target: { value: "good" } }) + fireEvent.click(screen.getByRole("button", { name: /sign in/i })) + await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith({ to: "/" })) + }) + + it("shows error message on wrong password", async () => { + mockPatLogin.mockRejectedValue(new Error("401")) + renderWithConfig(patConfig) + fireEvent.change(screen.getByPlaceholderText("Enter password"), { target: { value: "wrong" } }) + fireEvent.click(screen.getByRole("button", { name: /sign in/i })) + await waitFor(() => expect(screen.getByRole("alert")).toBeInTheDocument()) + expect(screen.getByRole("alert")).toHaveTextContent(/invalid password/i) }) }) diff --git a/packages/web/src/routes/_app.tsx b/packages/web/src/routes/_app.tsx index 8ca2a22..25e7978 100644 --- a/packages/web/src/routes/_app.tsx +++ b/packages/web/src/routes/_app.tsx @@ -21,7 +21,7 @@ export const Route = createFileRoute("/_app")({ }) function AppLayout() { - const { user } = Route.useRouteContext() + const { user } = Route.useRouteContext() as { user: SessionUser } return ( diff --git a/packages/web/src/routes/login.tsx b/packages/web/src/routes/login.tsx index 9623c47..0372517 100644 --- a/packages/web/src/routes/login.tsx +++ b/packages/web/src/routes/login.tsx @@ -1,6 +1,8 @@ -import { createFileRoute, redirect, isRedirect } from "@tanstack/react-router" -import { getMe } from "../api/index.js" +import { useState } from "react" +import { createFileRoute, redirect, isRedirect, useNavigate, useLoaderData } from "@tanstack/react-router" +import { getMe, getAuthConfig, patLogin } from "../api/index.js" import { DashlightLogo } from "../components/ui/DashlightLogo.js" +import type { AuthConfig } from "../types/index.js" export const Route = createFileRoute("/login")({ beforeLoad: async () => { @@ -13,10 +15,30 @@ export const Route = createFileRoute("/login")({ if (isRedirect(err)) throw err } }, + loader: async (): Promise => { + try { + return await getAuthConfig() + } catch { + // Server unreachable — fall back to OAuth form, which also won't work + // but avoids crashing the router and shows the user a sensible page. + return { mode: "oauth", passwordRequired: false } + } + }, component: LoginPage, }) function LoginPage() { + const authConfig = useLoaderData({ from: "/login" }) as AuthConfig + + if (authConfig.mode === "pat" && authConfig.passwordRequired) { + return + } + + // OAuth mode (PAT+no-password never renders login since getMe() always succeeds) + return +} + +function OAuthLoginPage() { return (
@@ -30,7 +52,68 @@ function LoginPage() { Sign in with GitHub +
+
+ ) +} +function PATPasswordForm() { + const navigate = useNavigate() + const [password, setPassword] = useState("") + const [error, setError] = useState(null) + const [loading, setLoading] = useState(false) + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + setError(null) + setLoading(true) + try { + await patLogin(password) + void navigate({ to: "/" }) + } catch { + setError("Invalid password. Please try again.") + } finally { + setLoading(false) + } + } + + return ( +
+
+
+ + Dashlight +
+
+ setPassword(e.target.value)} + autoFocus + required + style={{ + padding: "0.5rem 0.75rem", + fontSize: 14, + border: "1px solid var(--color-border)", + borderRadius: "var(--radius)", + background: "var(--color-bg)", + color: "var(--color-text)", + }} + /> + {error && ( +

+ {error} +

+ )} + +
) diff --git a/packages/web/src/types/index.ts b/packages/web/src/types/index.ts index f73ff7b..88ecbe2 100644 --- a/packages/web/src/types/index.ts +++ b/packages/web/src/types/index.ts @@ -28,6 +28,11 @@ export interface SessionUser { avatarUrl: string } +export interface AuthConfig { + mode: "oauth" | "pat" + passwordRequired: boolean +} + // ── GitHub domain types ─────────────────────────────────────────────────────── export interface GitHubUser { From 7bf2fc49bd15fefd476eb25edb2dc4f67d0f887c Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:21:41 +0200 Subject: [PATCH 07/51] fix: parallel job in run detail dag (#24) --- .../src/components/dag/WorkflowDAG.test.tsx | 86 +++++++- .../web/src/components/dag/WorkflowDAG.tsx | 107 +++++++++- packages/web/src/lib/dag-layout.test.ts | 193 ++++++++++++++++++ packages/web/src/lib/dag-layout.ts | 116 +++++++++++ 4 files changed, 490 insertions(+), 12 deletions(-) create mode 100644 packages/web/src/lib/dag-layout.test.ts create mode 100644 packages/web/src/lib/dag-layout.ts diff --git a/packages/web/src/components/dag/WorkflowDAG.test.tsx b/packages/web/src/components/dag/WorkflowDAG.test.tsx index 9745150..b12c621 100644 --- a/packages/web/src/components/dag/WorkflowDAG.test.tsx +++ b/packages/web/src/components/dag/WorkflowDAG.test.tsx @@ -22,6 +22,26 @@ function makeJob(overrides: Partial = {}): WorkflowJob { } } +function addMs(base: string, ms: number): string { + return new Date(new Date(base).getTime() + ms).toISOString() +} + +const BASE = "2024-01-01T10:00:00.000Z" + +/** + * Build N jobs with strictly sequential timestamps so buildDagLayout returns + * null (each level has exactly one job → maxRows = 1 → linear fallback). + */ +function makeSequentialJobs(names: string[]): WorkflowJob[] { + return names.map((name, i) => + makeJob({ + name, + startedAt: addMs(BASE, i * 90_000), + completedAt: addMs(BASE, i * 90_000 + 60_000), + }) + ) +} + // ── sortJobs ────────────────────────────────────────────────────────────────── describe("sortJobs", () => { @@ -61,23 +81,23 @@ describe("sortJobs", () => { }) }) -// ── WorkflowDAG rendering ───────────────────────────────────────────────────── +// ── WorkflowDAG — linear fallback ───────────────────────────────────────────── -describe("WorkflowDAG", () => { +describe("WorkflowDAG (linear)", () => { it("shows empty state when no jobs", () => { render() expect(screen.getByText("No jobs to display.")).toBeInTheDocument() }) it("renders a pill for each job", () => { - const jobs = [makeJob({ name: "build" }), makeJob({ name: "test" })] + const jobs = makeSequentialJobs(["build", "test"]) render() expect(screen.getByText("build")).toBeInTheDocument() expect(screen.getByText("test")).toBeInTheDocument() }) it("renders arrows between jobs", () => { - const jobs = [makeJob({ name: "check" }), makeJob({ name: "build" }), makeJob({ name: "deploy" })] + const jobs = makeSequentialJobs(["check", "build", "deploy"]) render() expect(screen.getAllByText("→")).toHaveLength(2) }) @@ -88,11 +108,65 @@ describe("WorkflowDAG", () => { }) it("renders jobs in startedAt order", () => { - const a = makeJob({ name: "validate", startedAt: "2024-01-01T10:00:00Z" }) - const b = makeJob({ name: "deploy", startedAt: "2024-01-01T10:20:00Z" }) + const a = makeJob({ name: "validate", startedAt: addMs(BASE, 0), completedAt: addMs(BASE, 60_000) }) + const b = makeJob({ name: "deploy", startedAt: addMs(BASE, 90_000), completedAt: addMs(BASE, 150_000) }) render() const pills = screen.getAllByText(/validate|deploy/) expect(pills[0]).toHaveTextContent("validate") expect(pills[1]).toHaveTextContent("deploy") }) + + it("uses the dag-linear container for sequential jobs", () => { + const jobs = makeSequentialJobs(["build", "test"]) + render() + expect(screen.getByTestId("dag-linear")).toBeInTheDocument() + expect(screen.queryByTestId("dag-parallel")).not.toBeInTheDocument() + }) +}) + +// ── WorkflowDAG — parallel layout ──────────────────────────────────────────── + +describe("WorkflowDAG (parallel)", () => { + /** + * Diamond: build → [test, lint] → deploy + * + * build started=T+0s, completed=T+60s + * test started=T+61s, completed=T+121s ← parallel with lint + * lint started=T+62s, completed=T+122s + * deploy started=T+123s, completed=T+183s + */ + function makeDiamondJobs() { + return [ + makeJob({ name: "build", startedAt: BASE, completedAt: addMs(BASE, 60_000) }), + makeJob({ name: "test", startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }), + makeJob({ name: "lint", startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }), + makeJob({ name: "deploy", startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }), + ] + } + + it("uses the dag-parallel container for parallel jobs", () => { + render() + expect(screen.getByTestId("dag-parallel")).toBeInTheDocument() + expect(screen.queryByTestId("dag-linear")).not.toBeInTheDocument() + }) + + it("renders a pill for each job in parallel layout", () => { + render() + expect(screen.getByText("build")).toBeInTheDocument() + expect(screen.getByText("test")).toBeInTheDocument() + expect(screen.getByText("lint")).toBeInTheDocument() + expect(screen.getByText("deploy")).toBeInTheDocument() + }) + + it("renders SVG bezier edges in parallel layout", () => { + const { container } = render() + const paths = container.querySelectorAll("svg path") + // Diamond: 1×2 + 2×1 = 4 edges + expect(paths.length).toBe(4) + }) + + it("does not render text arrows in parallel layout", () => { + render() + expect(screen.queryByText("→")).not.toBeInTheDocument() + }) }) diff --git a/packages/web/src/components/dag/WorkflowDAG.tsx b/packages/web/src/components/dag/WorkflowDAG.tsx index 2099988..e61c831 100644 --- a/packages/web/src/components/dag/WorkflowDAG.tsx +++ b/packages/web/src/components/dag/WorkflowDAG.tsx @@ -1,5 +1,7 @@ import { Fragment } from "react" import { runStatusVariant, formatDuration } from "../../lib/utils.js" +import { buildDagLayout } from "../../lib/dag-layout.js" +import type { DagLayout } from "../../lib/dag-layout.js" import type { WorkflowJob } from "../../types/index.js" interface WorkflowDAGProps { @@ -49,6 +51,8 @@ function JobPill({ job }: { job: WorkflowJob }) { fontWeight: 500, minWidth: 0, whiteSpace: "nowrap", + height: "100%", + boxSizing: "border-box", }} > No jobs to display.

- } +const NODE_W = 180 +const NODE_H = 36 +const COL_GAP = 56 +const ROW_GAP = 12 +const PAD = 8 + +function nodeX(level: number) { return PAD + level * (NODE_W + COL_GAP) } +function nodeY(row: number) { return PAD + row * (NODE_H + ROW_GAP) } + +// ── Parallel DAG ────────────────────────────────────────────────────────────── + +function ParallelDAG({ layout }: { layout: DagLayout }) { + const { nodes, edges, levelCount, maxRows } = layout + + const svgW = PAD * 2 + levelCount * NODE_W + (levelCount - 1) * COL_GAP + const svgH = PAD * 2 + maxRows * NODE_H + (maxRows - 1) * ROW_GAP + + const nodeMap = new Map(nodes.map(n => [n.job.id, n])) + + return ( +
+
+ {/* SVG bezier edges */} + + + {/* Absolutely-positioned job pills */} + {nodes.map(({ job, level, row }) => ( +
+ +
+ ))} +
+
+ ) +} + +// ── Linear DAG (fallback) ───────────────────────────────────────────────────── +function LinearDAG({ jobs }: { jobs: WorkflowJob[] }) { const sorted = sortJobs(jobs) return ( -
+
) } + +// ── DAG ─────────────────────────────────────────────────────────────────────── + +export function WorkflowDAG({ jobs }: WorkflowDAGProps) { + if (jobs.length === 0) { + return

No jobs to display.

+ } + + const layout = buildDagLayout(jobs) + + if (layout) { + return + } + + return +} diff --git a/packages/web/src/lib/dag-layout.test.ts b/packages/web/src/lib/dag-layout.test.ts new file mode 100644 index 0000000..6e7810e --- /dev/null +++ b/packages/web/src/lib/dag-layout.test.ts @@ -0,0 +1,193 @@ +import { describe, it, expect } from "vitest" +import { buildDagLayout, SCHEDULE_TOLERANCE_MS } from "./dag-layout.js" +import type { WorkflowJob } from "../types/index.js" + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +let _id = 0 +function makeJob(overrides: Partial = {}): WorkflowJob { + return { + id: ++_id, + name: `Job ${_id}`, + status: "completed", + conclusion: "success", + startedAt: null, + completedAt: null, + steps: [], + runnerName: "ubuntu-latest", + labels: [], + htmlUrl: "https://github.com", + ...overrides, + } +} + +/** Offset a base ISO timestamp by `ms` milliseconds. */ +function addMs(base: string, ms: number): string { + return new Date(new Date(base).getTime() + ms).toISOString() +} + +const BASE = "2024-01-01T10:00:00.000Z" + +// ── Null-return cases ───────────────────────────────────────────────────────── + +describe("buildDagLayout — null cases", () => { + it("returns null for 0 jobs", () => { + expect(buildDagLayout([])).toBeNull() + }) + + it("returns null for 1 job", () => { + const job = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + expect(buildDagLayout([job])).toBeNull() + }) + + it("returns null when no job has a startedAt timestamp", () => { + const a = makeJob({ startedAt: null }) + const b = makeJob({ startedAt: null }) + expect(buildDagLayout([a, b])).toBeNull() + }) + + it("returns null when all jobs are sequential (maxRows = 1)", () => { + // job2 starts 30 s after job1 completes → different levels → 1 job per level + const job1 = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const job2 = makeJob({ startedAt: addMs(BASE, 90_000), completedAt: addMs(BASE, 150_000) }) + const job3 = makeJob({ startedAt: addMs(BASE, 180_000), completedAt: addMs(BASE, 240_000) }) + expect(buildDagLayout([job1, job2, job3])).toBeNull() + }) +}) + +// ── Level assignment ────────────────────────────────────────────────────────── + +describe("buildDagLayout — level assignment", () => { + /** + * Diamond pattern: + * build (L0) → test (L1) ─┐ + * → lint (L1) ─┤→ deploy (L2) + */ + function makeDiamond() { + const build = makeJob({ name: "build", startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const test_ = makeJob({ name: "test", startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }) + const lint = makeJob({ name: "lint", startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }) + const deploy = makeJob({ name: "deploy", startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }) + return { build, test_, lint, deploy, jobs: [build, test_, lint, deploy] } + } + + it("assigns correct levels in a diamond pattern", () => { + const { build, test_, lint, deploy, jobs } = makeDiamond() + const layout = buildDagLayout(jobs) + expect(layout).not.toBeNull() + const nodeFor = (id: number) => layout!.nodes.find(n => n.job.id === id)! + + expect(nodeFor(build.id).level).toBe(0) + expect(nodeFor(test_.id).level).toBe(1) + expect(nodeFor(lint.id).level).toBe(1) + expect(nodeFor(deploy.id).level).toBe(2) + }) + + it("sets levelCount to 3 for the diamond pattern", () => { + const { jobs } = makeDiamond() + expect(buildDagLayout(jobs)!.levelCount).toBe(3) + }) + + it("sets maxRows to 2 for the diamond pattern", () => { + const { jobs } = makeDiamond() + expect(buildDagLayout(jobs)!.maxRows).toBe(2) + }) + + it("respects SCHEDULE_TOLERANCE_MS — jobs within tolerance are treated as sequential", () => { + // job2 starts exactly at job1.completedAt + tolerance → still a predecessor + const job1 = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const job2 = makeJob({ startedAt: addMs(BASE, 60_000 - SCHEDULE_TOLERANCE_MS), completedAt: addMs(BASE, 120_000) }) + // Two separate levels → maxRows = 1 → null + expect(buildDagLayout([job1, job2])).toBeNull() + }) + + it("jobs that start before any prior job completes land on the same level", () => { + // a and b both overlap in time → same level + const a = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const b = makeJob({ startedAt: addMs(BASE, 1_000), completedAt: addMs(BASE, 61_000) }) + const layout = buildDagLayout([a, b]) + expect(layout).not.toBeNull() + const [na, nb] = [layout!.nodes.find(n => n.job.id === a.id)!, layout!.nodes.find(n => n.job.id === b.id)!] + expect(na.level).toBe(nb.level) + }) +}) + +// ── Row centering ───────────────────────────────────────────────────────────── + +describe("buildDagLayout — row centering", () => { + it("centres a single-job column within the maxRows grid", () => { + // Diamond: level 1 has 2 jobs (maxRows=2); levels 0 and 2 have 1 job each + // offset for a 1-job column in a 2-row grid = floor((2-1)/2) = 0 + const build = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const test_ = makeJob({ startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }) + const lint = makeJob({ startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }) + const deploy = makeJob({ startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }) + const layout = buildDagLayout([build, test_, lint, deploy])! + const nodeFor = (id: number) => layout.nodes.find(n => n.job.id === id)! + + // maxRows=2, single-job column → offset = floor((2-1)/2) = 0 + expect(nodeFor(build.id).row).toBe(0) + expect(nodeFor(deploy.id).row).toBe(0) + }) + + it("assigns consecutive rows within a multi-job column", () => { + const build = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const test_ = makeJob({ startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }) + const lint = makeJob({ startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }) + const deploy = makeJob({ startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }) + const layout = buildDagLayout([build, test_, lint, deploy])! + const nodeFor = (id: number) => layout.nodes.find(n => n.job.id === id)! + + // test and lint are at level 1; their rows should be 0 and 1 (consecutive) + const rows = [nodeFor(test_.id).row, nodeFor(lint.id).row].sort((a, b) => a - b) + expect(rows).toEqual([0, 1]) + }) +}) + +// ── Edge generation ─────────────────────────────────────────────────────────── + +describe("buildDagLayout — edges", () => { + it("generates N×M edges between adjacent levels", () => { + // Level 0: [build] (1 job), Level 1: [test, lint] (2 jobs), Level 2: [deploy] (1 job) + // Expected edges: build→test, build→lint (1×2), test→deploy, lint→deploy (2×1) + const build = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const test_ = makeJob({ startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }) + const lint = makeJob({ startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }) + const deploy = makeJob({ startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }) + const { edges } = buildDagLayout([build, test_, lint, deploy])! + + const edgeSet = new Set(edges.map(e => `${e.fromId}->${e.toId}`)) + expect(edgeSet.has(`${build.id}->${test_.id}`)).toBe(true) + expect(edgeSet.has(`${build.id}->${lint.id}`)).toBe(true) + expect(edgeSet.has(`${test_.id}->${deploy.id}`)).toBe(true) + expect(edgeSet.has(`${lint.id}->${deploy.id}`)).toBe(true) + expect(edges).toHaveLength(4) + }) + + it("does not generate edges skipping a level", () => { + const build = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const test_ = makeJob({ startedAt: addMs(BASE, 61_000), completedAt: addMs(BASE, 121_000) }) + const lint = makeJob({ startedAt: addMs(BASE, 62_000), completedAt: addMs(BASE, 122_000) }) + const deploy = makeJob({ startedAt: addMs(BASE, 123_000), completedAt: addMs(BASE, 183_000) }) + const { edges } = buildDagLayout([build, test_, lint, deploy])! + + const edgeSet = new Set(edges.map(e => `${e.fromId}->${e.toId}`)) + // build should not connect directly to deploy + expect(edgeSet.has(`${build.id}->${deploy.id}`)).toBe(false) + }) +}) + +// ── Pending jobs ────────────────────────────────────────────────────────────── + +describe("buildDagLayout — pending jobs", () => { + it("places a pending job one level after the last assigned job", () => { + // parallel a+b at level 0; pending c should land at level 1 + const a = makeJob({ startedAt: BASE, completedAt: addMs(BASE, 60_000) }) + const b = makeJob({ startedAt: addMs(BASE, 1_000), completedAt: addMs(BASE, 61_000) }) + const c = makeJob({ startedAt: null, completedAt: null, status: "queued" }) + const layout = buildDagLayout([a, b, c]) + expect(layout).not.toBeNull() + const nodeC = layout!.nodes.find(n => n.job.id === c.id)! + expect(nodeC.level).toBe(1) + }) +}) diff --git a/packages/web/src/lib/dag-layout.ts b/packages/web/src/lib/dag-layout.ts new file mode 100644 index 0000000..dab47b9 --- /dev/null +++ b/packages/web/src/lib/dag-layout.ts @@ -0,0 +1,116 @@ +import type { WorkflowJob } from "../types/index.js" + +export interface DagNode { + job: WorkflowJob + level: number // column index (0 = leftmost) + row: number // row within column (0 = top, centred across all columns) +} + +export interface DagEdge { + fromId: number + toId: number +} + +export interface DagLayout { + nodes: DagNode[] + edges: DagEdge[] + levelCount: number // total columns + maxRows: number // max jobs in any single column +} + +/** + * Milliseconds of tolerance when deciding whether job A finished "just before" + * job B started. Absorbs GitHub scheduler jitter (jobs in the same wave + * typically start within 1–2 s of each other). + */ +export const SCHEDULE_TOLERANCE_MS = 5_000 + +/** + * Build a parallel DAG layout from job execution timing. + * + * Algorithm: sort jobs by startedAt, then assign each job a level equal to + * (max level of predecessors) + 1. A job P is a predecessor of job J when + * P.completedAt ≤ J.startedAt + SCHEDULE_TOLERANCE_MS — meaning P had + * finished (or nearly finished) before J began. Two jobs that started before + * either completed land on the same level and are rendered side-by-side. + * + * Edges are drawn between every job in level N and every job in level N+1. + * Without the GitHub `needs` field this is an approximation; it is exact for + * the common single-chain and fan-out/fan-in patterns. + * + * Returns null when: + * - fewer than 2 jobs are provided + * - no job has a startedAt timestamp + * - all jobs land in a single column (no parallelism to visualise) + */ +export function buildDagLayout(jobs: WorkflowJob[]): DagLayout | null { + if (jobs.length < 2) return null + if (!jobs.some(j => j.startedAt)) return null + + const sorted = [...jobs].sort((a, b) => { + if (!a.startedAt && !b.startedAt) return 0 + if (!a.startedAt) return 1 + if (!b.startedAt) return -1 + return new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime() + }) + + // ── Level assignment ────────────────────────────────────────────────────── + const levelOf = new Map() // jobId → column + + for (const job of sorted) { + if (!job.startedAt) { + // Pending job: place one column after the last assigned job + const maxSoFar = levelOf.size > 0 ? Math.max(...levelOf.values()) : -1 + levelOf.set(job.id, maxSoFar + 1) + continue + } + + const startMs = new Date(job.startedAt).getTime() + let level = 0 + + for (const [prevId, prevLevel] of levelOf) { + const prev = jobs.find(j => j.id === prevId)! + if (!prev.completedAt) continue + const endMs = new Date(prev.completedAt).getTime() + if (endMs <= startMs + SCHEDULE_TOLERANCE_MS) { + level = Math.max(level, prevLevel + 1) + } + } + + levelOf.set(job.id, level) + } + + // ── Group by level ──────────────────────────────────────────────────────── + const byLevel = new Map() + for (const job of jobs) { + const lv = levelOf.get(job.id) ?? 0 + if (!byLevel.has(lv)) byLevel.set(lv, []) + byLevel.get(lv)!.push(job) + } + + const maxRows = Math.max(...[...byLevel.values()].map(g => g.length)) + if (maxRows < 2) return null // no parallelism — linear is equivalent + + const levelCount = Math.max(...byLevel.keys()) + 1 + + // ── Row assignment (centre each column vertically) ──────────────────────── + const nodes: DagNode[] = [] + for (const [level, group] of [...byLevel.entries()].sort(([a], [b]) => a - b)) { + const offset = Math.floor((maxRows - group.length) / 2) + group.forEach((job, i) => nodes.push({ job, level, row: offset + i })) + } + + // ── Edges: every job in level N → every job in level N+1 ───────────────── + const edges: DagEdge[] = [] + for (let lv = 0; lv < levelCount - 1; lv++) { + const froms = byLevel.get(lv) ?? [] + const tos = byLevel.get(lv + 1) ?? [] + for (const f of froms) { + for (const t of tos) { + edges.push({ fromId: f.id, toId: t.id }) + } + } + } + + return { nodes, edges, levelCount, maxRows } +} From 0924c732254185f74931e9c161d75fad30c0e87f Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:43:56 +0200 Subject: [PATCH 08/51] fix: copy public folder in docker web to include favicon (#25) --- packages/web/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web/Dockerfile b/packages/web/Dockerfile index b153c16..518839d 100644 --- a/packages/web/Dockerfile +++ b/packages/web/Dockerfile @@ -47,6 +47,7 @@ RUN pnpm install --frozen-lockfile # Copy source and build COPY packages/web/index.html ./packages/web/ +COPY packages/web/public/ ./packages/web/public/ COPY packages/web/src/ ./packages/web/src/ COPY packages/web/tsconfig.json packages/web/vite.config.ts ./packages/web/ RUN pnpm --filter @dashlight/web build From 814c2e699aa8f273da1f45c5ead0df01fb7996ad Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:46:00 +0200 Subject: [PATCH 09/51] feat: optional workflow health dashboard section (#26) * feat: workflow health section for dashboard * fix: build activity align agenda * fix: repository healt table cell overflow, card borders * fix: repositories list sorting --- README.md | 4 +- env.example | 11 +- packages/server/src/index.ts | 2 + packages/server/src/routes/config.test.ts | 91 +++++++++ packages/server/src/routes/config.ts | 19 ++ packages/web/src/api/index.ts | 5 + .../components/WorkflowHealthSection.test.tsx | 177 ++++++++++++++++++ .../src/components/WorkflowHealthSection.tsx | 163 ++++++++++++++++ .../src/components/charts/RunCharts.test.tsx | 152 +++++++++++++++ .../web/src/components/charts/RunCharts.tsx | 102 +++++----- .../components/ui/TruncatingTitle.test.tsx | 161 ++++++++++++++++ .../web/src/components/ui/TruncatingTitle.tsx | 93 +++++++++ packages/web/src/lib/utils.test.ts | 22 +++ packages/web/src/lib/utils.ts | 9 + packages/web/src/main.tsx | 7 +- packages/web/src/routes/_app/-index.test.tsx | 91 +++++++++ .../src/routes/_app/-repositories.test.tsx | 61 +++++- packages/web/src/routes/_app/index.tsx | 48 +++-- packages/web/src/routes/_app/repositories.tsx | 3 +- packages/web/src/styles/globals.css | 17 ++ packages/web/src/types/index.ts | 6 + 21 files changed, 1173 insertions(+), 71 deletions(-) create mode 100644 packages/server/src/routes/config.test.ts create mode 100644 packages/server/src/routes/config.ts create mode 100644 packages/web/src/components/WorkflowHealthSection.test.tsx create mode 100644 packages/web/src/components/WorkflowHealthSection.tsx create mode 100644 packages/web/src/components/charts/RunCharts.test.tsx create mode 100644 packages/web/src/components/ui/TruncatingTitle.test.tsx create mode 100644 packages/web/src/components/ui/TruncatingTitle.tsx diff --git a/README.md b/README.md index f89febc..fc34cb0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dashlight -A self-hosted GitHub Actions dashboard. See workflow runs, job status, and per-repository health scores across personal and organisation repos in one view. Filter by branch or status, drill into job logs, and track run trends over time. Sign in with your own GitHub account (OAuth) or share a single Personal Access Token across your team (PAT mode, optionally password-protected). +A self-hosted GitHub Actions dashboard. See workflow runs, job status, and per-repository health scores across personal and organisation repos in one view. Pin specific workflows in a **Workflow Health** section for an at-a-glance view of your most important pipelines across all repos. Filter by branch or status, drill into job logs, and track run trends over time. Sign in with your own GitHub account (OAuth) or share a single Personal Access Token across your team (PAT mode, optionally password-protected). **No database. Two Docker containers. Your GitHub token never touches the browser.** @@ -218,6 +218,7 @@ All variables are set in `.env` (copy from `env.example`). |---|---|---| | `GITHUB_ORG` | — | Show only repos in this org | | `GITHUB_REPOS` | — | Show only these repos (comma-separated `owner/repo`). Takes precedence over `GITHUB_ORG` | +| `WATCH_WORKFLOWS` | — | Comma-separated workflow names to highlight in the **Workflow Health** section at the top of the dashboard (e.g. `publish,security-scan,deploy`). Matching is case-insensitive. The section is hidden when this variable is not set or no matching runs exist in any repo. | | `GITHUB_SCOPE` | — | OAuth scopes to request (leave blank for the built-in default). Ignored in PAT mode. | | `WEB_PORT` | `5174` | Host port for the nginx container | | `FRONTEND_URL` | `http://localhost:5174` | Public URL of the app — must match where users open it | @@ -445,6 +446,7 @@ Hono Server (Node 22, internal only) ├── /auth/* — GitHub OAuth flow, session management ├── /proxy/* — Authenticated GitHub API proxy (LRU cache) ├── /api/score — Repository health scoring (7 categories) + ├── /api/config — Server-side configuration exposed to the frontend (e.g. WATCH_WORKFLOWS) └── /system/* — Health check │ ▼ diff --git a/env.example b/env.example index 73ae0f4..198cc90 100644 --- a/env.example +++ b/env.example @@ -14,7 +14,7 @@ GITHUB_TOKEN= # When set, users must enter this password before accessing the dashboard. # When not set, the dashboard is open to anyone who can reach the server. # Requires SESSION_SECRET when set. -APP_PASSWORD=orR$T:eGdHH +APP_PASSWORD= # ── OAuth mode (per-user GitHub accounts) ───────────────────────────────────── # GitHub OAuth App credentials (create at github.com/settings/developers) @@ -55,6 +55,15 @@ GITHUB_REPOS= # ---- +# Workflows to highlight in the "Workflow Health" section at the top of the dashboard. +# Comma-separated workflow names (case-insensitive). When set, the section shows the +# latest run for each matching workflow across all displayed repositories. +# When not set, or when no matching runs exist in any repo, the section is hidden. +# e.g. publish,security-scan,deploy +WATCH_WORKFLOWS= + +# ---- + # In-memory LRU cache max size in MB CACHE_MAX_SIZE_MB=128 diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index a2a62fd..1b8eb16 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -14,6 +14,7 @@ import proxyRoutes from "./routes/proxy.js" import reposRoutes from "./routes/repos.js" import scoreRoutes from "./routes/score.js" import systemRoutes from "./routes/system.js" +import configRoutes from "./routes/config.js" import { authMiddleware } from "./middleware/auth.js" import { cacheInvalidateUser } from "./lib/cache.js" import type { AuthEnv } from "./middleware/auth.js" @@ -117,6 +118,7 @@ async function bootstrap() { app.route("/proxy", proxyRoutes) app.route("/api/repos", reposRoutes) app.route("/api/score", scoreRoutes) + app.route("/api/config", configRoutes) app.route("/system", systemRoutes) // Clear server-side cache for the authenticated user diff --git a/packages/server/src/routes/config.test.ts b/packages/server/src/routes/config.test.ts new file mode 100644 index 0000000..6565245 --- /dev/null +++ b/packages/server/src/routes/config.test.ts @@ -0,0 +1,91 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { Hono } from "hono" + +// ── Module mocks (hoisted) ──────────────────────────────────────────────────── + +vi.mock("../middleware/auth.js", () => ({ + authMiddleware: vi.fn(async (c: import("hono").Context, next: () => Promise) => { + c.set("session", { sub: "u1", login: "octocat", name: "Octocat", avatarUrl: "", sessionId: "s1" }) + c.set("githubToken", "tok") + await next() + }), +})) + +import configRouter from "./config.js" + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +function makeApp() { + const app = new Hono() + app.route("/api/config", configRouter) + return app +} + +beforeEach(() => { + delete process.env["WATCH_WORKFLOWS"] +}) + +afterEach(() => { + delete process.env["WATCH_WORKFLOWS"] +}) + +// ── Tests ───────────────────────────────────────────────────────────────────── + +describe("GET /api/config", () => { + it("returns empty watchWorkflows when WATCH_WORKFLOWS is not set", async () => { + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: [] }) + }) + + it("returns empty watchWorkflows when WATCH_WORKFLOWS is an empty string", async () => { + process.env["WATCH_WORKFLOWS"] = "" + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: [] }) + }) + + it("returns a single workflow name", async () => { + process.env["WATCH_WORKFLOWS"] = "publish" + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: ["publish"] }) + }) + + it("parses comma-separated workflow names", async () => { + process.env["WATCH_WORKFLOWS"] = "publish,security-scan,deploy" + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: ["publish", "security-scan", "deploy"] }) + }) + + it("trims whitespace around workflow names", async () => { + process.env["WATCH_WORKFLOWS"] = " publish , scan , deploy " + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: ["publish", "scan", "deploy"] }) + }) + + it("filters out empty entries from trailing/double commas", async () => { + process.env["WATCH_WORKFLOWS"] = "publish,,scan," + const res = await makeApp().request("/api/config") + expect(res.status).toBe(200) + const body = await res.json() + expect(body).toEqual({ watchWorkflows: ["publish", "scan"] }) + }) + + it("requires authentication — rejects unauthenticated requests", async () => { + // Temporarily override the mock to simulate an auth failure + const { authMiddleware } = await import("../middleware/auth.js") + vi.mocked(authMiddleware).mockImplementationOnce(async (c, _next) => { + return c.json({ error: "Unauthorized" }, 401) + }) + const res = await makeApp().request("/api/config") + expect(res.status).toBe(401) + }) +}) diff --git a/packages/server/src/routes/config.ts b/packages/server/src/routes/config.ts new file mode 100644 index 0000000..82300e5 --- /dev/null +++ b/packages/server/src/routes/config.ts @@ -0,0 +1,19 @@ +import { Hono } from "hono" +import { authMiddleware } from "../middleware/auth.js" +import type { AuthEnv } from "../middleware/auth.js" + +const config = new Hono() + +config.use("/*", authMiddleware) + +/** + * GET /api/config + * Returns static server configuration that the frontend needs at runtime. + */ +config.get("/", (c) => { + const raw = process.env["WATCH_WORKFLOWS"] ?? "" + const watchWorkflows = raw.split(",").map((s) => s.trim()).filter(Boolean) + return c.json({ watchWorkflows }) +}) + +export default config diff --git a/packages/web/src/api/index.ts b/packages/web/src/api/index.ts index 9ee7d05..ece2e4f 100644 --- a/packages/web/src/api/index.ts +++ b/packages/web/src/api/index.ts @@ -2,6 +2,7 @@ import { fetchApi, fetchApiText, ApiError } from "./client.js" import type { SessionUser, AuthConfig, + AppConfig, Organization, Repository, Workflow, @@ -138,6 +139,10 @@ export async function getAuthConfig(): Promise { return fetchApi("/auth/config") } +export async function getAppConfig(): Promise { + return fetchApi("/api/config") +} + export async function getMe(): Promise { return fetchApi("/auth/me") } diff --git a/packages/web/src/components/WorkflowHealthSection.test.tsx b/packages/web/src/components/WorkflowHealthSection.test.tsx new file mode 100644 index 0000000..afb71cb --- /dev/null +++ b/packages/web/src/components/WorkflowHealthSection.test.tsx @@ -0,0 +1,177 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { render, screen } from "@testing-library/react" + +// ── Module mocks (hoisted) ──────────────────────────────────────────────────── + +vi.mock("@tanstack/react-router", () => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Link: ({ children, to, params: _params, ...rest }: any) => {children}, +})) + +// ResizeObserver is used by TruncatingTitle — stub globally (class, not arrow fn) +beforeEach(() => { + vi.stubGlobal("ResizeObserver", class { observe = vi.fn(); disconnect = vi.fn() }) +}) +afterEach(() => { + vi.unstubAllGlobals() + vi.clearAllMocks() +}) + +import { WorkflowHealthSection } from "./WorkflowHealthSection.js" +import type { WorkflowRun } from "../types/index.js" + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +let _id = 0 +function makeRun(overrides: Partial & { workflowName: string }): WorkflowRun { + return { + id: ++_id, + name: overrides.workflowName, + status: "completed", + conclusion: "success", + headBranch: "main", + headSha: "abc1234", + runNumber: 1, + event: "push", + workflowId: ++_id, + workflowPath: null, + workflowName: overrides.workflowName, + repository: "owner/repo", + createdAt: "2024-01-01T10:00:00Z", + updatedAt: "2024-01-01T10:05:00Z", + runStartedAt: "2024-01-01T10:00:00Z", + runAttempt: 1, + url: "https://github.com", + htmlUrl: "https://github.com", + actor: null, + displayTitle: overrides.workflowName, + ...overrides, + } +} + +function makeRepoRuns( + fullName: string, + runs: WorkflowRun[] +): { name: string; fullName: string; runs: WorkflowRun[] } { + return { name: fullName.split("/")[1]!, fullName, runs } +} + +// ── Tests ───────────────────────────────────────────────────────────────────── + +describe("WorkflowHealthSection", () => { + it("returns nothing when watchWorkflows is empty", () => { + const { container } = render( + + ) + expect(container).toBeEmptyDOMElement() + }) + + it("returns nothing when watchWorkflows is empty even with runs", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + const { container } = render( + + ) + expect(container).toBeEmptyDOMElement() + }) + + it("returns nothing when no runs match the configured workflow names", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "ci" })])] + const { container } = render( + + ) + expect(container).toBeEmptyDOMElement() + }) + + it("returns nothing when repoRuns is empty", () => { + const { container } = render( + + ) + expect(container).toBeEmptyDOMElement() + }) + + it("renders the section title with configured workflow names", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + render() + expect(screen.getByText("Workflow Health: publish, scan")).toBeInTheDocument() + }) + + it("renders owner and repo name inside the card", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + render() + expect(screen.getByText("owner/")).toBeInTheDocument() + expect(screen.getByText("repo")).toBeInTheDocument() + }) + + it("renders a run card for each matched workflow", () => { + const repoRuns = [ + makeRepoRuns("owner/repo", [ + makeRun({ workflowName: "publish" }), + makeRun({ workflowName: "scan" }), + ]), + ] + render() + expect(screen.getByText("publish")).toBeInTheDocument() + expect(screen.getByText("scan")).toBeInTheDocument() + }) + + it("matching is case-insensitive", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "Publish" })])] + render() + expect(screen.getByText("Publish")).toBeInTheDocument() + }) + + it("excludes repos that have no matching workflows", () => { + const repoRuns = [ + makeRepoRuns("owner/repo-a", [makeRun({ workflowName: "publish" })]), + makeRepoRuns("owner/repo-b", [makeRun({ workflowName: "ci" })]), + ] + render() + expect(screen.getByText("repo-a")).toBeInTheDocument() + expect(screen.queryByText("repo-b")).not.toBeInTheDocument() + }) + + it("shows a card for each matching repo in a single flat grid", () => { + const repoRuns = [ + makeRepoRuns("owner/repo-a", [makeRun({ workflowName: "publish" })]), + makeRepoRuns("owner/repo-b", [makeRun({ workflowName: "publish" })]), + ] + const { container } = render( + + ) + expect(screen.getByText("repo-a")).toBeInTheDocument() + expect(screen.getByText("repo-b")).toBeInTheDocument() + // Both cards in a single grid — no nested sub-grids + expect(container.querySelectorAll(".latest-runs-grid")).toHaveLength(1) + expect(container.querySelectorAll(".latest-run-card")).toHaveLength(2) + }) + + it("prefers in-progress run over completed when both exist", () => { + const completed = makeRun({ workflowName: "publish", status: "completed", conclusion: "success" }) + const inProgress = makeRun({ workflowName: "publish", status: "in_progress", conclusion: null }) + const repoRuns = [makeRepoRuns("owner/repo", [completed, inProgress])] + render() + // in_progress run should have the pulse dot + const dots = document.querySelectorAll(".run-dot-pulse") + expect(dots.length).toBeGreaterThan(0) + }) + + it("only shows one card per workflow name per repo", () => { + // Two runs with the same workflow name — only one card should appear + const run1 = makeRun({ workflowName: "publish" }) + const run2 = makeRun({ workflowName: "publish" }) + const repoRuns = [makeRepoRuns("owner/repo", [run1, run2])] + render() + expect(screen.getAllByText("publish")).toHaveLength(1) + }) + + it("does not render non-matching workflow runs", () => { + const repoRuns = [ + makeRepoRuns("owner/repo", [ + makeRun({ workflowName: "publish" }), + makeRun({ workflowName: "ci" }), + ]), + ] + render() + expect(screen.queryByText("ci")).not.toBeInTheDocument() + }) +}) diff --git a/packages/web/src/components/WorkflowHealthSection.tsx b/packages/web/src/components/WorkflowHealthSection.tsx new file mode 100644 index 0000000..47de7b5 --- /dev/null +++ b/packages/web/src/components/WorkflowHealthSection.tsx @@ -0,0 +1,163 @@ +import { Link } from "@tanstack/react-router" +import { Card } from "./ui/Card.js" +import { TruncatingTitle } from "./ui/TruncatingTitle.js" +import { formatDuration, formatRelativeTime, runStatusVariant, VARIANT_COLOR } from "../lib/utils.js" +import type { WorkflowRun } from "../types/index.js" + +// ── Types ───────────────────────────────────────────────────────────────────── + +interface RepoRunEntry { + name: string + fullName: string + runs: WorkflowRun[] +} + +interface WorkflowHealthSectionProps { + watchWorkflows: string[] + repoRuns: RepoRunEntry[] +} + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +/** Prioritise in-progress/queued; fall back to most recent. */ +function pickRun(runs: WorkflowRun[]): WorkflowRun | undefined { + return runs.find((r) => r.status === "in_progress" || r.status === "queued") ?? runs[0] +} + +// ── Run dot ─────────────────────────────────────────────────────────────────── + +function RunDot({ status, conclusion }: { status: WorkflowRun["status"]; conclusion: WorkflowRun["conclusion"] }) { + const isActive = status === "in_progress" || status === "queued" + let colorClass = "run-dot-neutral" + if (conclusion === "success") colorClass = "run-dot-success" + else if (conclusion === "failure" || conclusion === "timed_out") colorClass = "run-dot-failure" + else if (conclusion === "cancelled") colorClass = "run-dot-cancelled" + else if (isActive) colorClass = "run-dot-running" + return +} + +// ── Single run card ─────────────────────────────────────────────────────────── + +function HealthRunCard({ run, fullName }: { run: WorkflowRun; fullName: string }) { + const [owner, repo] = fullName.split("/") + const isActive = run.status === "in_progress" || run.status === "queued" + const commitUrl = `https://github.com/${fullName}/commit/${run.headSha}` + const duration = formatDuration(run.runStartedAt, isActive ? null : run.updatedAt) + const variant = runStatusVariant(run.status, run.conclusion) + const color = VARIANT_COLOR[variant] + + return ( +
+ {/* Repo name — sits above the stretched link, purely informational */} +
+ {owner}/{repo} +
+
+ + {run.workflowName ?? run.name} + + +
+ +
+ + {duration} + · + {formatRelativeTime(run.runStartedAt ?? run.createdAt)} +
+
+ ) +} + +// ── Icons (inline SVG — same as used elsewhere in the dashboard) ────────────── + +function ClockIcon() { + return ( + + + + + ) +} + +function BranchIcon() { + return ( + + + + + ) +} + +function CommitIcon() { + return ( + + + + ) +} + +// ── Section ─────────────────────────────────────────────────────────────────── + +export function WorkflowHealthSection({ watchWorkflows, repoRuns }: WorkflowHealthSectionProps) { + if (watchWorkflows.length === 0) return null + + // Flatten: one entry per (repo × matched workflow), preserving watchWorkflows order + const cards: { fullName: string; run: WorkflowRun }[] = [] + for (const { fullName, runs } of repoRuns) { + for (const wfName of watchWorkflows) { + const matching = runs.filter( + (r) => r.workflowName.toLowerCase() === wfName.toLowerCase() + ) + const run = pickRun(matching) + if (run) cards.push({ fullName, run }) + } + } + + if (cards.length === 0) return null + + return ( + +
+ +
+
+ {cards.map(({ fullName, run }) => ( + + ))} +
+
+ ) +} diff --git a/packages/web/src/components/charts/RunCharts.test.tsx b/packages/web/src/components/charts/RunCharts.test.tsx new file mode 100644 index 0000000..ee86430 --- /dev/null +++ b/packages/web/src/components/charts/RunCharts.test.tsx @@ -0,0 +1,152 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { render, screen } from "@testing-library/react" +import { RepoActivityChart, paletteColor } from "./RunCharts.js" +import type { WorkflowRun } from "../../types/index.js" + +// ── Recharts mock ───────────────────────────────────────────────────────────── + +// Recharts relies on browser layout APIs unavailable in jsdom. Stub the +// components used by RepoActivityChart so tests focus on our logic. +vi.mock("recharts", () => ({ + ResponsiveContainer: ({ children }: { children: React.ReactNode }) =>
{children}
, + LineChart: ({ children }: { children: React.ReactNode }) =>
{children}
, + Line: () => null, + CartesianGrid: () => null, + XAxis: () => null, + YAxis: () => null, + Tooltip: () => null, +})) + +// ── Helpers ─────────────────────────────────────────────────────────────────── + +let _id = 0 +beforeEach(() => { _id = 0 }) +afterEach(() => { vi.clearAllMocks() }) + +function makeRun(overrides: Partial & { createdAt?: string } = {}): WorkflowRun { + return { + id: ++_id, + name: "CI", + status: "completed", + conclusion: "success", + headBranch: "main", + headSha: "abc1234", + runNumber: 1, + event: "push", + workflowId: 1, + workflowPath: null, + workflowName: "CI", + repository: "owner/repo", + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + runStartedAt: new Date().toISOString(), + runAttempt: 1, + url: "https://github.com", + htmlUrl: "https://github.com", + actor: null, + displayTitle: "CI", + ...overrides, + } +} + +function makeRepoRuns(name: string, runCount = 1) { + const fullName = `owner/${name}` + return { + name, + fullName, + runs: Array.from({ length: runCount }, () => makeRun()), + } +} + +// ── paletteColor ────────────────────────────────────────────────────────────── + +describe("paletteColor", () => { + it("returns a non-empty string for index 0", () => { + expect(paletteColor(0)).toBeTruthy() + }) + + it("wraps around when index exceeds palette length", () => { + expect(paletteColor(0)).toBe(paletteColor(8)) + }) + + it("returns distinct colors for adjacent indices", () => { + expect(paletteColor(0)).not.toBe(paletteColor(1)) + }) +}) + +// ── RepoActivityChart — empty state ────────────────────────────────────────── + +describe("RepoActivityChart — empty state", () => { + it("shows a no-activity message when all repos have no runs", () => { + render() + expect(screen.getByText(/No run activity/)).toBeInTheDocument() + }) + + it("shows a no-activity message when repoRuns is empty", () => { + render() + expect(screen.getByText(/No run activity/)).toBeInTheDocument() + }) +}) + +// ── RepoActivityChart — legend ──────────────────────────────────────────────── + +describe("RepoActivityChart — legend", () => { + it("renders a legend item for each active repo", () => { + const repoRuns = [ + makeRepoRuns("alpha", 1), + makeRepoRuns("beta", 1), + makeRepoRuns("gamma", 1), + ] + render() + expect(screen.getByText("alpha")).toBeInTheDocument() + expect(screen.getByText("beta")).toBeInTheDocument() + expect(screen.getByText("gamma")).toBeInTheDocument() + }) + + it("renders the legend outside the ResponsiveContainer wrapper", () => { + const repoRuns = [makeRepoRuns("my-repo", 1)] + const { container } = render() + const legend = container.querySelector(".activity-chart-legend") + expect(legend).toBeInTheDocument() + // The legend must NOT be a descendant of the ResponsiveContainer div + // (which is the first child div — the chart wrapper) + const chartWrapper = container.firstElementChild?.firstElementChild + expect(chartWrapper?.contains(legend)).toBe(false) + }) + + it("does not render a legend item for repos with no runs", () => { + const repoRuns = [ + makeRepoRuns("active", 1), + makeRepoRuns("inactive", 0), + ] + render() + expect(screen.getByText("active")).toBeInTheDocument() + expect(screen.queryByText("inactive")).not.toBeInTheDocument() + }) + + it("renders with many repos and long names without breaking layout classes", () => { + const names = Array.from({ length: 10 }, (_, i) => + `organisation_with_very_long_name_repo_${i + 1}` + ) + const repoRuns = names.map((n) => makeRepoRuns(n, 1)) + const { container } = render() + const legend = container.querySelector(".activity-chart-legend") + expect(legend).toBeInTheDocument() + const items = container.querySelectorAll(".activity-chart-legend-item") + expect(items).toHaveLength(10) + // Every item text is present + for (const name of names) { + expect(screen.getByText(name)).toBeInTheDocument() + } + }) + + it("assigns a distinct color circle to each legend item", () => { + const repoRuns = [makeRepoRuns("a", 1), makeRepoRuns("b", 1)] + const { container } = render() + const circles = container.querySelectorAll(".activity-chart-legend-item circle") + const fills = Array.from(circles).map((c) => c.getAttribute("fill")) + expect(fills[0]).toBe(paletteColor(0)) + expect(fills[1]).toBe(paletteColor(1)) + expect(fills[0]).not.toBe(fills[1]) + }) +}) diff --git a/packages/web/src/components/charts/RunCharts.tsx b/packages/web/src/components/charts/RunCharts.tsx index 1e9d930..f5ec333 100644 --- a/packages/web/src/components/charts/RunCharts.tsx +++ b/packages/web/src/components/charts/RunCharts.tsx @@ -10,7 +10,6 @@ import { CartesianGrid, LineChart, Line, - Legend, } from "recharts" import type { WorkflowRun } from "../../types/index.js" @@ -103,55 +102,62 @@ export function RepoActivityChart({ repoRuns }: { repoRuns: RepoRunEntry[] }) { const xInterval = Math.floor(30 / 5) return ( - - - - - - [value as number, name as string]} - /> - - {activeRepos.map(({ name }, i) => ( - + + + + + + [value as number, name as string]} /> + {activeRepos.map(({ name }, i) => ( + + ))} + + +
+ {activeRepos.map(({ name }, i) => ( + + + {name} + ))} - - +
+
) } diff --git a/packages/web/src/components/ui/TruncatingTitle.test.tsx b/packages/web/src/components/ui/TruncatingTitle.test.tsx new file mode 100644 index 0000000..98ab020 --- /dev/null +++ b/packages/web/src/components/ui/TruncatingTitle.test.tsx @@ -0,0 +1,161 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { render, screen } from "@testing-library/react" +import { TruncatingTitle } from "./TruncatingTitle.js" + +// ── ResizeObserver mock ─────────────────────────────────────────────────────── + +// Arrow functions cannot be constructors — use a class so `new ResizeObserver()` works. +const mockObserve = vi.fn() +const mockDisconnect = vi.fn() + +beforeEach(() => { + vi.stubGlobal("ResizeObserver", class { + observe = mockObserve + disconnect = mockDisconnect + }) +}) + +afterEach(() => { + vi.unstubAllGlobals() + vi.clearAllMocks() +}) + +// ── Overflow predicate helpers ──────────────────────────────────────────────── + +/** Overflow predicate: overflows while the candidate text contains `needle`. */ +const overflowsWhile = (needle: string) => (el: HTMLSpanElement) => + Boolean(el.textContent?.includes(needle)) + +// ── Tests ───────────────────────────────────────────────────────────────────── + +describe("TruncatingTitle", () => { + // ── No-overflow cases ─────────────────────────────────────────────────────── + + it("renders all items when none overflow", () => { + render() + expect(screen.getByText("Health: publish, scan, deploy")).toBeInTheDocument() + }) + + it("renders a single item without a +N suffix", () => { + render() + expect(screen.getByText("Health: publish")).toBeInTheDocument() + expect(screen.queryByText(/more/)).not.toBeInTheDocument() + }) + + it("applies the className to the span", () => { + const { container } = render( + + ) + expect(container.querySelector(".card-title")).toBeInTheDocument() + }) + + it("does not show +N suffix when the explicit predicate returns false", () => { + render( + false} + /> + ) + expect(screen.queryByText(/more/)).not.toBeInTheDocument() + expect(screen.getByText("Health: publish, scan")).toBeInTheDocument() + }) + + // ── Overflow reduction (single-pass, synchronous) ─────────────────────────── + + it("reduces to 1 item + +N more when always overflowing", () => { + render( + true} + /> + ) + expect(screen.getByText("Health: publish +2 more")).toBeInTheDocument() + }) + + it("stops reducing when overflow is resolved", () => { + // Overflowing while the full third-item string ", deploy" is present + render( + + ) + // "Health: publish, scan +1 more" — no longer contains ", deploy" → stops + expect(screen.getByText("Health: publish, scan +1 more")).toBeInTheDocument() + }) + + it("shows the correct +N count", () => { + render( + true} + /> + ) + expect(screen.getByText("X: a +4 more")).toBeInTheDocument() + }) + + it("stops at 1 item minimum and does not show +0 suffix", () => { + // With a single item, there is nothing to truncate further; + // the while loop never executes and we end up showing the 1 item without suffix. + render( + true} + /> + ) + expect(screen.getByText("X: only")).toBeInTheDocument() + expect(screen.queryByText(/more/)).not.toBeInTheDocument() + }) + + // ── Items change ──────────────────────────────────────────────────────────── + + it("expands back to full when items change and new set fits", () => { + const { rerender } = render( + true} + /> + ) + expect(screen.getByText("Health: publish +1 more")).toBeInTheDocument() + + rerender( + false} + /> + ) + expect(screen.getByText("Health: alpha, beta")).toBeInTheDocument() + }) + + it("re-applies reduction after items change when still overflowing", () => { + const { rerender } = render( + false} /> + ) + expect(screen.getByText("X: a")).toBeInTheDocument() + + rerender( + true} /> + ) + expect(screen.getByText("X: a +2 more")).toBeInTheDocument() + }) + + // ── ResizeObserver lifecycle ──────────────────────────────────────────────── + + it("sets up a ResizeObserver on mount", () => { + render() + expect(mockObserve).toHaveBeenCalled() + }) + + it("disconnects the ResizeObserver on unmount", () => { + const { unmount } = render() + unmount() + expect(mockDisconnect).toHaveBeenCalled() + }) +}) diff --git a/packages/web/src/components/ui/TruncatingTitle.tsx b/packages/web/src/components/ui/TruncatingTitle.tsx new file mode 100644 index 0000000..92e7146 --- /dev/null +++ b/packages/web/src/components/ui/TruncatingTitle.tsx @@ -0,0 +1,93 @@ +import { useState, useRef, useLayoutEffect, useEffect } from "react" + +interface TruncatingTitleProps { + prefix: string + items: string[] + className?: string + /** + * Override the overflow predicate — intended for tests only. + * Receives the span element after its textContent has been set to the + * candidate string, so implementations can inspect textContent directly. + * Default: el.scrollWidth > el.clientWidth + */ + _isOverflowing?: (el: HTMLSpanElement) => boolean +} + +const defaultIsOverflowing = (el: HTMLSpanElement) => el.scrollWidth > el.clientWidth + +/** + * Renders `prefix: item1, item2 …` on a single line. When the text would + * overflow the container, trailing items are hidden and replaced with a + * "+N more" suffix. Re-expands when the container grows (ResizeObserver). + * + * Uses a single-pass measurement strategy: mutates the span's single text + * node via nodeValue (in-place, preserving React's stateNode reference) to + * probe each candidate string, then commits the final visibleCount in one + * setState call (no cascading re-renders). The span always renders a single + * text expression so React reconciles exactly one text node — no placement + * side-effects from empty-string → non-empty transitions. + */ +export function TruncatingTitle({ + prefix, + items, + className, + _isOverflowing = defaultIsOverflowing, +}: TruncatingTitleProps) { + const [visibleCount, setVisibleCount] = useState(items.length) + // Incrementing this triggers a re-evaluation after a container resize + const [sizeTrigger, setSizeTrigger] = useState(0) + const ref = useRef(null) + + useLayoutEffect(() => { + const el = ref.current + if (!el) return + + // Mutate the existing text node in-place so React's stateNode reference + // stays valid. Using el.textContent = X would replace the DOM child, + // detaching the node React tracks and causing reconciliation artefacts. + const textNode = el.childNodes[0] as Text | undefined + if (!textNode) return + const probe = (s: string) => { textNode.nodeValue = s } + + // Check if all items fit — also handles re-expansion after resize. + // Greedy search: reduce count until truncated text fits (min 1). + // useLayoutEffect + setState is intentional: fires before paint so the + // browser never renders the intermediate probe strings. + let count = items.length + probe(`${prefix}: ${items.join(", ")}`) + if (_isOverflowing(el)) { + while (count > 1) { + count-- + const hidden = items.length - count + probe(`${prefix}: ${items.slice(0, count).join(", ")} +${hidden} more`) + if (!_isOverflowing(el)) break + } + } + + // eslint-disable-next-line react-hooks/set-state-in-effect -- useLayoutEffect+setState is the recommended React pattern for pre-paint DOM measurement + setVisibleCount(count) + }, [prefix, items, _isOverflowing, sizeTrigger]) + + // Re-evaluate on container resize so newly gained space is used + useEffect(() => { + const el = ref.current + if (!el || typeof ResizeObserver === "undefined") return + const ro = new ResizeObserver(() => setSizeTrigger((t) => t + 1)) + ro.observe(el.parentElement ?? el) + return () => ro.disconnect() + }, []) + + const hidden = items.length - visibleCount + const displayed = items.slice(0, visibleCount).join(", ") + const suffix = hidden > 0 ? ` +${hidden} more` : "" + + return ( + + {`${prefix}: ${displayed}${suffix}`} + + ) +} diff --git a/packages/web/src/lib/utils.test.ts b/packages/web/src/lib/utils.test.ts index 4b4a59b..4839599 100644 --- a/packages/web/src/lib/utils.test.ts +++ b/packages/web/src/lib/utils.test.ts @@ -10,6 +10,7 @@ import { truncate, tierLabel, tierColor, + VARIANT_COLOR, } from "./utils.js" // ── formatDuration ──────────────────────────────────────────────────────────── @@ -157,6 +158,27 @@ describe("runStatusVariant", () => { }) }) +// ── VARIANT_COLOR ───────────────────────────────────────────────────────────── + +describe("VARIANT_COLOR", () => { + it("has an entry for every StatusVariant", () => { + const variants = ["success", "failure", "running", "pending", "cancelled", "neutral"] as const + for (const v of variants) { + expect(VARIANT_COLOR[v]).toBeTruthy() + } + }) + + it("each value references a CSS custom property", () => { + for (const color of Object.values(VARIANT_COLOR)) { + expect(color).toMatch(/^var\(--/) + } + }) + + it("success and failure map to distinct colors", () => { + expect(VARIANT_COLOR.success).not.toBe(VARIANT_COLOR.failure) + }) +}) + // ── runStatusLabel ──────────────────────────────────────────────────────────── describe("runStatusLabel", () => { diff --git a/packages/web/src/lib/utils.ts b/packages/web/src/lib/utils.ts index 7126697..d1d1612 100644 --- a/packages/web/src/lib/utils.ts +++ b/packages/web/src/lib/utils.ts @@ -45,6 +45,15 @@ export function formatDateTime(dateStr: string | null): string { export type StatusVariant = "success" | "failure" | "running" | "pending" | "cancelled" | "neutral" +export const VARIANT_COLOR: Record = { + success: "var(--color-success)", + failure: "var(--color-failure)", + running: "var(--color-running)", + cancelled: "var(--color-cancelled)", + neutral: "var(--color-neutral)", + pending: "var(--color-neutral)", +} + export function runStatusVariant(status: RunStatus, conclusion: RunConclusion): StatusVariant { if (status === "in_progress" || status === "queued" || status === "waiting") return "running" if (status === "completed") { diff --git a/packages/web/src/main.tsx b/packages/web/src/main.tsx index 72f2173..4da0d63 100644 --- a/packages/web/src/main.tsx +++ b/packages/web/src/main.tsx @@ -34,12 +34,15 @@ ReactDOM.createRoot(root).render( // dehydrateOptions filter was added (which excluded auth queries). // Without this, users who loaded the app before the fix would still // have ["auth", "me"] in IndexedDB and bypass the password check on reload. - buster: "v1", + buster: "v2", // Auth state must never be restored from IndexedDB — always verify with // the server on page load so that adding APP_PASSWORD or changing auth // mode takes effect immediately without requiring a manual cache clear. dehydrateOptions: { - shouldDehydrateQuery: (query) => query.queryKey[0] !== "auth", + // "auth" must never be restored (avoids bypassing password check on reload). + // "config" must never be restored (WATCH_WORKFLOWS may change between sessions). + shouldDehydrateQuery: (query) => + query.queryKey[0] !== "auth" && query.queryKey[0] !== "config", }, }} > diff --git a/packages/web/src/routes/_app/-index.test.tsx b/packages/web/src/routes/_app/-index.test.tsx index f106df6..81d0e34 100644 --- a/packages/web/src/routes/_app/-index.test.tsx +++ b/packages/web/src/routes/_app/-index.test.tsx @@ -45,6 +45,7 @@ import { HealthTable, BuildTrendsCard, } from "./index.js" +import { VARIANT_COLOR } from "../../lib/utils.js" // ── Test helpers ────────────────────────────────────────────────────────────── @@ -266,6 +267,48 @@ describe("RepoRunCards", () => { const link = screen.getByRole("link", { name: /aabbccd/ }) expect(link).toHaveAttribute("href", "https://github.com/acme/api/commit/aabbccddee112233") }) + + // ── Colored left border ───────────────────────────────────────────────────── + + it("success run card has a green left border", () => { + const run = makeRun({ status: "completed", conclusion: "success" }) + const { container } = render() + const card = container.querySelector(".latest-run-card") as HTMLElement + expect(card.style.borderLeft).toContain(VARIANT_COLOR.success) + }) + + it("failure run card has a red left border", () => { + const run = makeRun({ status: "completed", conclusion: "failure" }) + const { container } = render() + const card = container.querySelector(".latest-run-card") as HTMLElement + expect(card.style.borderLeft).toContain(VARIANT_COLOR.failure) + }) + + it("in_progress run card has a running-color left border", () => { + const run = makeRun({ status: "in_progress", conclusion: null }) + const { container } = render() + const card = container.querySelector(".latest-run-card") as HTMLElement + expect(card.style.borderLeft).toContain(VARIANT_COLOR.running) + }) + + it("cancelled run card has a cancelled-color left border", () => { + const run = makeRun({ status: "completed", conclusion: "cancelled" }) + const { container } = render() + const card = container.querySelector(".latest-run-card") as HTMLElement + expect(card.style.borderLeft).toContain(VARIANT_COLOR.cancelled) + }) + + it("each card gets its own status-appropriate border color", () => { + const runs = [ + makeRun({ workflowId: 1, status: "completed", conclusion: "success" }), + makeRun({ workflowId: 2, status: "completed", conclusion: "failure" }), + ] + const { container } = render() + const cards = container.querySelectorAll(".latest-run-card") as NodeListOf + const borders = Array.from(cards).map((c) => c.style.borderLeft) + expect(borders[0]).toContain(VARIANT_COLOR.success) + expect(borders[1]).toContain(VARIANT_COLOR.failure) + }) }) // ── ActivityCard ────────────────────────────────────────────────────────────── @@ -485,6 +528,54 @@ describe("HealthTable", () => { expect(link).not.toHaveAttribute("href", "/repositories/$owner/$repo/runs") expect(link).toHaveAttribute("href", "/runs/$owner/$repo/$runId") }) + + // ── Truncation and layout ─────────────────────────────────────────────────── + + it("wraps workflow name in health-workflow-name-cell for truncation", () => { + const repo = makeRepo({ fullName: "owner/repo" }) + const repoRuns = [{ + name: "repo", fullName: "owner/repo", + runs: [makeRun({ workflowId: 1, workflowName: "npm_and_yarn in /microservices for @xmldom/xmldom - Update #1334106698" })], + }] + const { container } = render() + const wfRow = container.querySelector(".health-workflow-row")! + expect(wfRow.querySelector(".health-workflow-name-cell")).toBeInTheDocument() + }) + + it("workflow name link inside name-cell has truncate class", () => { + const repo = makeRepo({ fullName: "owner/repo" }) + const repoRuns = [{ + name: "repo", fullName: "owner/repo", + runs: [makeRun({ workflowId: 1, workflowName: "A Very Long Workflow Name That Should Be Truncated" })], + }] + const { container } = render() + const wfRow = container.querySelector(".health-workflow-row")! + const nameCell = wfRow.querySelector(".health-workflow-name-cell")! + const link = nameCell.querySelector("a") + expect(link?.classList.contains("truncate")).toBe(true) + }) + + it("workflow last-run cell has health-last-run class for no-wrap", () => { + const repo = makeRepo({ fullName: "owner/repo" }) + const repoRuns = [{ + name: "repo", fullName: "owner/repo", + runs: [makeRun({ workflowId: 1, workflowName: "CI" })], + }] + const { container } = render() + const wfRow = container.querySelector(".health-workflow-row")! + // Second td is the last-run cell + const lastRunTd = wfRow.querySelectorAll("td")[1] + expect(lastRunTd?.classList.contains("health-last-run")).toBe(true) + }) + + it("repo-level last-run cell has health-last-run class for no-wrap", () => { + const repo = makeRepo({ fullName: "owner/repo" }) + const repoRuns = [{ name: "repo", fullName: "owner/repo", runs: [makeRun()] }] + const { container } = render() + const repoRow = container.querySelector(".health-repo-row")! + const lastRunTd = repoRow.querySelectorAll("td")[1] + expect(lastRunTd?.classList.contains("health-last-run")).toBe(true) + }) }) // ── BuildTrendsCard ─────────────────────────────────────────────────────────── diff --git a/packages/web/src/routes/_app/-repositories.test.tsx b/packages/web/src/routes/_app/-repositories.test.tsx index d75d0eb..45f556d 100644 --- a/packages/web/src/routes/_app/-repositories.test.tsx +++ b/packages/web/src/routes/_app/-repositories.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach } from "vitest" -import { render, screen } from "@testing-library/react" +import { render, screen, fireEvent } from "@testing-library/react" import React from "react" import type { Repository } from "../../types/index.js" @@ -151,4 +151,63 @@ describe("Repositories list", () => { render() expect(screen.getByText("Actions not enabled")).toBeInTheDocument() }) + + // ── Alphabetical ordering ─────────────────────────────────────────────────── + + it("renders repos in alphabetical order by fullName", () => { + const repos = [ + makeRepo({ id: 1, fullName: "acme/zebra", name: "zebra" }), + makeRepo({ id: 2, fullName: "acme/alpha", name: "alpha" }), + makeRepo({ id: 3, fullName: "acme/middle", name: "middle" }), + ] + vi.mocked(useQuery) + .mockReturnValueOnce({ data: repos, isLoading: false } as never) + .mockReturnValue({ data: { runs: [], actionsDisabled: false }, isLoading: false } as never) + const { container } = render() + const links = container.querySelectorAll("tbody tr td a") + const names = Array.from(links).map((a) => a.textContent) + expect(names).toEqual(["alpha", "middle", "zebra"]) + }) + + it("sorting is stable regardless of the API response order", () => { + const repos = [ + makeRepo({ id: 3, fullName: "org/charlie", name: "charlie" }), + makeRepo({ id: 1, fullName: "org/alpha", name: "alpha" }), + makeRepo({ id: 2, fullName: "org/bravo", name: "bravo" }), + ] + vi.mocked(useQuery) + .mockReturnValueOnce({ data: repos, isLoading: false } as never) + .mockReturnValue({ data: { runs: [], actionsDisabled: false }, isLoading: false } as never) + const { container } = render() + const links = container.querySelectorAll("tbody tr td a") + const names = Array.from(links).map((a) => a.textContent) + expect(names).toEqual(["alpha", "bravo", "charlie"]) + }) + + it("alphabetical order is preserved after filter narrows the list", () => { + const repos = [ + makeRepo({ id: 1, fullName: "org/go-utils", name: "go-utils", language: "Go" }), + makeRepo({ id: 2, fullName: "org/go-server", name: "go-server", language: "Go" }), + makeRepo({ id: 3, fullName: "org/ts-client", name: "ts-client", language: "TypeScript" }), + ] + // Use mockImplementation so re-renders after fireEvent still get the right data per query + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(useQuery).mockImplementation((options: any) => { + if (options.queryKey[0] === "repos") { + return { data: repos, isLoading: false } as never + } + return { data: { runs: [], actionsDisabled: false }, isLoading: false } as never + }) + + const { container } = render() + // All three visible and sorted before filtering + let links = container.querySelectorAll("tbody tr td a") + expect(Array.from(links).map((a) => a.textContent)).toEqual(["go-server", "go-utils", "ts-client"]) + + // Type "go" — only the two go repos remain, still sorted + fireEvent.change(screen.getByPlaceholderText("Search here..."), { target: { value: "go" } }) + + links = container.querySelectorAll("tbody tr td a") + expect(Array.from(links).map((a) => a.textContent)).toEqual(["go-server", "go-utils"]) + }) }) diff --git a/packages/web/src/routes/_app/index.tsx b/packages/web/src/routes/_app/index.tsx index 990ad41..d66862f 100644 --- a/packages/web/src/routes/_app/index.tsx +++ b/packages/web/src/routes/_app/index.tsx @@ -1,13 +1,14 @@ import React, { useState } from "react" import { createFileRoute, Link } from "@tanstack/react-router" import { useQuery, useQueries } from "@tanstack/react-query" -import { getRepos, getRuns } from "../../api/index.js" +import { getRepos, getRuns, getAppConfig } from "../../api/index.js" import { PageSpinner } from "../../components/ui/Spinner.js" import { Card, CardHeader } from "../../components/ui/Card.js" import { RepoActivityChart, BuildTrendChart } from "../../components/charts/RunCharts.js" import type { RepoRunEntry } from "../../components/charts/RunCharts.js" import { SuccessSquares } from "../../components/ui/SuccessSquares.js" -import { formatRelativeTime, computeRunSummary, formatDuration } from "../../lib/utils.js" +import { formatRelativeTime, computeRunSummary, formatDuration, runStatusVariant, VARIANT_COLOR } from "../../lib/utils.js" +import { WorkflowHealthSection } from "../../components/WorkflowHealthSection.js" import type { Repository, WorkflowRun } from "../../types/index.js" export const Route = createFileRoute("/_app/")({ @@ -21,6 +22,12 @@ function Dashboard() { refetchInterval: 60_000, }) + const { data: appConfig } = useQuery({ + queryKey: ["config"], + queryFn: () => getAppConfig(), + staleTime: Infinity, + }) + const repoList = (repos ?? []).slice(0, 10) // useQueries handles a dynamic-length array without violating Rules of Hooks @@ -44,11 +51,14 @@ function Dashboard() { runs: runResults[i]?.data?.runs ?? [], })) + const watchWorkflows = appConfig?.watchWorkflows ?? [] + return (
- + +
@@ -95,11 +105,13 @@ export function RepoRunCards({ fullName, runs }: { fullName: string; runs: Workf const isActive = run.status === "in_progress" || run.status === "queued" const commitUrl = `https://github.com/${fullName}/commit/${run.headSha}` const duration = formatDuration(run.runStartedAt, isActive ? null : run.updatedAt) + const borderColor = VARIANT_COLOR[runStatusVariant(run.status, run.conclusion)] return (
+ {lastRun ? ( @@ -422,20 +434,22 @@ export function HealthTable({ repoRuns, repos }: { repoRuns: RepoRunEntry[]; rep return (
- - {wfLast ? ( - - {wf.name} - - ) : ( - {wf.name} - )} + + + {wfLast ? ( + + {wf.name} + + ) : ( + {wf.name} + )} + + {wfLast ? ( diff --git a/packages/web/src/routes/_app/repositories.tsx b/packages/web/src/routes/_app/repositories.tsx index ce61ba4..94fa386 100644 --- a/packages/web/src/routes/_app/repositories.tsx +++ b/packages/web/src/routes/_app/repositories.tsx @@ -35,7 +35,7 @@ function Repositories() { } const q = filter.toLowerCase() - const visibleRepos = q + const visibleRepos = (q ? repos.filter((r) => r.fullName.toLowerCase().includes(q) || (r.description?.toLowerCase().includes(q) ?? false) || @@ -43,6 +43,7 @@ function Repositories() { r.topics.some((t) => t.toLowerCase().includes(q)) ) : repos + ).toSorted((a, b) => a.fullName.localeCompare(b.fullName)) const title = q ? `Repositories (${visibleRepos.length} of ${repos.length})` diff --git a/packages/web/src/styles/globals.css b/packages/web/src/styles/globals.css index ac326ba..5082356 100644 --- a/packages/web/src/styles/globals.css +++ b/packages/web/src/styles/globals.css @@ -75,6 +75,7 @@ a:hover { text-decoration: underline; } .main-content { margin-left: var(--sidebar-width); flex: 1; + min-width: 0; display: flex; flex-direction: column; } @@ -293,6 +294,17 @@ tr:hover td { background: var(--color-bg-secondary); } .trend-item { min-width: 0; } .trend-item-label { font-size: 12px; font-weight: 600; margin-bottom: 0.5rem; } +/* ── Build Activity chart legend ─────────────────────────────────────────── */ +.activity-chart-legend { + display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem 1rem; + padding-top: 0.5rem; + font-size: 11px; color: var(--color-text-secondary); +} +.activity-chart-legend-item { + display: flex; align-items: center; gap: 0.35rem; + white-space: nowrap; +} + /* ── Build Activity stats ────────────────────────────────────────────────── */ .activity-stats { display: flex; flex-wrap: wrap; gap: 1.25rem; @@ -361,6 +373,11 @@ tr:hover td { background: var(--color-bg-secondary); } font-size: 12px; border-bottom: none; background: transparent; } +/* Allow the name cell to shrink and truncate rather than expanding the row */ +.health-workflow-row td:first-child { max-width: 0; overflow: hidden; } +.health-workflow-name-cell { display: flex; align-items: center; overflow: hidden; min-width: 0; } +/* Prevent date strings like "Nov 21" from wrapping across lines */ +.health-last-run { white-space: nowrap; } tr:has(+ .health-repo-label-row) td { padding-bottom: 0.875rem; } tr + .health-repo-label-row td { border-top: 1px solid var(--color-border); padding-top: 1.75rem; } .health-workflow-row:hover td { background: var(--color-bg-secondary); } diff --git a/packages/web/src/types/index.ts b/packages/web/src/types/index.ts index 88ecbe2..e8dbaf2 100644 --- a/packages/web/src/types/index.ts +++ b/packages/web/src/types/index.ts @@ -167,3 +167,9 @@ export interface ActivePipeline { run: WorkflowRun repository: string } + +// ── App config ──────────────────────────────────────────────────────────────── + +export interface AppConfig { + watchWorkflows: string[] +} From eb3957b6eb47fbc7ac9fbe322b7645f3238a721a Mon Sep 17 00:00:00 2001 From: Max Epperlein Date: Tue, 28 Apr 2026 20:32:10 +0200 Subject: [PATCH 10/51] fix: applyBump in compute next version script --- .../__tests__/compute-next-version.test.mjs | 37 +++++++++++++++++++ scripts/compute-next-version.mjs | 10 +++++ 2 files changed, 47 insertions(+) diff --git a/scripts/__tests__/compute-next-version.test.mjs b/scripts/__tests__/compute-next-version.test.mjs index 34a0f62..1c73e31 100644 --- a/scripts/__tests__/compute-next-version.test.mjs +++ b/scripts/__tests__/compute-next-version.test.mjs @@ -74,6 +74,36 @@ describe("applyBump", () => { it("falls back to patch for an unrecognised release type", () => { expect(applyBump("1.2.3", "unknown")).toBe("1.2.4"); }); + + // Pre-release versions — always bump the counter, ignore bump type + it("increments rc counter for a patch bump (rc.1 → rc.2)", () => { + expect(applyBump("1.0.0-rc.1", "patch")).toBe("1.0.0-rc.2"); + }); + + it("increments rc counter for a minor bump — does not jump to stable", () => { + expect(applyBump("1.0.0-rc.1", "minor")).toBe("1.0.0-rc.2"); + }); + + it("increments rc counter for a major bump — does not jump to stable", () => { + expect(applyBump("1.0.0-rc.1", "major")).toBe("1.0.0-rc.2"); + }); + + it("handles rc counter larger than 9", () => { + expect(applyBump("1.0.0-rc.9", "patch")).toBe("1.0.0-rc.10"); + }); + + it("preserves the base version digits for pre-release", () => { + expect(applyBump("2.3.4-rc.1", "minor")).toBe("2.3.4-rc.2"); + }); + + it("works with alpha and beta labels", () => { + expect(applyBump("1.0.0-alpha.1", "patch")).toBe("1.0.0-alpha.2"); + expect(applyBump("1.0.0-beta.3", "minor")).toBe("1.0.0-beta.4"); + }); + + it("never produces NaN for a pre-release version", () => { + expect(applyBump("1.0.0-rc.1", "patch")).not.toContain("NaN"); + }); }); // ── computeNextVersion ─────────────────────────────────────────────────────── @@ -117,4 +147,11 @@ describe("computeNextVersion", () => { mockBump.mockResolvedValue({ releaseType: "major" }); expect(await computeNextVersion()).toBe("1.0.0"); }); + + it("increments rc counter when current version is a pre-release (feat commits do not skip to stable)", async () => { + vi.mocked(readFileSync).mockReturnValue(JSON.stringify({ version: "1.0.0-rc.1" })); + vi.mocked(execSync).mockReturnValue(Buffer.from("v1.0.0-rc.1\n")); + mockBump.mockResolvedValue({ releaseType: "minor" }); + expect(await computeNextVersion()).toBe("1.0.0-rc.2"); + }); }); diff --git a/scripts/compute-next-version.mjs b/scripts/compute-next-version.mjs index 5b27f6f..75221c5 100644 --- a/scripts/compute-next-version.mjs +++ b/scripts/compute-next-version.mjs @@ -42,8 +42,18 @@ export function getLastTag() { /** * Apply a semver bump type to a version string. * Any unrecognised type falls back to `patch`. + * + * Pre-release versions (e.g. 1.0.0-rc.1) always bump the pre-release counter + * (→ 1.0.0-rc.2) regardless of the commit-derived release type. Promoting a + * pre-release to a stable version must be done by manually updating + * package.json before the release is triggered. */ export function applyBump(version, releaseType) { + const preMatch = version.match(/^(\d+\.\d+\.\d+)-(.+?)\.(\d+)$/); + if (preMatch) { + const [, base, label, num] = preMatch; + return `${base}-${label}.${Number(num) + 1}`; + } const [major, minor, patch] = version.split(".").map(Number); if (releaseType === "major") return `${major + 1}.0.0`; if (releaseType === "minor") return `${major}.${minor + 1}.0`; From 7a69f2231e47ba51b848a5aa0d963193d14216ce Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Thu, 7 May 2026 10:44:04 +0200 Subject: [PATCH 11/51] fix: bump hono to 4.12.18 to patch bodyLimit bypass (#28) --- packages/server/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index b420ad8..bf47a0d 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "@hono/node-server": "^1.19.14", - "hono": "^4.12.14", + "hono": "^4.12.18", "jose": "^6.2.2", "js-yaml": "^4.1.1", "lru-cache": "^11.3.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6c10699..662328a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,10 +49,10 @@ importers: dependencies: '@hono/node-server': specifier: ^1.19.14 - version: 1.19.14(hono@4.12.14) + version: 1.19.14(hono@4.12.18) hono: - specifier: ^4.12.14 - version: 4.12.14 + specifier: ^4.12.18 + version: 4.12.18 jose: specifier: ^6.2.2 version: 6.2.2 @@ -1493,8 +1493,8 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.14: - resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==} + hono@4.12.18: + resolution: {integrity: sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -2580,9 +2580,9 @@ snapshots: '@exodus/bytes@1.15.0': {} - '@hono/node-server@1.19.14(hono@4.12.14)': + '@hono/node-server@1.19.14(hono@4.12.18)': dependencies: - hono: 4.12.14 + hono: 4.12.18 '@humanfs/core@0.19.1': {} @@ -3553,7 +3553,7 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.14: {} + hono@4.12.18: {} html-encoding-sniffer@6.0.0: dependencies: From a50b5c9b0b4384674c16a044817418b217c03c89 Mon Sep 17 00:00:00 2001 From: Max Epperlein <20338900+manieperplex@users.noreply.github.com> Date: Thu, 7 May 2026 18:36:28 +0200 Subject: [PATCH 12/51] feat: repository runner, workflow health section ui adjustments (#29) * feat: workflow names as subheading for workflow health * feat: repository detail runner section * feat: workflow health section use reponame without owner as default, show only when different owners with same reponame --- packages/server/src/lib/cache.ts | 1 + packages/server/src/routes/proxy.ts | 1 + packages/web/src/api/index.ts | 24 +++++ .../components/WorkflowHealthSection.test.tsx | 101 ++++++++++++++++-- .../src/components/WorkflowHealthSection.tsx | 53 +++++++-- .../components/ui/TruncatingTitle.test.tsx | 18 ++++ .../web/src/components/ui/TruncatingTitle.tsx | 13 ++- .../_app/-repositories.$owner.$repo.test.tsx | 80 +++++++++++++- .../_app/-runs_.$owner.$repo.$runId.test.tsx | 16 ++- .../routes/_app/repositories.$owner.$repo.tsx | 55 +++++++++- .../routes/_app/runs_.$owner.$repo.$runId.tsx | 13 ++- packages/web/src/types/index.ts | 9 ++ 12 files changed, 358 insertions(+), 26 deletions(-) diff --git a/packages/server/src/lib/cache.ts b/packages/server/src/lib/cache.ts index ec8e8b3..509e88c 100644 --- a/packages/server/src/lib/cache.ts +++ b/packages/server/src/lib/cache.ts @@ -9,6 +9,7 @@ export const TTL = { workflows: 10 * 60 * 1000, repos: 15 * 60 * 1000, orgs: 30 * 60 * 1000, + runners: 5 * 60 * 1000, score: 24 * 60 * 60 * 1000, yaml: 7 * 24 * 60 * 60 * 1000, logs: 7 * 24 * 60 * 60 * 1000, diff --git a/packages/server/src/routes/proxy.ts b/packages/server/src/routes/proxy.ts index 04d3978..1073f9d 100644 --- a/packages/server/src/routes/proxy.ts +++ b/packages/server/src/routes/proxy.ts @@ -233,6 +233,7 @@ function resolveTtl(path: string): number { if (path.match(/\/repos\/[^/]+\/[^/]+\/check-runs/)) return TTL.annotations if (path.match(/\/repos\/[^/]+\/[^/]+\/git\/trees/)) return TTL.yaml if (path.match(/\/repos\/[^/]+\/[^/]+\/actions\/jobs\/[^/]+\/logs/)) return TTL.logs + if (path.match(/\/repos\/[^/]+\/[^/]+\/actions\/runners/)) return TTL.runners if ( path.match(/\/repos\/[^/]+\/[^/]+\/community\/profile/) || path.match(/\/repos\/[^/]+\/[^/]+\/branches\/[^/]+\/protection/) diff --git a/packages/web/src/api/index.ts b/packages/web/src/api/index.ts index ece2e4f..8594c66 100644 --- a/packages/web/src/api/index.ts +++ b/packages/web/src/api/index.ts @@ -10,6 +10,7 @@ import type { WorkflowJob, RunArtifact, RepositoryScore, + SelfHostedRunner, RunStatus, RunConclusion, } from "../types/index.js" @@ -50,6 +51,11 @@ interface GHJob { interface GHArtifact { id: number; name: string; size_in_bytes: number; expired: boolean } +interface GHRunner { + id: number; name: string; os: string + status: "online" | "offline"; busy: boolean + labels: Array<{ id: number; name: string; type: string }> +} // ── Normalizers ─────────────────────────────────────────────────────────────── @@ -133,6 +139,17 @@ function normalizeJob(j: GHJob): WorkflowJob { } } +function normalizeRunner(r: GHRunner): SelfHostedRunner { + return { + id: r.id, + name: r.name, + os: r.os, + status: r.status, + busy: r.busy, + labels: r.labels.map((l) => l.name), + } +} + // ── Auth ────────────────────────────────────────────────────────────────────── export async function getAuthConfig(): Promise { @@ -300,6 +317,13 @@ export async function cancelRun(owner: string, repo: string, runId: number): Pro ) } +export async function getRepoRunners(owner: string, repo: string): Promise { + const res = await fetchApi<{ runners: GHRunner[] }>( + `/proxy/repos/${owner}/${repo}/actions/runners` + ) + return (res.runners ?? []).map(normalizeRunner) +} + // ── Scoring ─────────────────────────────────────────────────────────────────── export async function getRepoScore( diff --git a/packages/web/src/components/WorkflowHealthSection.test.tsx b/packages/web/src/components/WorkflowHealthSection.test.tsx index afb71cb..d51fcf1 100644 --- a/packages/web/src/components/WorkflowHealthSection.test.tsx +++ b/packages/web/src/components/WorkflowHealthSection.test.tsx @@ -17,7 +17,7 @@ afterEach(() => { vi.clearAllMocks() }) -import { WorkflowHealthSection } from "./WorkflowHealthSection.js" +import { WorkflowHealthSection, repoDisplayLabel } from "./WorkflowHealthSection.js" import type { WorkflowRun } from "../types/index.js" // ── Helpers ─────────────────────────────────────────────────────────────────── @@ -89,17 +89,39 @@ describe("WorkflowHealthSection", () => { expect(container).toBeEmptyDOMElement() }) - it("renders the section title with configured workflow names", () => { + it("renders 'Workflow Health' as the section title", () => { const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] render() - expect(screen.getByText("Workflow Health: publish, scan")).toBeInTheDocument() + expect(screen.getByText("Workflow Health")).toBeInTheDocument() }) - it("renders owner and repo name inside the card", () => { + it("renders workflow names as a subtitle on a separate element", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + render() + expect(screen.getByText("publish, scan")).toBeInTheDocument() + }) + + it("title and subtitle are separate DOM elements", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + const { container } = render() + const title = container.querySelector(".card-title") + const subtitle = container.querySelector(".card-header .text-muted.text-small") + expect(title?.textContent).toBe("Workflow Health") + expect(subtitle?.textContent).toBe("publish, scan") + }) + + it("card-header uses stretch alignment so the subtitle span is width-constrained", () => { + const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] + const { container } = render() + const header = container.querySelector(".card-header") as HTMLElement + expect(header.style.alignItems).toBe("stretch") + }) + + it("shows only repo short-name when there is no name collision", () => { const repoRuns = [makeRepoRuns("owner/repo", [makeRun({ workflowName: "publish" })])] render() - expect(screen.getByText("owner/")).toBeInTheDocument() expect(screen.getByText("repo")).toBeInTheDocument() + expect(screen.queryByText(/owner/)).not.toBeInTheDocument() }) it("renders a run card for each matched workflow", () => { @@ -160,8 +182,8 @@ describe("WorkflowHealthSection", () => { const run1 = makeRun({ workflowName: "publish" }) const run2 = makeRun({ workflowName: "publish" }) const repoRuns = [makeRepoRuns("owner/repo", [run1, run2])] - render() - expect(screen.getAllByText("publish")).toHaveLength(1) + const { container } = render() + expect(container.querySelectorAll(".latest-run-card")).toHaveLength(1) }) it("does not render non-matching workflow runs", () => { @@ -174,4 +196,69 @@ describe("WorkflowHealthSection", () => { render() expect(screen.queryByText("ci")).not.toBeInTheDocument() }) + + it("does not show owner prefix when the same repo has multiple workflow cards", () => { + const repoRuns = [ + makeRepoRuns("owner/api", [ + makeRun({ workflowName: "publish" }), + makeRun({ workflowName: "scan" }), + ]), + ] + render() + expect(screen.queryByText(/…\//)).not.toBeInTheDocument() + expect(screen.getAllByText("api")).toHaveLength(2) + }) + + it("shows abbreviated owner prefix when two repos share the same short-name", () => { + const repoRuns = [ + makeRepoRuns("manifold/api", [makeRun({ workflowName: "publish" })]), + makeRepoRuns("acmecorp/api", [makeRun({ workflowName: "publish" })]), + ] + render() + expect(screen.getByText("man…/")).toBeInTheDocument() + expect(screen.getByText("acm…/")).toBeInTheDocument() + expect(screen.getAllByText("api")).toHaveLength(2) + }) + + it("does not show owner prefix for repos whose short-name is unique", () => { + const repoRuns = [ + makeRepoRuns("manifold/api", [makeRun({ workflowName: "publish" })]), + makeRepoRuns("acmecorp/api", [makeRun({ workflowName: "publish" })]), + makeRepoRuns("acmecorp/website", [makeRun({ workflowName: "publish" })]), + ] + render() + // "api" collides — both get prefix + expect(screen.getByText("man…/")).toBeInTheDocument() + expect(screen.getByText("acm…/")).toBeInTheDocument() + // "website" is unique — no prefix + expect(screen.getByText("website")).toBeInTheDocument() + expect(screen.queryByText(/acm…\/.*website/)).not.toBeInTheDocument() + }) +}) + +// ── repoDisplayLabel ────────────────────────────────────────────────────────── + +describe("repoDisplayLabel", () => { + it("returns null owner when repo name is unique", () => { + const result = repoDisplayLabel("acme/api", new Set()) + expect(result).toEqual({ owner: null, repo: "api" }) + }) + + it("returns abbreviated owner when repo name is in the duplicate set", () => { + const result = repoDisplayLabel("manifold/api", new Set(["api"])) + expect(result).toEqual({ owner: "man…", repo: "api" }) + }) + + it("abbreviation uses exactly the first 3 characters of the owner", () => { + const result = repoDisplayLabel("ab/api", new Set(["api"])) + expect(result.owner).toBe("ab…") + + const result2 = repoDisplayLabel("abcdefgh/api", new Set(["api"])) + expect(result2.owner).toBe("abc…") + }) + + it("extracts the repo part correctly for names containing slashes only once", () => { + const result = repoDisplayLabel("my-org/my-repo", new Set()) + expect(result.repo).toBe("my-repo") + }) }) diff --git a/packages/web/src/components/WorkflowHealthSection.tsx b/packages/web/src/components/WorkflowHealthSection.tsx index 47de7b5..a8c1cba 100644 --- a/packages/web/src/components/WorkflowHealthSection.tsx +++ b/packages/web/src/components/WorkflowHealthSection.tsx @@ -24,6 +24,22 @@ function pickRun(runs: WorkflowRun[]): WorkflowRun | undefined { return runs.find((r) => r.status === "in_progress" || r.status === "queued") ?? runs[0] } +/** + * Returns the display label for a repo within a set of cards. + * Normally just the repo short-name; when another card shares that + * short-name (different owner), prefixes the first 3 chars of the + * owner followed by "…/" to disambiguate — e.g. "man…/api". + */ +export function repoDisplayLabel(fullName: string, duplicateRepoNames: Set): { owner: string | null; repo: string } { + const slash = fullName.indexOf("/") + const owner = fullName.slice(0, slash) + const repo = fullName.slice(slash + 1) + if (duplicateRepoNames.has(repo)) { + return { owner: `${owner.slice(0, 3)}…`, repo } + } + return { owner: null, repo } +} + // ── Run dot ─────────────────────────────────────────────────────────────────── function RunDot({ status, conclusion }: { status: WorkflowRun["status"]; conclusion: WorkflowRun["conclusion"] }) { @@ -38,13 +54,20 @@ function RunDot({ status, conclusion }: { status: WorkflowRun["status"]; conclus // ── Single run card ─────────────────────────────────────────────────────────── -function HealthRunCard({ run, fullName }: { run: WorkflowRun; fullName: string }) { - const [owner, repo] = fullName.split("/") +function HealthRunCard({ run, fullName, duplicateRepoNames }: { + run: WorkflowRun + fullName: string + duplicateRepoNames: Set +}) { + const slash = fullName.indexOf("/") + const ownerRaw = fullName.slice(0, slash) + const repo = fullName.slice(slash + 1) const isActive = run.status === "in_progress" || run.status === "queued" const commitUrl = `https://github.com/${fullName}/commit/${run.headSha}` const duration = formatDuration(run.runStartedAt, isActive ? null : run.updatedAt) const variant = runStatusVariant(run.status, run.conclusion) const color = VARIANT_COLOR[variant] + const { owner: ownerPrefix } = repoDisplayLabel(fullName, duplicateRepoNames) return (
- {owner}/{repo} + {ownerPrefix && {ownerPrefix}/}{repo}
{run.workflowName ?? run.name} @@ -148,14 +171,30 @@ export function WorkflowHealthSection({ watchWorkflows, repoRuns }: WorkflowHeal if (cards.length === 0) return null + // Detect repo short-names that appear under more than one distinct owner + const repoOwnerMap = new Map>() + for (const { fullName } of cards) { + const slash = fullName.indexOf("/") + const owner = fullName.slice(0, slash) + const repo = fullName.slice(slash + 1) + if (!repoOwnerMap.has(repo)) repoOwnerMap.set(repo, new Set()) + repoOwnerMap.get(repo)!.add(owner) + } + const duplicateRepoNames = new Set( + [...repoOwnerMap.entries()] + .filter(([, owners]) => owners.size > 1) + .map(([repo]) => repo) + ) + return ( -
- +
+ Workflow Health +
{cards.map(({ fullName, run }) => ( - + ))}
diff --git a/packages/web/src/components/ui/TruncatingTitle.test.tsx b/packages/web/src/components/ui/TruncatingTitle.test.tsx index 98ab020..4c2797a 100644 --- a/packages/web/src/components/ui/TruncatingTitle.test.tsx +++ b/packages/web/src/components/ui/TruncatingTitle.test.tsx @@ -146,6 +146,24 @@ describe("TruncatingTitle", () => { expect(screen.getByText("X: a +2 more")).toBeInTheDocument() }) + // ── Prefix-less mode ─────────────────────────────────────────────────────── + + it("renders items without a prefix or colon when prefix is omitted", () => { + render() + expect(screen.getByText("publish, scan")).toBeInTheDocument() + expect(screen.queryByText(/:/)).not.toBeInTheDocument() + }) + + it("truncates correctly with no prefix", () => { + render( + true} + /> + ) + expect(screen.getByText("publish +2 more")).toBeInTheDocument() + }) + // ── ResizeObserver lifecycle ──────────────────────────────────────────────── it("sets up a ResizeObserver on mount", () => { diff --git a/packages/web/src/components/ui/TruncatingTitle.tsx b/packages/web/src/components/ui/TruncatingTitle.tsx index 92e7146..90106f0 100644 --- a/packages/web/src/components/ui/TruncatingTitle.tsx +++ b/packages/web/src/components/ui/TruncatingTitle.tsx @@ -1,7 +1,8 @@ import { useState, useRef, useLayoutEffect, useEffect } from "react" interface TruncatingTitleProps { - prefix: string + /** Optional label prepended as `prefix: items`. Omit to render items only. */ + prefix?: string items: string[] className?: string /** @@ -28,7 +29,7 @@ const defaultIsOverflowing = (el: HTMLSpanElement) => el.scrollWidth > el.client * side-effects from empty-string → non-empty transitions. */ export function TruncatingTitle({ - prefix, + prefix = "", items, className, _isOverflowing = defaultIsOverflowing, @@ -53,13 +54,15 @@ export function TruncatingTitle({ // Greedy search: reduce count until truncated text fits (min 1). // useLayoutEffect + setState is intentional: fires before paint so the // browser never renders the intermediate probe strings. + const fmt = (text: string) => prefix ? `${prefix}: ${text}` : text + let count = items.length - probe(`${prefix}: ${items.join(", ")}`) + probe(fmt(items.join(", "))) if (_isOverflowing(el)) { while (count > 1) { count-- const hidden = items.length - count - probe(`${prefix}: ${items.slice(0, count).join(", ")} +${hidden} more`) + probe(fmt(`${items.slice(0, count).join(", ")} +${hidden} more`)) if (!_isOverflowing(el)) break } } @@ -87,7 +90,7 @@ export function TruncatingTitle({ className={className} style={{ whiteSpace: "nowrap", overflow: "hidden", display: "block", minWidth: 0, flex: 1 }} > - {`${prefix}: ${displayed}${suffix}`} + {prefix ? `${prefix}: ${displayed}${suffix}` : `${displayed}${suffix}`} ) } diff --git a/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx b/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx index 2512c18..b691d76 100644 --- a/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx +++ b/packages/web/src/routes/_app/-repositories.$owner.$repo.test.tsx @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest" import { render, screen } from "@testing-library/react" -import type { WorkflowRun, Workflow } from "../../types/index.js" +import type { WorkflowRun, Workflow, SelfHostedRunner } from "../../types/index.js" // ── Mocks (must precede imports of the module under test) ───────────────────── @@ -27,6 +27,7 @@ vi.mock("../../api/index.js", () => ({ getRepoScore: vi.fn(), getWorkflows: vi.fn(), getRuns: vi.fn(), + getRepoRunners: vi.fn(), })) vi.mock("../../components/charts/RunCharts.js", () => ({ @@ -72,7 +73,7 @@ vi.mock("../../components/ui/EventBadge.js", () => ({ import React from "react" import { useQuery } from "@tanstack/react-query" -import { Route, triggersFromRuns, WorkflowsCard, RecentRunsCard } from "./repositories.$owner.$repo.js" +import { Route, triggersFromRuns, WorkflowsCard, RecentRunsCard, RunnersCard } from "./repositories.$owner.$repo.js" // ── Test helpers ─────────────────────────────────────────────────────────────── @@ -109,6 +110,18 @@ function makeRun(overrides: Partial = {}): WorkflowRun { } } +function makeRunner(overrides: Partial = {}): SelfHostedRunner { + return { + id: ++_id, + name: "runner-1", + os: "linux", + status: "online", + busy: false, + labels: ["self-hosted", "linux"], + ...overrides, + } +} + function makeWorkflow(overrides: Partial = {}): Workflow { const id = ++_id return { @@ -421,3 +434,66 @@ describe("RepositoryDetail page", () => { expect(container.querySelector(".health-repo-label-owner")).not.toBeNull() }) }) + +// ── RunnersCard ─────────────────────────────────────────────────────────────── + +describe("RunnersCard", () => { + it("shows nothing while loading", () => { + mockUseQuery.mockReturnValue({ data: undefined, isLoading: true } as ReturnType) + render() + expect(screen.queryByText("No self-hosted runners configured.")).not.toBeInTheDocument() + }) + + it("shows empty state when runners data is undefined and not loading", () => { + mockUseQuery.mockReturnValue({ data: undefined, isLoading: false } as ReturnType) + render() + expect(screen.getByText("No self-hosted runners configured.")).toBeInTheDocument() + }) + + it("shows empty state when runners array is empty", () => { + mockUseQuery.mockReturnValue({ data: [], isLoading: false } as ReturnType) + render() + expect(screen.getByText("No self-hosted runners configured.")).toBeInTheDocument() + }) + + it("renders a row per runner", () => { + mockUseQuery.mockReturnValue({ data: [makeRunner(), makeRunner({ name: "runner-2" })] } as ReturnType) + const { container } = render() + expect(container.querySelectorAll("tbody tr")).toHaveLength(2) + }) + + it("shows runner name, OS, status, and labels", () => { + mockUseQuery.mockReturnValue({ + data: [makeRunner({ name: "my-runner", os: "linux", status: "online", labels: ["self-hosted", "x64"] })], + } as ReturnType) + render() + expect(screen.getByText("my-runner")).toBeInTheDocument() + expect(screen.getByText("linux")).toBeInTheDocument() + expect(screen.getByText("online")).toBeInTheDocument() + expect(screen.getByText("self-hosted, x64")).toBeInTheDocument() + }) + + it("shows 'busy' indicator when runner is busy", () => { + mockUseQuery.mockReturnValue({ + data: [makeRunner({ status: "online", busy: true })], + } as ReturnType) + render() + expect(screen.getByText("online · busy")).toBeInTheDocument() + }) + + it("shows offline status for offline runner", () => { + mockUseQuery.mockReturnValue({ + data: [makeRunner({ status: "offline", busy: false })], + } as ReturnType) + render() + expect(screen.getByText("offline")).toBeInTheDocument() + }) + + it("shows '—' in labels cell when runner has no labels", () => { + mockUseQuery.mockReturnValue({ + data: [makeRunner({ labels: [] })], + } as ReturnType) + render() + expect(screen.getByText("—")).toBeInTheDocument() + }) +}) diff --git a/packages/web/src/routes/_app/-runs_.$owner.$repo.$runId.test.tsx b/packages/web/src/routes/_app/-runs_.$owner.$repo.$runId.test.tsx index f103e4f..b2f4a73 100644 --- a/packages/web/src/routes/_app/-runs_.$owner.$repo.$runId.test.tsx +++ b/packages/web/src/routes/_app/-runs_.$owner.$repo.$runId.test.tsx @@ -262,11 +262,23 @@ describe("JobsCard", () => { expect(screen.getByText("ubuntu-22.04")).toBeInTheDocument() }) - it("shows '—' when runner is null", () => { - render() + it("shows '—' when runner is null and labels are empty", () => { + render() expect(screen.getByText("—")).toBeInTheDocument() }) + it("shows labels when runnerName is null", () => { + render() + expect(screen.getByText("ubuntu-latest")).toBeInTheDocument() + expect(screen.queryByText("—")).not.toBeInTheDocument() + }) + + it("shows runnerName and labels together", () => { + render() + expect(screen.getByText("runner-1")).toBeInTheDocument() + expect(screen.getByText("(self-hosted, linux)")).toBeInTheDocument() + }) + it("shows job count in card header", () => { render() expect(screen.getByTestId("card-header")).toHaveTextContent("Jobs (3)") diff --git a/packages/web/src/routes/_app/repositories.$owner.$repo.tsx b/packages/web/src/routes/_app/repositories.$owner.$repo.tsx index 98667fa..d0904ee 100644 --- a/packages/web/src/routes/_app/repositories.$owner.$repo.tsx +++ b/packages/web/src/routes/_app/repositories.$owner.$repo.tsx @@ -1,6 +1,6 @@ import { createFileRoute, Link, Outlet, useChildMatches } from "@tanstack/react-router" import { useQuery } from "@tanstack/react-query" -import { getRepo, getRepoScore, getWorkflows, getRuns } from "../../api/index.js" +import { getRepo, getRepoScore, getWorkflows, getRuns, getRepoRunners } from "../../api/index.js" import { StatusBadge, TierBadge } from "../../components/ui/Badge.js" import { Button } from "../../components/ui/Button.js" import { Card, CardHeader } from "../../components/ui/Card.js" @@ -8,7 +8,7 @@ import { PageSpinner } from "../../components/ui/Spinner.js" import { BuildTrendChart, DurationChart } from "../../components/charts/RunCharts.js" import { EventBadge } from "../../components/ui/EventBadge.js" import { formatRelativeTime, formatDuration, formatDateTime } from "../../lib/utils.js" -import type { RepositoryScore, WorkflowRun } from "../../types/index.js" +import type { RepositoryScore, SelfHostedRunner, WorkflowRun } from "../../types/index.js" export const Route = createFileRoute("/_app/repositories/$owner/$repo")({ component: RepositoryDetail, @@ -55,6 +55,7 @@ function RepositoryDetail() {
+
@@ -242,6 +243,56 @@ function BuildChartsCard({ owner, repo }: { owner: string; repo: string }) { ) } +export function RunnersCard({ owner, repo }: { owner: string; repo: string }) { + const { data: runners, isLoading } = useQuery({ + queryKey: ["runners", owner, repo], + queryFn: () => getRepoRunners(owner, repo), + staleTime: 5 * 60 * 1000, + }) + + return ( + + + {isLoading ? null : !runners || runners.length === 0 ? ( +

No self-hosted runners configured.

+ ) : ( + + )} +
+ ) +} + +function RunnersTable({ runners }: { runners: SelfHostedRunner[] }) { + return ( +
+ + + + + + + + + + + {runners.map((r) => ( + + + + + + + ))} + +
NameOSStatusLabels
{r.name}{r.os} + + {r.status}{r.busy ? " · busy" : ""} + + {r.labels.length > 0 ? r.labels.join(", ") : "—"}
+
+ ) +} + export function RecentRunsCard({ owner, repo }: { owner: string; repo: string }) { const { data: runsData } = useQuery({ queryKey: ["runs", `${owner}/${repo}`, "recent"], diff --git a/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx b/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx index b6c735a..07fdb68 100644 --- a/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx +++ b/packages/web/src/routes/_app/runs_.$owner.$repo.$runId.tsx @@ -280,7 +280,18 @@ export function JobsCard({ {job.steps.filter((s) => s.conclusion === "success").length} / {job.steps.length}
{formatDuration(job.startedAt, job.completedAt)}{job.runnerName ?? "—"} + {job.runnerName + ? <> + {job.runnerName} + {job.labels.length > 0 && ( + ({job.labels.join(", ")}) + )} + + : job.labels.length > 0 + ? {job.labels.join(", ")} + : "—"} +