diff --git a/.gitignore b/.gitignore index 5f09bf8..830dd2c 100644 --- a/.gitignore +++ b/.gitignore @@ -193,6 +193,7 @@ ClientBin/ *.pfx *.publishsettings node_modules/ +dist/ orleans.codegen.cs .directory @@ -262,5 +263,3 @@ __pycache__/ *.pyc -**/*docker-compose/LetsEncryptServer/acme -**/*docker-compose/LetsEncryptServer/cache \ No newline at end of file diff --git a/README.md b/README.md index 6a6ad13..1231af7 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,212 @@ -# LetsEncrypt C# Client by MaksIT +# MaksIT.CertsUI - Container-based Let's Encrypt ACME client with WebUI + +Powerful client to obtain and manage Let's Encrypt HTTPS certificates. +This client currently supports the HTTP-01 challenge and is designed to follow the official [Let's Encrypt requirements and guidelines](https://letsencrypt.org/docs/), implementing the ACME protocol and adhering to recommended security and operational practices. + + +If you find this project useful, please consider supporting its development: + +[Buy Me A Coffee](https://www.buymeacoffee.com/maksitcom) + + +--- + +## Table of Contents + +- [MaksIT.CertsUI - Container-based Let's Encrypt ACME client with WebUI](#maksitcertsui---container-based-lets-encrypt-acme-client-with-webui) + - [Table of Contents](#table-of-contents) + - [Versions History](#versions-history) + - [Architecture](#architecture) + - [Current Limitations](#current-limitations) + - [Architecture Scheme](#architecture-scheme) + - [Architecture Description](#architecture-description) + - [MaksIT.CertsUI Agent](#maksitcertsui-agent) + - [MaksIT.CertsUI WebUI](#maksitcertsui-webui) + - [MaksIT.CertsUI WebAPI](#maksitcertsui-webapi) + - [Flow Overview](#flow-overview) + - [HAProxy configuration](#haproxy-configuration) + - [Explanation](#explanation) + - [MaksIT.CertsUI Agent installation](#maksitcertsui-agent-installation) + - [MaksIT.CertsUI Server Installation on Linux with Podman Compose](#maksitcertsui-server-installation-on-linux-with-podman-compose) + - [Prerequisites](#prerequisites) + - [Running the Project with Podman Compose](#running-the-project-with-podman-compose) + - [MaksIT.CertsUI Server Installation on Windows with Docker Compose](#maksitcertsui-server-installation-on-windows-with-docker-compose) + - [Prerequisites](#prerequisites-1) + - [Secrets and Configuration](#secrets-and-configuration) + - [Running the Project with Docker Compose](#running-the-project-with-docker-compose) + - [MaksIT.CertsUI Server installation on Kubernetes](#maksitcertsui-server-installation-on-kubernetes) + - [1. Add MaksIT Helm Repository](#1-add-maksit-helm-repository) + - [2. Prepare Namespace, Secrets, and ConfigMap](#2-prepare-namespace-secrets-and-configmap) + - [3. Create a Minimal Custom Values File](#3-create-a-minimal-custom-values-file) + - [4. Install the Helm Chart](#4-install-the-helm-chart) + - [MaksIT.CertsUI Interface Overview](#maksitcertsui-interface-overview) + - [Contact](#contact) -Simple client to obtain Let's Encrypt HTTPS certificates developed with .net core and currently works only with http challenge ## Versions History -* 29 Jun, 2019 - V1.0 -* 01 Nov, 2019 - V2.0 (Dependency Injection pattern implementation) -* 31 May, 2024 - V3.0 (Webapi and containerization) -* 11 Aug, 2024 - V3.1 (Release) -* 11 Sep, 2025 - V3.2 New WebUI with authentication -* 15 Nov, 2025 - V3.3 Pre release -* -## Haproxy configuration +* 29 Jun, 2019 - V1.0.0 +* 01 Nov, 2019 - V2.0.0 (Dependency Injection pattern implementation) +* 31 May, 2024 - V3.0.0 (Webapi and containerization) +* 11 Aug, 2024 - V3.1.0 (Release) +* 11 Sep, 2025 - V3.2.0 New WebUI with authentication +* 15 Nov, 2025 - V3.3.0 Pre release + + +--- + +## Architecture + +This solution provides automated, secure management of Let's Encrypt certificates for environments where the edge proxy is behind NAT and certificate management logic runs in a Docker/Podman compose or Kubernetes cluster. + + +### Current Limitations + + +- **Single Agent Support:** + The current implementation supports only a single MaksIT.CertsUI Agent instance. High-availability (HA) or multi-agent deployments are not supported at this time. (Multi-agent/HA support may be added in future releases.) + +- **No HA Mode:** + There is no built-in high-availability mode for the WebAPI or Agent components. This is by design, as the solution targets environments where a single edge proxy and agent are sufficient, and additional complexity is unnecessary. + +- **HTTP-01 Challenge Only:** + Only the HTTP-01 ACME challenge type is supported. DNS-01 and other challenge types are not implemented. + +- **Single Kubernetes Replica:** + The solution is intended for use with a single Kubernetes replica for the MaksIT.CertsUI server and MaksIT.WebUI components. + +These limitations are intentional to keep the architecture simple and reliable for typical edge proxy scenarios. Future releases may introduce additional features based on user demand. + +### Architecture Scheme + +``` + Edge Proxy (NAT) Kubernetes Cluster (Internal Network) + +-----------------------+ +----------------------------------------------------+ + | | HTTP | +-----------------------+ +----------------+ | ++-------------------+ | Reverse Proxy-----|--------|->| | | | | +| | ACME | (HAProxy/Nginx) | | | MaksIT.CertsUI Server |<--->| MaksIT.WebUI | | +| Let's Encrypt |<------>| | HTTP | | (ACME logic) | | (Management) | | +| (Internet) | HTTP | MaksIT.CertsUI Agent<-|--------|--| | | | | +| | | (Edge WebAPI, | | +-----------------------+ +----------------+ | ++-------------------+ | next to HAProxy) | +----------------------------------------------------+ + | | + +-----------------------+ + | + | + v + +-----------------------+ + | | + | Application(s) | + | | + +-----------------------+ +``` + +### Architecture Description + + +#### MaksIT.CertsUI Agent + +The **MaksIT.CertsUI Agent** is a lightweight service responsible for **receiving cached certificates** from the **MaksIT.CertsUI** server and **deploying them to the local file system** used by your reverse proxy (e.g., **HAProxy** or **Nginx**). It also handles **proxy service reloads** to activate new certificates. + + +**Language Independence:** +A standard **C# WebAPI implementation** of the Agent is available in this repository for immediate use or customization. However, the Agent is fully independent from the MaksIT.CertsUI server and communicates via standard **HTTP APIs**. This means you can implement the Agent in **any programming language or framework** that supports HTTP endpoints (such as **C#**, **Go**, **Python**, **Rust**, **Node.js**, etc.). The only requirements are: + +- Ability to **receive certificate files via HTTP** +- Ability to **write files** to the proxy’s certificate directory +- Ability to **reload or restart** the proxy process + + +**Security:** +Communication between the Agent and the **MaksIT.CertsUI** server is secured using a **shared API key**. This ensures that only authorized servers can deploy certificates and trigger proxy reloads, protecting your edge infrastructure from unauthorized access. + +> **Warning:** Never commit secrets or API keys to version control. Always use strong, unique secrets and passwords. + +This flexibility allows you to integrate the Agent into diverse environments and choose the best technology stack for your edge server. + +#### MaksIT.CertsUI WebUI + +The **MaksIT.CertsUI WebUI** is a user-friendly web interface designed to simplify the management of Let's Encrypt certificates within your infrastructure. With the WebUI, administrators can easily view, import, and export the certificate cache, streamlining certificate operations without the need for direct command-line interaction. + +**Key Features:** + +- **Certificate Management Dashboard:** + Provides a clear overview of all managed certificates, their status, and expiration dates. + +- **Import/Export Certificate Cache:** + Easily back up or restore your certificate cache. This feature allows you to move certificates between environments or recover from failures without reissuing certificates from Let's Encrypt. + +- **Redeploy Cached Certificates:** + Instantly redeploy existing (cached) certificates to your edge agents or proxies. This avoids unnecessary requests to Let's Encrypt, reducing rate limit concerns and ensuring rapid recovery or migration. + +- **No Need for Reissuance:** + By leveraging the cache import/export and redeploy features, you can restore or migrate certificates without triggering new ACME challenges or consuming additional Let's Encrypt issuance quotas. + +- **Secure Access:** + The WebUI is accessible only via username and password authentication, ensuring that only authorized users can manage certificates. + +The WebUI is designed for operational efficiency and security, making certificate lifecycle management straightforward for both small and large deployments. + + +#### MaksIT.CertsUI WebAPI + +The **MaksIT.CertsUI Webapi** is the core backend service responsible for orchestrating all certificate management operations in the MaksIT.CertsUI solution. It implements the ACME protocol to interact with Let's Encrypt, handles HTTP-01 challenges, manages the certificate cache, and coordinates certificate deployment to edge agents. + +**Main Responsibilities:** + +- **ACME Protocol Handling:** + Communicates with Let's Encrypt to request, renew, and revoke certificates using the official ACME protocol. + +- **Challenge Management:** + Receives and responds to HTTP-01 challenge requests, enabling domain validation even when the edge proxy is behind NAT. + +- **Certificate Cache Management:** + Stores issued certificates securely and provides endpoints for importing, exporting, and redeploying cached certificates. + +- **Agent Coordination:** + Sends certificates to edge agents (such as the MaksIT.CertsUI Agent) and instructs them to reload or restart the proxy service to activate new certificates. + +- **API Security:** + All API endpoints are protected by authentication mechanisms (such as API keys), ensuring that only authorized agents and users can perform sensitive operations. + +- **Integration with WebUI:** + Serves as the backend for the MaksIT.CertsUI WebUI, enabling administrators to manage certificates through a secure and intuitive web interface. + +The Webapi is designed for deployment in secure environments such as Kubernetes clusters, centralizing certificate management while keeping HTTPS termination and certificate storage at the network edge. + +#### Flow Overview + +1. **ACME Challenge Routing:** + - The Edge Proxy (HAProxy/Nginx), running behind NAT, listens for HTTP requests on port80. + - Requests to `/.well-known/acme-challenge/` are forwarded via HTTP to the LetsEncrypt Client running in the Kubernetes cluster. + +2. **LetsEncrypt Client (Kubernetes):** + - Handles ACME challenge requests, responds to Let's Encrypt for domain validation, and manages certificate issuance. + - The Web UI provides management for certificate operations. + +3. **Certificate Deployment:** + - After successful validation and certificate issuance, the LetsEncrypt Client sends the new certificates to the Agent (Edge WebAPI) running on the same machine as the Edge Proxy. + - The Agent stores the certificates in the directory used by the proxy (e.g., `/etc/haproxy/certs`). + +4. **Proxy Reload:** + - The LetsEncrypt Client instructs the Agent to reload or restart the Edge Proxy, ensuring the new certificates are used for HTTPS traffic. + +5. **HTTPS Serving:** + - The Edge Proxy serves HTTPS traffic to backend applications using the updated certificates. + + +**Key Points:** +- The Edge Proxy and Agent are deployed together on the edge server, while the LetsEncrypt Client and Web UI run in Kubernetes. +- All ACME challenge and certificate management logic is centralized in Kubernetes, while certificate storage and HTTPS termination remain at the edge. +- This architecture supports secure automation even when the edge server is not directly accessible from the public internet. + + +> **Note:** Currently, only HTTP-01 challenges and a single Kubernetes replica are supported by this solution. + + +--- + +## HAProxy configuration ```bash sudo mkdir /etc/haproxy/certs @@ -21,7 +216,7 @@ sudo mkdir /etc/haproxy/certs sudo nano /etc/haproxy/haproxy.cfg ``` -```ini +```cfg #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- @@ -76,7 +271,7 @@ frontend http_frontend # Backend to handle ACME challenge requests #--------------------------------------------------------------------- backend acme_backend - server local_acme 127.0.0.1:8080 + #server local_acme 172.16.0.5:8080 #--------------------------------------------------------------------- # Frontend for HTTPS traffic (port 443) with SNI and strict-sni @@ -87,55 +282,36 @@ frontend https_frontend http-request capture req.hdr(host) len 64 # Define ACLs for routing based on hostname - acl host_git hdr(host) -i git.maks-it.com - acl host_cr hdr(host) -i cr.maks-it.com + acl host_homepage hdr(host) -i maks-it.com # Use appropriate backend based on SNI hostname - use_backend git_backend if host_git - use_backend cr_backend if host_cr + use_backend homepage_backend if host_homepage + + default_backend homepage_backend #--------------------------------------------------------------------- -# Backend for git.maks-it.com +# Backend for maks-it.com #--------------------------------------------------------------------- -backend git_backend +backend homepage_backend http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-Host %[hdr(host)] - server git_server gitsrv0002.corp.maks-it.com:3000 - -#--------------------------------------------------------------------- -# Backend for cr.maks-it.com -#--------------------------------------------------------------------- -backend cr_backend - http-request set-header X-Forwarded-Proto https - http-request set-header X-Forwarded-Host %[hdr(host)] - server cr_server hcrsrv0001.corp.maks-it.com:80 - -#--------------------------------------------------------------------- -# letsencrypt load balancer -#--------------------------------------------------------------------- -frontend letsencrypt - bind *:8080 - mode http - acl path_well_known_acme path_beg /.well-known/acme-challenge/ - acl path_swagger path_beg /swagger/ - acl path_api path_beg /api/ - - use_backend letsencrypt_server if path_well_known_acme - use_backend letsencrypt_server if path_swagger - use_backend letsencrypt_server if path_api - default_backend letsencrypt_app - -backend letsencrypt_server - mode http - server server1 127.0.0.1:9000 check - -backend letsencrypt_app - mode http - server app1 127.0.0.1:3000 check - + server homepage_server 172.16.0.10:8080 ``` -## MaksIT agent installation +### Explanation +* ACME Challenge Handling: +The http_frontend listens on port 80 and checks if the request path starts with /.well-known/acme-challenge/. These requests are required by Let's Encrypt for domain validation and are forwarded to the acme_backend. All other HTTP requests are redirected to HTTPS. +* HTTPS Frontend: +The https_frontend listens on port 443, uses SNI (Server Name Indication) to serve the correct certificate, and routes requests to the appropriate backend based on the hostname. +* Backends: + * acme_backend should point to your ACME challenge responder (such as your LetsEncrypt client). + * homepage_backend is an example backend for your main site, forwarding requests to your application server. +* Certificate Storage: +Place your SSL certificates in /etc/haproxy/certs. Each certificate file should contain the full certificate chain and private key. + +## MaksIT.CertsUI Agent installation + +Agent should be installed on same machine with your reverse proxy. From your home directory @@ -147,23 +323,613 @@ git clone https://github.com/MAKS-IT-COM/certs-ui.git cd certs-ui/src/Agent ``` +Edit `appsettings.json` configuration: + +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + + "Configuration": { + "ApiKey": "", + "CertsPath": "" + } +} +``` + + +**Note:** +Replace `` with your shared API key and `` with the path to your certificates directory (e.g., `/etc/haproxy/certs` as referenced in `haproxy.cfg`). +> **Warning:** Never commit secrets or API keys to version control. Always use strong, unique secrets and passwords. + +If you are using a **RHEL-based** distribution, you can deploy the agent with: + ```bash sudo sh ./build_and_deploy.sh ``` +This script will create the `maks-it-agent` service and open port `5000` for communication. -## Maks IT LetsEncrypt server installation -From your home directory +--- + +## MaksIT.CertsUI Server Installation on Linux with Podman Compose + +Podman Compose usage to orchestrate multiple **MaksIT.CertsUI** services on Linux. + +### Prerequisites + +- [Podman](https://podman.io/getting-started/installation) +- Create these folders: + - `/opt/Compose/MaksIT.CertsUI/acme` + - `/opt/Compose/MaksIT.CertsUI/cache` + - `/opt/Compose/MaksIT.CertsUI/data` + - `/opt/Compose/MaksIT.CertsUI/tmp` + - `/opt/Compose/MaksIT.CertsUI/configMap` + - `/opt/Compose/MaksIT.CertsUI/secrets` + - `/opt/Compose/MaksIT.CertsUI/client` + +Bash command to use: ```bash -git clone https://github.com/MAKS-IT-COM/certs-ui.git +mkdir -p /opt/Compose/MaksIT.CertsUI/acme \ + /opt/Compose/MaksIT.CertsUI/cache \ + /opt/Compose/MaksIT.CertsUI/data \ + /opt/Compose/MaksIT.CertsUI/tmp \ + /opt/Compose/MaksIT.CertsUI/configMap \ + /opt/Compose/MaksIT.CertsUI/secrets \ + /opt/Compose/MaksIT.CertsUI/client +``` + +Create the following files in the appropriate folders: + +**1. Create the file `/opt/Compose/MaksIT.CertsUI/secrets/appsecrets.json` with this command:** + +```bash +cat > /opt/Compose/MaksIT.CertsUI/secrets/appsecrets.json <", + "Pepper": "" + }, + "Agent": { + "AgentKey": "" + } + } +} +EOF +``` + +**Note:** +Replace placeholder values ``, ``, ``, with secure, your environment-specific values. +Make sure `` matches the key configured in your agent deployment. + +**2. Create the file `/opt/Compose/MaksIT.CertsUI/configMap/appsettings.json` with this command:** + +```bash +cat > /opt/Compose/MaksIT.CertsUI/configMap/appsettings.json <", + "Audience": "", + "Expiration": 15, + "RefreshExpiration": 180 + }, + "Agent": { + "AgentHostname": "http://", + "AgentPort": 5000, + "ServiceToReload": "haproxy" + }, + "Production": "https://acme-v02.api.letsencrypt.org/directory", + "Staging": "https://acme-staging-v02.api.letsencrypt.org/directory", + "CacheFolder": "/cache", + "AcmeFolder": "/acme", + "DataFolder": "/data", + "SettingsFile": "/data/settings.json" + } +} +EOF +``` + +**Note:** +Replace all JWT-related placeholder values ``, `` and `` with your environment-specific values. + +**3. Create the file `/opt/Compose/MaksIT.CertsUI/client/config.js` with this command:** + +```bash +cat > /opt/Compose/MaksIT.CertsUI/configMap/appsettings.json </api" +}; +EOF +``` + +**Note:** + - Replace placeholder value `` to tell the client where **MaksIT.CertsUI** server is running + +### Running the Project with Podman Compose + +In the project root (`/opt/Compose/MaksIT.CertsUI`), create a new file named `docker-compose.yml` with the following content: + +```yaml +services: + reverse-proxy: + image: cr.maks-it.com/certs-ui/reverseproxy:latest + container_name: reverse-proxy + ports: + - "8080:8080" + depends_on: + - certs-ui-client + - certs-ui-server + networks: + - certs-ui-network + + certs-ui-client: + image: cr.maks-it.com/certs-ui/client:latest + container_name: certs-ui-client + volumes: + - /opt/Compose/MaksIT.CertsUI/client/config.js:/app/dist/config.js:ro + networks: + - certs-ui-network + + certs-ui-server: + image: cr.maks-it.com/certs-ui/server:latest + container_name: certs-ui-server + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_HTTP_PORTS=5000 + volumes: + - /opt/Compose/MaksIT.CertsUI/acme:/acme + - /opt/Compose/MaksIT.CertsUI/cache:/cache + - /opt/Compose/MaksIT.CertsUI/data:/data + - /opt/Compose/MaksIT.CertsUI/tmp:/tmp + - /opt/Compose/MaksIT.CertsUI/configMap/appsettings.json:/configMap/appsettings.json:ro + - /opt/Compose/MaksIT.CertsUI/secrets/appsecrets.json:/secrets/appsecrets.json:ro + networks: + - certs-ui-network + +networks: + certs-ui-network: + driver: bridge +``` + +**Note:** + - Adjust volume paths if changed + +```bash +podman compose -f docker-compose.yml up --build +``` + +This command builds and starts the following services: +- **reverse-proxy**: Exposes both `certs-ui-client` and `certs-ui-server` on the same hostname. +- **certs-ui-client**: The WebUI for managing certificates. +- **certs-ui-server**: The backend server handling ACME logic and certificate management. + +**Stop the services:** + +Press `Ctrl+C` in the terminal, then run: + +```bash +podman compose -f docker-compose.yml down +``` + + +--- + +## MaksIT.CertsUI Server Installation on Windows with Docker Compose + +Use Docker Compose to orchestrate multiple **MaksIT.CertsUI** services on Windows. + +### Prerequisites + +- [Docker Desktop](https://www.docker.com/products/docker-desktop/) (includes Docker Compose) +- Create these folders: + - `C:\Compose\MaksIT.CertsUI\acme` + - `C:\Compose\MaksIT.CertsUI\cache` + - `C:\Compose\MaksIT.CertsUI\data` + - `C:\Compose\MaksIT.CertsUI\tmp` + - `C:\Compose\MaksIT.CertsUI\configMap` + - `C:\Compose\MaksIT.CertsUI\secrets` + +Powershell command to use: + +```powershell +New-Item -Path ` + 'C:\Compose\MaksIT.CertsUI\acme', ` + 'C:\Compose\MaksIT.CertsUI\cache', ` + 'C:\Compose\MaksIT.CertsUI\data', ` + 'C:\Compose\MaksIT.CertsUI\tmp', ` + 'C:\Compose\MaksIT.CertsUI\configMap', ` + 'C:\Compose\MaksIT.CertsUI\secrets' ` + -ItemType Directory -Force +``` + +### Secrets and Configuration + +Create the following files in the appropriate folders: + +**1. Create the file `C:\Compose\MaksIT.CertsUI\secrets\appsecrets.json` with this command:** + +```powershell +Set-Content -Path 'C:\Compose\MaksIT.CertsUI\secrets\appsecrets.json' -Value @' +{ + "Configuration": { + "Auth": { + "Secret": "", + "Pepper": "" + }, + "Agent": { + "AgentKey": "" + } + } +} +'@ +``` + +**Note:** +Replace placeholder values ``, ``, ``, with secure, your environment-specific values. +Make sure `` matches the key configured in your agent deployment. + +**2. Create the file `C:\Compose\MaksIT.CertsUI\configMap\appsettings.json` with this command:** + +```powershell +Set-Content -Path 'C:\Compose\MaksIT.CertsUI\configMap\appsettings.json' -Value @' +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "Configuration": { + "Auth": { + "Issuer": "", + "Audience": "", + "Expiration": 15, + "RefreshExpiration": 180 + }, + "Agent": { + "AgentHostname": "http://", + "AgentPort": 5000, + "ServiceToReload": "haproxy" + }, + "Production": "https://acme-v02.api.letsencrypt.org/directory", + "Staging": "https://acme-staging-v02.api.letsencrypt.org/directory", + "CacheFolder": "/cache", + "AcmeFolder": "/acme", + "DataFolder": "/data", + "SettingsFile": "/data/settings.json" + } +} +'@ +``` + +**Note:** +Replace all JWT-related placeholder values ``, `` and `` with your environment-specific values. + +**3. Create the file `C:\Compose\MaksIT.CertsUI\client\config.js` with this command:** + +```powershell +Set-Content -Path 'C:\Compose\MaksIT.CertsUI\client\config.js' -Value @' +window.RUNTIME_CONFIG = { + API_URL: "http://:8080/api" +}; +'@ +``` + +**Note:** + - Replace placeholder value `` to tell the client where **MaksIT.CertsUI** server is running + +### Running the Project with Docker Compose + +In the project root (`C:\Compose\MaksIT.CertsUI`), create a new file named `docker-compose.yml` with the following content: + +```powershell +Set-Content -Path 'C:\Compose\MaksIT.CertsUI\docker-compose.yml' -Value @' +services: + reverse-proxy: + image: cr.maks-it.com/certs-ui/reverseproxy:latest + container_name: reverse-proxy + ports: + - "8080:8080" + depends_on: + - certs-ui-client + - certs-ui-server + networks: + - certs-ui-network + + certs-ui-client: + image: cr.maks-it.com/certs-ui/client:latest + container_name: certs-ui-client + volumes: + - C:\Compose\MaksIT.CertsUI\client\config.js:/app/dist/config.js:ro + networks: + - certs-ui-network + + certs-ui-server: + image: cr.maks-it.com/certs-ui/server:latest + container_name: certs-ui-server + environment: + - ASPNETCORE_ENVIRONMENT=Production + - ASPNETCORE_HTTP_PORTS=5000 + volumes: + - C:\Compose\MaksIT.CertsUI\acme:/acme + - C:\Compose\MaksIT.CertsUI\cache:/cache + - C:\Compose\MaksIT.CertsUI\data:/data + - C:\Compose\MaksIT.CertsUI\tmp:/tmp + - C:\Compose\MaksIT.CertsUI\configMap\appsettings.json:/configMap/appsettings.json:ro + - C:\Compose\MaksIT.CertsUI\secrets\appsecrets.json:/secrets/appsecrets.json:ro + networks: + - certs-ui-network + +networks: + certs-ui-network: + driver: bridge +'@ +``` + +**Note:** + - Adjust volume paths if changed + +```powershell +docker compose -f docker-compose.yml up --build +``` + +This command builds and starts the following services: +- **reverse-proxy**: Exposes both `certs-ui-client` and `certs-ui-server` on the same hostname. +- **certs-ui-client**: The WebUI for managing certificates. +- **certs-ui-server**: The backend server handling ACME logic and certificate management. + +**Stop the services:** + +Press `Ctrl+C` in the terminal, then run: + +```powershell +docker compose -f docker-compose.yml down +``` + + + + +--- + +## MaksIT.CertsUI Server installation on Kubernetes + +### 1. Add MaksIT Helm Repository + +The MaksIT.CertsUI Helm chart is available from the MaksIT container registry. Add the MaksIT Helm repository to your Helm client: + +```bash +helm repo add maksit https://cr.maks-it.com/chartrepo/charts +helm repo update +``` + +### 2. Prepare Namespace, Secrets, and ConfigMap + +Before installing the Helm chart, create a dedicated namespace and provide the required secrets and configuration for the MaksIT.CertsUI Webapi. + +**Step 1: Create Namespace** + +```bash +kubectl create namespace certs-ui +``` + +**Step 2: Create the Secret (`appsecrets.json`)** + +Replace the placeholder values with your actual secrets. This secret contains authentication and agent keys required by the Webapi. + +```json +{ + "Auth": { + "Secret": "", + "Pepper": "" +}, + "Agent": { + "AgentKey": "" + } +} ``` ```bash -cd certs-ui/src +kubectl create secret generic certs-ui-server-secrets \ + --from-literal=appsecrets.json='{ + "Auth": { + "Secret": "", + "Pepper": "" + }, + "Agent": { + "AgentKey": "" + } + }' \ + -n certs-ui +``` + +**Note:** +Replace placeholder values ``, ``, ``, with secure, your environment-specific values. +Make sure `` matches the key configured in your agent deployment. + +**Step 3: Create the ConfigMap (`appsettings.json`)** + +Edit the values as needed for your environment. This configmap contains application settings for logging, authentication, agent configuration, and ACME endpoints. + +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } +}, + "Configuration": { + "Auth": { + "Issuer": "", + "Audience": "", + "Expiration": 15, + "RefreshExpiration": 180 + }, + "Agent": { + "AgentHostname": "http://", + "AgentPort": 5000, + "ServiceToReload": "haproxy" + }, + "Production": "https://acme-v02.api.letsencrypt.org/directory", + "Staging": "https://acme-staging-v02.api.letsencrypt.org/directory", + "CacheFolder": "/cache", + "AcmeFolder": "/acme", + "DataFolder": "/data", + "SettingsFile": "/data/settings.json" + } +} ``` ```bash -podman-compose -f docker-compose.final.yml up +kubectl create configmap certs-ui-server-configmap \ + --from-literal=appsettings.json='{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "Configuration": { + "Auth": { + "Issuer": "", + "Audience": "", + "Expiration": 15, + "RefreshExpiration": 180 + }, + "Agent": { + "AgentHostname": "http://", + "AgentPort": 5000, + "ServiceToReload": "haproxy" + }, + "Production": "https://acme-v02.api.letsencrypt.org/directory", + "Staging": "https://acme-staging-v02.api.letsencrypt.org/directory", + "CacheFolder": "/cache", + "AcmeFolder": "/acme", + "DataFolder": "/data", + "SettingsFile": "/data/settings.json" + } + }' \ + -n certs-ui ``` + +**Note:** +Replace all JWT-related placeholder values ``, `` and `` with your environment-specific values. + +### 3. Create a Minimal Custom Values File + +Below is a minimal example of a `custom-values.yaml` for most users. It disables image pull secrets by default (since the chart and images are public), sets the storage class for persistent volumes, and configures the reverse proxy service. You can further customize this file as needed for your environment. + +```yaml +global: + imagePullSecrets: [] # Keep empty + +components: + server: + persistence: + storageClass: local-path + + reverseproxy: + service: + type: LoadBalancer + port: 8080 + targetPort: 8080 + # Remove or comment out the next two lines to let your cloud provider assign a dynamic IP + # loadBalancerIP: "172.16.0.5" + # annotations: + # lbipam.cilium.io/ips: "172.16.0.5" + externalTrafficPolicy: Local + sessionAffinity: ClientIP + sessionAffinityConfig: + clientIP: + timeoutSeconds: 10800 +``` + +### 4. Install the Helm Chart + +Install the MaksIT.CertsUI chart using your custom values file: + +```bash +helm install certs-ui maksit/certs-ui -n certs-ui -f custom-values.yaml +``` + + + + + + +--- + +## MaksIT.CertsUI Interface Overview + +The **MaksIT.CertsUI** interface provides a user-friendly web dashboard for managing Let's Encrypt certificates in your environment. Below is a step-by-step guide to getting started with the WebUI: + + +1. **First Login:** + Open the client in your browser. + **Default credentials:** + - Username: `admin` + - Password: `password` + > **Important:** Change the default password immediately after logging in for the first time for security. + + ![LoginScreen](/assets/chrome_IvvCTtYcbi.png) + +2. **Change the Default Password:** + Click on the **admin** username in the top right corner and select **Edit User**. + + ![LogoutOfcanvas](/assets/chrome_KJw6epn11q.png) + + Go to **Change password**. + + ![ChangePassword](/assets/chrome_YYr4z77ROv.png) + + Enter a strong, alphanumeric password with special characters. + + ![InsertNewPassword](/assets/chrome_hTAVSZW6fb.png) + +3. **Verify Agent Connectivity:** + Before registering certificates, ensure the agent is properly configured and available. + Go to **Utilities** and click **Test agent**. If everything is set up correctly, a "Hello World!" toast notification will appear. + + ![Utilities](/assets/chrome_j5MltyeUfB.png) + +4. **Register a New Account:** + Proceed to register a new account and fill in the required fields. + *Tip: Start with a few hostnames and gradually add 3 or 4 at a time.* + + ![Register](/assets/chrome_vPdHf2afpO.png) + +5. **View and Manage Certificates:** + If registration is successful, your new account will be created and you will see a list of obtained certificates along with their expiration dates. + + ![Home](/assets/chrome_ydyMattQYU.png) + +The WebUI streamlines certificate management, making it easy to change credentials, verify agent status, and monitor certificate lifecycles. + + +--- + +## Contact + +For any inquiries or contributions, feel free to reach out: + +- **Email**: maksym.sadovnychyy@gmail.com +- **Author**: Maksym Sadovnychyy (MAKS-IT) + +--- + +> **Tip:** For the latest updates, documentation, and source code, visit the [GitHub repository](https://github.com/MAKS-IT-COM/certs-ui). \ No newline at end of file diff --git a/assets/chrome_IvvCTtYcbi.png b/assets/chrome_IvvCTtYcbi.png new file mode 100644 index 0000000..5a03640 Binary files /dev/null and b/assets/chrome_IvvCTtYcbi.png differ diff --git a/assets/chrome_KJw6epn11q.png b/assets/chrome_KJw6epn11q.png new file mode 100644 index 0000000..26cde82 Binary files /dev/null and b/assets/chrome_KJw6epn11q.png differ diff --git a/assets/chrome_RPsKiPwaDC.png b/assets/chrome_RPsKiPwaDC.png new file mode 100644 index 0000000..020bc6a Binary files /dev/null and b/assets/chrome_RPsKiPwaDC.png differ diff --git a/assets/chrome_YYr4z77ROv.png b/assets/chrome_YYr4z77ROv.png new file mode 100644 index 0000000..69f01bd Binary files /dev/null and b/assets/chrome_YYr4z77ROv.png differ diff --git a/assets/chrome_hTAVSZW6fb.png b/assets/chrome_hTAVSZW6fb.png new file mode 100644 index 0000000..5a83200 Binary files /dev/null and b/assets/chrome_hTAVSZW6fb.png differ diff --git a/assets/chrome_j5MltyeUfB.png b/assets/chrome_j5MltyeUfB.png new file mode 100644 index 0000000..bcf5e84 Binary files /dev/null and b/assets/chrome_j5MltyeUfB.png differ diff --git a/assets/chrome_vPdHf2afpO.png b/assets/chrome_vPdHf2afpO.png new file mode 100644 index 0000000..92abd92 Binary files /dev/null and b/assets/chrome_vPdHf2afpO.png differ diff --git a/assets/chrome_ydyMattQYU.png b/assets/chrome_ydyMattQYU.png new file mode 100644 index 0000000..45b7d30 Binary files /dev/null and b/assets/chrome_ydyMattQYU.png differ diff --git a/src/Agent/Agent.csproj b/src/Agent/Agent.csproj index fc9e032..66c1346 100644 --- a/src/Agent/Agent.csproj +++ b/src/Agent/Agent.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Deploy-Helm.bat b/src/Deploy-Helm.bat index 40d54a5..6b5e5e2 100644 --- a/src/Deploy-Helm.bat +++ b/src/Deploy-Helm.bat @@ -5,3 +5,5 @@ cd /d %~dp0 REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory powershell -ExecutionPolicy Bypass -File "%~dp0Deploy-Helm.ps1" + +pause \ No newline at end of file diff --git a/src/Deploy-Helm.ps1 b/src/Deploy-Helm.ps1 index 0b2e12e..1a36a4c 100644 --- a/src/Deploy-Helm.ps1 +++ b/src/Deploy-Helm.ps1 @@ -3,7 +3,6 @@ $projectName = "certs-ui" $namespace = "certs-ui" $chartPath = "./helm" $harborUrl = "cr.maks-it.com" -$loadBalancerIP = "172.16.0.5" # Retrieve and decode username:password from environment variable (Base64) try { diff --git a/src/LetsEncrypt.sln b/src/LetsEncrypt.sln index 45d0838..082a818 100644 --- a/src/LetsEncrypt.sln +++ b/src/LetsEncrypt.sln @@ -13,7 +13,7 @@ Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-co EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent", "Agent\Agent.csproj", "{871BDED3-C6AE-437D-9B45-3AA3F184D002}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaksIT.Models", "Models\MaksIT.Models.csproj", "{6814169B-D4D0-40B2-9FA9-89997DD44C30}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaksIT.Models", "MaksIT.Models\MaksIT.Models.csproj", "{6814169B-D4D0-40B2-9FA9-89997DD44C30}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReverseProxy", "ReverseProxy\ReverseProxy.csproj", "{BE051147-7AB7-4358-9C24-5CB40FAFF4FC}" EndProject diff --git a/src/Models/Agent/Requests/CertsUploadRequest.cs b/src/MaksIT.Models/Agent/Requests/CertsUploadRequest.cs similarity index 100% rename from src/Models/Agent/Requests/CertsUploadRequest.cs rename to src/MaksIT.Models/Agent/Requests/CertsUploadRequest.cs diff --git a/src/Models/Agent/Requests/ServiceReloadRequest.cs b/src/MaksIT.Models/Agent/Requests/ServiceReloadRequest.cs similarity index 100% rename from src/Models/Agent/Requests/ServiceReloadRequest.cs rename to src/MaksIT.Models/Agent/Requests/ServiceReloadRequest.cs diff --git a/src/Models/Agent/Responses/HelloWorldResponse.cs b/src/MaksIT.Models/Agent/Responses/HelloWorldResponse.cs similarity index 100% rename from src/Models/Agent/Responses/HelloWorldResponse.cs rename to src/MaksIT.Models/Agent/Responses/HelloWorldResponse.cs diff --git a/src/Models/LetsEncryptServer/Account/Requests/PatchAccountRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Account/Requests/PatchAccountRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Account/Requests/PatchAccountRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Account/Requests/PatchAccountRequest.cs diff --git a/src/Models/LetsEncryptServer/Account/Requests/PatchHostnameRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Account/Requests/PatchHostnameRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Account/Requests/PatchHostnameRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Account/Requests/PatchHostnameRequest.cs diff --git a/src/Models/LetsEncryptServer/Account/Requests/PostAccountRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Account/Requests/PostAccountRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Account/Requests/PostAccountRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Account/Requests/PostAccountRequest.cs diff --git a/src/Models/LetsEncryptServer/Account/Responses/GetAccountResponse.cs b/src/MaksIT.Models/LetsEncryptServer/Account/Responses/GetAccountResponse.cs similarity index 100% rename from src/Models/LetsEncryptServer/Account/Responses/GetAccountResponse.cs rename to src/MaksIT.Models/LetsEncryptServer/Account/Responses/GetAccountResponse.cs diff --git a/src/Models/LetsEncryptServer/Account/Responses/GetHostnameResponse.cs b/src/MaksIT.Models/LetsEncryptServer/Account/Responses/GetHostnameResponse.cs similarity index 100% rename from src/Models/LetsEncryptServer/Account/Responses/GetHostnameResponse.cs rename to src/MaksIT.Models/LetsEncryptServer/Account/Responses/GetHostnameResponse.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/ConfigureClientRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/ConfigureClientRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/ConfigureClientRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/ConfigureClientRequest.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/GetCerificatesRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/GetCerificatesRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/GetCerificatesRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/GetCerificatesRequest.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/GetOrderRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/GetOrderRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/GetOrderRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/GetOrderRequest.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/InitRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/InitRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/InitRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/InitRequest.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/NewOrderRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/NewOrderRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/NewOrderRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/NewOrderRequest.cs diff --git a/src/Models/LetsEncryptServer/CertsFlow/Requests/RevokeCertificatesRequest.cs b/src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/RevokeCertificatesRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/CertsFlow/Requests/RevokeCertificatesRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/CertsFlow/Requests/RevokeCertificatesRequest.cs diff --git a/src/Models/LetsEncryptServer/Identity/Login/LoginRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/Login/LoginRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/Login/LoginRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/Login/LoginRequest.cs diff --git a/src/Models/LetsEncryptServer/Identity/Login/LoginResponse.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/Login/LoginResponse.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/Login/LoginResponse.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/Login/LoginResponse.cs diff --git a/src/Models/LetsEncryptServer/Identity/Login/RefreshTokenRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/Login/RefreshTokenRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/Login/RefreshTokenRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/Login/RefreshTokenRequest.cs diff --git a/src/Models/LetsEncryptServer/Identity/Logout/LogoutRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/Logout/LogoutRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/Logout/LogoutRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/Logout/LogoutRequest.cs diff --git a/src/Models/LetsEncryptServer/Identity/User/PatchUserRequest.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/User/PatchUserRequest.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/User/PatchUserRequest.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/User/PatchUserRequest.cs diff --git a/src/Models/LetsEncryptServer/Identity/User/UserResponse.cs b/src/MaksIT.Models/LetsEncryptServer/Identity/User/UserResponse.cs similarity index 100% rename from src/Models/LetsEncryptServer/Identity/User/UserResponse.cs rename to src/MaksIT.Models/LetsEncryptServer/Identity/User/UserResponse.cs diff --git a/src/Models/MaksIT.Models.csproj b/src/MaksIT.Models/MaksIT.Models.csproj similarity index 100% rename from src/Models/MaksIT.Models.csproj rename to src/MaksIT.Models/MaksIT.Models.csproj diff --git a/src/MaksIT.WebUI/.env.prod b/src/MaksIT.WebUI/.env.prod new file mode 100644 index 0000000..9470eae --- /dev/null +++ b/src/MaksIT.WebUI/.env.prod @@ -0,0 +1,4 @@ +VITE_APP_TITLE=MaksIT.CertsUI +VITE_COMPANY=MaksIT +VITE_COMPANY_URL=https://maks-it.com +VITE_API_URL=http://172.16.0.5:8080/api \ No newline at end of file diff --git a/src/MaksIT.WebUI/Dockerfile.prod b/src/MaksIT.WebUI/Dockerfile.prod index 04b1fa4..1b4b844 100644 --- a/src/MaksIT.WebUI/Dockerfile.prod +++ b/src/MaksIT.WebUI/Dockerfile.prod @@ -1 +1,15 @@ -FROM node:24 \ No newline at end of file +FROM node:24 AS build +WORKDIR /app +COPY ["MaksIT.WebUI/package.json", "MaksIT.WebUI/package-lock.json", "./"] +COPY ["MaksIT.WebUI/.env.prod", "./.env.prod"] +RUN npm ci +COPY ["MaksIT.WebUI/", "./"] +RUN npm run build + +FROM nginx:1.27-alpine AS production +WORKDIR /app +COPY --from=build /app/dist ./dist +COPY ["MaksIT.WebUI/nginx.conf", "/etc/nginx/conf.d/default.conf"] + +EXPOSE 5173 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/src/MaksIT.WebUI/index.html b/src/MaksIT.WebUI/index.html index 8775f6a..928294e 100644 --- a/src/MaksIT.WebUI/index.html +++ b/src/MaksIT.WebUI/index.html @@ -8,6 +8,7 @@
+ diff --git a/src/MaksIT.WebUI/nginx.conf b/src/MaksIT.WebUI/nginx.conf new file mode 100644 index 0000000..eac1cf4 --- /dev/null +++ b/src/MaksIT.WebUI/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 5173; + server_name _; + + root /app/dist; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} \ No newline at end of file diff --git a/src/MaksIT.WebUI/package-lock.json b/src/MaksIT.WebUI/package-lock.json index 4597d2b..f9d72bc 100644 --- a/src/MaksIT.WebUI/package-lock.json +++ b/src/MaksIT.WebUI/package-lock.json @@ -1,65 +1,244 @@ { - "name": "maksit-vault", + "name": "maksit-certs-ui", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "maksit-vault", + "name": "maksit-certs-ui", "version": "0.0.0", "dependencies": { - "@reduxjs/toolkit": "^2.8.2", + "@reduxjs/toolkit": "^2.10.1", "@tanstack/react-table": "^8.21.3", - "axios": "^1.11.0", + "axios": "^1.13.2", "client-zip": "^2.5.0", "date-fns": "^4.1.0", "jwt-decode": "^4.0.0", "lodash": "^4.17.21", - "lucide-react": "^0.536.0", + "lucide-react": "^0.553.0", "qrcode.react": "^4.2.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", + "react": "^19.2.0", + "react-dom": "^19.2.0", "react-pdf": "^10.2.0", "react-redux": "^9.2.0", - "react-router-dom": "^7.7.1", + "react-router-dom": "^7.9.6", "react-virtualized": "^9.22.6", - "uuid": "^11.1.0", - "zod": "^4.0.14" + "uuid": "^13.0.0", + "zod": "^4.1.12" }, "devDependencies": { - "@eslint/js": "^9.32.0", + "@eslint/js": "^9.39.1", "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.10", "@tailwindcss/line-clamp": "^0.4.4", - "@tailwindcss/typography": "^0.5.16", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.1.17", "@types/lodash": "^4.17.20", - "@types/react": "^19.1.9", - "@types/react-dom": "^19.1.7", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", "@types/react-resizable": "^3.0.8", - "@types/react-virtualized": "^9.22.2", - "@vitejs/plugin-react-swc": "^3.11.0", - "eslint": "^9.32.0", + "@types/react-virtualized": "^9.22.3", + "@vitejs/plugin-react-swc": "^4.2.2", + "eslint": "^9.39.1", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "tailwindcss": "^4.1.11", - "typescript": "^5.8.0", - "typescript-eslint": "^8.38.0", - "vite": "^7.0.6" + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.2" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" @@ -74,6 +253,54 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", @@ -500,9 +727,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -542,13 +769,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -557,19 +784,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -617,9 +847,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "dev": true, "license": "MIT", "engines": { @@ -630,9 +860,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -640,13 +870,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", - "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -719,23 +949,10 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -743,6 +960,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -754,16 +982,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -995,14 +1223,14 @@ } }, "node_modules/@reduxjs/toolkit": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz", - "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.10.1.tgz", + "integrity": "sha512-/U17EXQ9Do9Yx4DlNGU6eVNfZvFJfYpUtRRdLf19PbPjdWBxNlxGZXywQZ1p1Nz8nMkWplTI7iD/23m07nolDA==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", - "immer": "^10.0.3", + "immer": "^10.2.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" @@ -1021,16 +1249,16 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz", + "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==", "dev": true, "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", - "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", + "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", "cpu": [ "arm" ], @@ -1042,9 +1270,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", - "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", + "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", "cpu": [ "arm64" ], @@ -1056,9 +1284,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", - "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", + "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", "cpu": [ "arm64" ], @@ -1070,9 +1298,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", - "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", + "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", "cpu": [ "x64" ], @@ -1084,9 +1312,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", - "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", + "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", "cpu": [ "arm64" ], @@ -1098,9 +1326,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", - "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", + "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", "cpu": [ "x64" ], @@ -1112,9 +1340,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", - "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", + "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", "cpu": [ "arm" ], @@ -1126,9 +1354,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", - "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", + "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", "cpu": [ "arm" ], @@ -1140,9 +1368,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", - "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", + "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", "cpu": [ "arm64" ], @@ -1154,9 +1382,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", - "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", + "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", "cpu": [ "arm64" ], @@ -1167,10 +1395,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", - "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", + "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", "cpu": [ "loong64" ], @@ -1181,10 +1409,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", - "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", + "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", "cpu": [ "ppc64" ], @@ -1196,9 +1424,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", - "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", + "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", "cpu": [ "riscv64" ], @@ -1210,9 +1438,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", - "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", + "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", "cpu": [ "riscv64" ], @@ -1224,9 +1452,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", - "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", + "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", "cpu": [ "s390x" ], @@ -1238,9 +1466,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", - "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", + "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", "cpu": [ "x64" ], @@ -1252,9 +1480,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", - "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", + "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", "cpu": [ "x64" ], @@ -1265,10 +1493,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", + "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", - "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", + "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", "cpu": [ "arm64" ], @@ -1280,9 +1522,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", - "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", + "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", "cpu": [ "ia32" ], @@ -1293,10 +1535,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", + "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", - "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", + "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", "cpu": [ "x64" ], @@ -1320,15 +1576,15 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.3.tgz", - "integrity": "sha512-ZaDETVWnm6FE0fc+c2UE8MHYVS3Fe91o5vkmGfgwGXFbxYvAjKSqxM/j4cRc9T7VZNSJjriXq58XkfCp3Y6f+w==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.2.tgz", + "integrity": "sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.23" + "@swc/types": "^0.1.25" }, "engines": { "node": ">=10" @@ -1338,16 +1594,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.13.3", - "@swc/core-darwin-x64": "1.13.3", - "@swc/core-linux-arm-gnueabihf": "1.13.3", - "@swc/core-linux-arm64-gnu": "1.13.3", - "@swc/core-linux-arm64-musl": "1.13.3", - "@swc/core-linux-x64-gnu": "1.13.3", - "@swc/core-linux-x64-musl": "1.13.3", - "@swc/core-win32-arm64-msvc": "1.13.3", - "@swc/core-win32-ia32-msvc": "1.13.3", - "@swc/core-win32-x64-msvc": "1.13.3" + "@swc/core-darwin-arm64": "1.15.2", + "@swc/core-darwin-x64": "1.15.2", + "@swc/core-linux-arm-gnueabihf": "1.15.2", + "@swc/core-linux-arm64-gnu": "1.15.2", + "@swc/core-linux-arm64-musl": "1.15.2", + "@swc/core-linux-x64-gnu": "1.15.2", + "@swc/core-linux-x64-musl": "1.15.2", + "@swc/core-win32-arm64-msvc": "1.15.2", + "@swc/core-win32-ia32-msvc": "1.15.2", + "@swc/core-win32-x64-msvc": "1.15.2" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -1359,9 +1615,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.3.tgz", - "integrity": "sha512-ux0Ws4pSpBTqbDS9GlVP354MekB1DwYlbxXU3VhnDr4GBcCOimpocx62x7cFJkSpEBF8bmX8+/TTCGKh4PbyXw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.2.tgz", + "integrity": "sha512-Ghyz4RJv4zyXzrUC1B2MLQBbppIB5c4jMZJybX2ebdEQAvryEKp3gq1kBksCNsatKGmEgXul88SETU19sMWcrw==", "cpu": [ "arm64" ], @@ -1376,9 +1632,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.3.tgz", - "integrity": "sha512-p0X6yhxmNUOMZrbeZ3ZNsPige8lSlSe1llllXvpCLkKKxN/k5vZt1sULoq6Nj4eQ7KeHQVm81/+AwKZyf/e0TA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.2.tgz", + "integrity": "sha512-7n/PGJOcL2QoptzL42L5xFFfXY5rFxLHnuz1foU+4ruUTG8x2IebGhtwVTpaDN8ShEv2UZObBlT1rrXTba15Zw==", "cpu": [ "x64" ], @@ -1393,9 +1649,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.3.tgz", - "integrity": "sha512-OmDoiexL2fVWvQTCtoh0xHMyEkZweQAlh4dRyvl8ugqIPEVARSYtaj55TBMUJIP44mSUOJ5tytjzhn2KFxFcBA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.2.tgz", + "integrity": "sha512-ZUQVCfRJ9wimuxkStRSlLwqX4TEDmv6/J+E6FicGkQ6ssLMWoKDy0cAo93HiWt/TWEee5vFhFaSQYzCuBEGO6A==", "cpu": [ "arm" ], @@ -1410,9 +1666,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.3.tgz", - "integrity": "sha512-STfKku3QfnuUj6k3g9ld4vwhtgCGYIFQmsGPPgT9MK/dI3Lwnpe5Gs5t1inoUIoGNP8sIOLlBB4HV4MmBjQuhw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.2.tgz", + "integrity": "sha512-GZh3pYBmfnpQ+JIg+TqLuz+pM+Mjsk5VOzi8nwKn/m+GvQBsxD5ectRtxuWUxMGNG8h0lMy4SnHRqdK3/iJl7A==", "cpu": [ "arm64" ], @@ -1427,9 +1683,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.3.tgz", - "integrity": "sha512-bc+CXYlFc1t8pv9yZJGus372ldzOVscBl7encUBlU1m/Sig0+NDJLz6cXXRcFyl6ABNOApWeR4Yl7iUWx6C8og==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.2.tgz", + "integrity": "sha512-5av6VYZZeneiYIodwzGMlnyVakpuYZryGzFIbgu1XP8wVylZxduEzup4eP8atiMDFmIm+s4wn8GySJmYqeJC0A==", "cpu": [ "arm64" ], @@ -1444,9 +1700,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.3.tgz", - "integrity": "sha512-dFXoa0TEhohrKcxn/54YKs1iwNeW6tUkHJgXW33H381SvjKFUV53WR231jh1sWVJETjA3vsAwxKwR23s7UCmUA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.2.tgz", + "integrity": "sha512-1nO/UfdCLuT/uE/7oB3EZgTeZDCIa6nL72cFEpdegnqpJVNDI6Qb8U4g/4lfVPkmHq2lvxQ0L+n+JdgaZLhrRA==", "cpu": [ "x64" ], @@ -1461,9 +1717,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.3.tgz", - "integrity": "sha512-ieyjisLB+ldexiE/yD8uomaZuZIbTc8tjquYln9Quh5ykOBY7LpJJYBWvWtm1g3pHv6AXlBI8Jay7Fffb6aLfA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.2.tgz", + "integrity": "sha512-Ksfrb0Tx310kr+TLiUOvB/I80lyZ3lSOp6cM18zmNRT/92NB4mW8oX2Jo7K4eVEI2JWyaQUAFubDSha2Q+439A==", "cpu": [ "x64" ], @@ -1478,9 +1734,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.3.tgz", - "integrity": "sha512-elTQpnaX5vESSbhCEgcwXjpMsnUbqqHfEpB7ewpkAsLzKEXZaK67ihSRYAuAx6ewRQTo7DS5iTT6X5aQD3MzMw==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.2.tgz", + "integrity": "sha512-IzUb5RlMUY0r1A9IuJrQ7Tbts1wWb73/zXVXT8VhewbHGoNlBKE0qUhKMED6Tv4wDF+pmbtUJmKXDthytAvLmg==", "cpu": [ "arm64" ], @@ -1495,9 +1751,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.3.tgz", - "integrity": "sha512-nvehQVEOdI1BleJpuUgPLrclJ0TzbEMc+MarXDmmiRFwEUGqj+pnfkTSb7RZyS1puU74IXdK/YhTirHurtbI9w==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.2.tgz", + "integrity": "sha512-kCATEzuY2LP9AlbU2uScjcVhgnCAkRdu62vbce17Ro5kxEHxYWcugkveyBRS3AqZGtwAKYbMAuNloer9LS/hpw==", "cpu": [ "ia32" ], @@ -1512,9 +1768,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.3.tgz", - "integrity": "sha512-A+JSKGkRbPLVV2Kwx8TaDAV0yXIXm/gc8m98hSkVDGlPBBmydgzNdWy3X7HTUBM7IDk7YlWE7w2+RUGjdgpTmg==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.2.tgz", + "integrity": "sha512-iJaHeYCF4jTn7OEKSa3KRiuVFIVYts8jYjNmCdyz1u5g8HRyTDISD76r8+ljEOgm36oviRQvcXaw6LFp1m0yyA==", "cpu": [ "x64" ], @@ -1536,9 +1792,9 @@ "license": "Apache-2.0" }, "node_modules/@swc/types": { - "version": "0.1.23", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", - "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", + "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1589,54 +1845,49 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", - "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", + "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "enhanced-resolve": "^5.18.1", - "jiti": "^2.4.2", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.11" + "tailwindcss": "4.1.17" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", - "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", + "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-x64": "4.1.11", - "@tailwindcss/oxide-freebsd-x64": "4.1.11", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-x64-musl": "4.1.11", - "@tailwindcss/oxide-wasm32-wasi": "4.1.11", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + "@tailwindcss/oxide-android-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-x64": "4.1.17", + "@tailwindcss/oxide-freebsd-x64": "4.1.17", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-x64-musl": "4.1.17", + "@tailwindcss/oxide-wasm32-wasi": "4.1.17", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", - "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", + "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", "cpu": [ "arm64" ], @@ -1651,9 +1902,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", - "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", + "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", "cpu": [ "arm64" ], @@ -1668,9 +1919,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", - "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", + "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", "cpu": [ "x64" ], @@ -1685,9 +1936,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", - "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", + "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", "cpu": [ "x64" ], @@ -1702,9 +1953,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", - "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", + "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", "cpu": [ "arm" ], @@ -1719,9 +1970,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", - "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", + "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", "cpu": [ "arm64" ], @@ -1736,9 +1987,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", - "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", + "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", "cpu": [ "arm64" ], @@ -1753,9 +2004,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", - "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", + "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", "cpu": [ "x64" ], @@ -1770,9 +2021,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", - "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", + "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", "cpu": [ "x64" ], @@ -1787,9 +2038,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", - "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", + "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1805,21 +2056,21 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.11", - "@tybys/wasm-util": "^0.9.0", - "tslib": "^2.8.0" + "@emnapi/core": "^1.6.0", + "@emnapi/runtime": "^1.6.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.7", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", - "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", + "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", "cpu": [ "arm64" ], @@ -1834,9 +2085,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", - "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", + "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", "cpu": [ "x64" ], @@ -1851,15 +2102,12 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", - "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", + "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", "dev": true, "license": "MIT", "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { @@ -1867,15 +2115,15 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", - "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.17.tgz", + "integrity": "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.11", - "@tailwindcss/oxide": "4.1.11", - "tailwindcss": "4.1.11" + "@tailwindcss/node": "4.1.17", + "@tailwindcss/oxide": "4.1.17", + "tailwindcss": "4.1.17" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" @@ -1915,9 +2163,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -1943,9 +2191,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", - "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.5.tgz", + "integrity": "sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==", "devOptional": true, "license": "MIT", "peer": true, @@ -1954,13 +2202,13 @@ } }, "node_modules/@types/react-dom": { - "version": "19.1.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", - "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "dev": true, "license": "MIT", "peerDependencies": { - "@types/react": "^19.0.0" + "@types/react": "^19.2.0" } }, "node_modules/@types/react-resizable": { @@ -1974,9 +2222,9 @@ } }, "node_modules/@types/react-virtualized": { - "version": "9.22.2", - "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.22.2.tgz", - "integrity": "sha512-0Eg/ME3OHYWGxs+/n4VelfYrhXssireZaa1Uqj5SEkTpSaBu5ctFGOCVxcOqpGXRiEdrk/7uho9tlZaryCIjHA==", + "version": "9.22.3", + "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.22.3.tgz", + "integrity": "sha512-UKRWeBIrECaKhE4O//TSFhlgwntMwyiEIOA7WZoVkr52Jahv0dH6YIOorqc358N2V3oKFclsq5XxPmx2PiYB5A==", "dev": true, "license": "MIT", "dependencies": { @@ -1991,17 +2239,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", - "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz", + "integrity": "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/type-utils": "8.38.0", - "@typescript-eslint/utils": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/type-utils": "8.46.4", + "@typescript-eslint/utils": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2015,9 +2263,9 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.38.0", + "@typescript-eslint/parser": "^8.46.4", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { @@ -2031,17 +2279,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", - "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz", + "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", "debug": "^4.3.4" }, "engines": { @@ -2053,18 +2301,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", - "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.38.0", - "@typescript-eslint/types": "^8.38.0", + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", "debug": "^4.3.4" }, "engines": { @@ -2075,18 +2323,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", - "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0" + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2097,9 +2345,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", - "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", "dev": true, "license": "MIT", "engines": { @@ -2110,19 +2358,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", - "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz", + "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4", + "@typescript-eslint/utils": "8.46.4", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2135,13 +2383,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", - "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", "dev": true, "license": "MIT", "engines": { @@ -2153,16 +2401,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", - "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.38.0", - "@typescript-eslint/tsconfig-utils": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2178,7 +2426,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -2208,9 +2456,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { @@ -2221,16 +2469,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", - "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0" + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2241,17 +2489,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", - "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/types": "8.46.4", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -2263,14 +2511,17 @@ } }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz", - "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.2.2.tgz", + "integrity": "sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.27", - "@swc/core": "^1.12.11" + "@rolldown/pluginutils": "1.0.0-beta.47", + "@swc/core": "^1.13.5" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" @@ -2509,9 +2760,9 @@ } }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -2526,6 +2777,16 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.28", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz", + "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2550,6 +2811,41 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2609,6 +2905,27 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001755", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", + "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2626,16 +2943,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/client-zip": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/client-zip/-/client-zip-2.5.0.tgz", @@ -2690,6 +2997,13 @@ "dev": true, "license": "MIT" }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cookie": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", @@ -2923,10 +3237,17 @@ "node": ">= 0.4" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.254", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz", + "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==", + "dev": true, + "license": "ISC" + }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", "dependencies": { @@ -3148,6 +3469,16 @@ "@esbuild/win32-x64": "0.25.5" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3162,26 +3493,25 @@ } }, "node_modules/eslint": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", - "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.32.0", - "@eslint/plugin-kit": "^0.3.4", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -3257,22 +3587,29 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, "engines": { - "node": ">=10" + "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" } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz", + "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3605,6 +3942,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -3674,9 +4021,9 @@ } }, "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -3820,6 +4167,23 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3831,9 +4195,9 @@ } }, "node_modules/immer": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", - "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", "license": "MIT", "funding": { "type": "opencollective", @@ -4293,9 +4657,9 @@ } }, "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", "bin": { @@ -4321,6 +4685,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4342,6 +4719,19 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -4392,9 +4782,9 @@ } }, "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -4408,22 +4798,44 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", "cpu": [ "arm64" ], @@ -4442,9 +4854,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", "cpu": [ "x64" ], @@ -4463,9 +4875,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", "cpu": [ "x64" ], @@ -4484,9 +4896,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", "cpu": [ "arm" ], @@ -4505,9 +4917,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", "cpu": [ "arm64" ], @@ -4526,9 +4938,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", "cpu": [ "arm64" ], @@ -4547,9 +4959,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", "cpu": [ "x64" ], @@ -4568,9 +4980,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", "cpu": [ "x64" ], @@ -4589,9 +5001,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", "cpu": [ "arm64" ], @@ -4610,9 +5022,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", "cpu": [ "x64" ], @@ -4652,20 +5064,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4685,23 +5083,33 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/lucide-react": { - "version": "0.536.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.536.0.tgz", - "integrity": "sha512-2PgvNa9v+qz4Jt/ni8vPLt4jwoFybXHuubQT8fv4iCW5TjDxkbZjNZZHa485ad73NSEn/jdsEtU57eE1g+ma8A==", + "version": "0.553.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.553.0.tgz", + "integrity": "sha512-BRgX5zrWmNy/lkVAe0dXBgd7XQdZ3HTf+Hwe3c9WK6dqgnj9h+hxV+MDncM88xDWlCq27+TKvHGE70ViODNILw==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/make-cancellable-promise": { @@ -4816,45 +5224,6 @@ "node": "*" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4888,6 +5257,13 @@ "dev": true, "license": "MIT" }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5256,9 +5632,9 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", "peer": true, "engines": { @@ -5266,16 +5642,16 @@ } }, "node_modules/react-dom": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", "peer": true, "dependencies": { - "scheduler": "^0.26.0" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.1.1" + "react": "^19.2.0" } }, "node_modules/react-is": { @@ -5353,9 +5729,9 @@ } }, "node_modules/react-router": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.1.tgz", - "integrity": "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz", + "integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -5375,12 +5751,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.1.tgz", - "integrity": "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.6.tgz", + "integrity": "sha512-2MkC2XSXq6HjGcihnx1s0DBWQETI4mlis4Ux7YTLvP67xnGxCvq+BcCQSO81qQHVUTM1V53tl4iVVaY5sReCOA==", "license": "MIT", "dependencies": { - "react-router": "7.7.1" + "react-router": "7.9.6" }, "engines": { "node": ">=20.0.0" @@ -5514,13 +5890,13 @@ } }, "node_modules/rollup": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", - "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", + "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -5530,26 +5906,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.41.1", - "@rollup/rollup-android-arm64": "4.41.1", - "@rollup/rollup-darwin-arm64": "4.41.1", - "@rollup/rollup-darwin-x64": "4.41.1", - "@rollup/rollup-freebsd-arm64": "4.41.1", - "@rollup/rollup-freebsd-x64": "4.41.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", - "@rollup/rollup-linux-arm-musleabihf": "4.41.1", - "@rollup/rollup-linux-arm64-gnu": "4.41.1", - "@rollup/rollup-linux-arm64-musl": "4.41.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", - "@rollup/rollup-linux-riscv64-gnu": "4.41.1", - "@rollup/rollup-linux-riscv64-musl": "4.41.1", - "@rollup/rollup-linux-s390x-gnu": "4.41.1", - "@rollup/rollup-linux-x64-gnu": "4.41.1", - "@rollup/rollup-linux-x64-musl": "4.41.1", - "@rollup/rollup-win32-arm64-msvc": "4.41.1", - "@rollup/rollup-win32-ia32-msvc": "4.41.1", - "@rollup/rollup-win32-x64-msvc": "4.41.1", + "@rollup/rollup-android-arm-eabi": "4.53.2", + "@rollup/rollup-android-arm64": "4.53.2", + "@rollup/rollup-darwin-arm64": "4.53.2", + "@rollup/rollup-darwin-x64": "4.53.2", + "@rollup/rollup-freebsd-arm64": "4.53.2", + "@rollup/rollup-freebsd-x64": "4.53.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", + "@rollup/rollup-linux-arm-musleabihf": "4.53.2", + "@rollup/rollup-linux-arm64-gnu": "4.53.2", + "@rollup/rollup-linux-arm64-musl": "4.53.2", + "@rollup/rollup-linux-loong64-gnu": "4.53.2", + "@rollup/rollup-linux-ppc64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-musl": "4.53.2", + "@rollup/rollup-linux-s390x-gnu": "4.53.2", + "@rollup/rollup-linux-x64-gnu": "4.53.2", + "@rollup/rollup-linux-x64-musl": "4.53.2", + "@rollup/rollup-openharmony-arm64": "4.53.2", + "@rollup/rollup-win32-arm64-msvc": "4.53.2", + "@rollup/rollup-win32-ia32-msvc": "4.53.2", + "@rollup/rollup-win32-x64-gnu": "4.53.2", + "@rollup/rollup-win32-x64-msvc": "4.53.2", "fsevents": "~2.3.2" } }, @@ -5633,9 +6011,9 @@ } }, "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/semver": { @@ -5649,9 +6027,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, "node_modules/set-function-length": { @@ -5950,39 +6328,25 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", - "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", + "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", "dev": true, "license": "MIT", "peer": true }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" }, - "engines": { - "node": ">=18" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tiny-invariant": { @@ -5992,14 +6356,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -6009,11 +6373,14 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6024,9 +6391,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "peer": true, @@ -6155,9 +6522,9 @@ } }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -6170,16 +6537,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.38.0.tgz", - "integrity": "sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==", + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.4.tgz", + "integrity": "sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.38.0", - "@typescript-eslint/parser": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/utils": "8.38.0" + "@typescript-eslint/eslint-plugin": "8.46.4", + "@typescript-eslint/parser": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4", + "@typescript-eslint/utils": "8.46.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6190,7 +6557,7 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/unbox-primitive": { @@ -6212,6 +6579,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6239,32 +6637,32 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/esm/bin/uuid" + "uuid": "dist-node/bin/uuid" } }, "node_modules/vite": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", - "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz", + "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.6", + "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", - "rollup": "^4.40.0", - "tinyglobby": "^0.2.14" + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" @@ -6328,11 +6726,14 @@ } }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6481,14 +6882,11 @@ } }, "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } + "license": "ISC" }, "node_modules/yocto-queue": { "version": "0.1.0", @@ -6504,13 +6902,27 @@ } }, "node_modules/zod": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", - "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } } } } diff --git a/src/MaksIT.WebUI/package.json b/src/MaksIT.WebUI/package.json index 877afc7..ef0c8fa 100644 --- a/src/MaksIT.WebUI/package.json +++ b/src/MaksIT.WebUI/package.json @@ -1,55 +1,55 @@ { - "name": "maksit-vault", + "name": "maksit-certs-ui", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", - "build": "tsc -b && vite build", + "build": "tsc -b && vite build --mode prod", "lint": "eslint .", "preview": "vite preview" }, "dependencies": { - "@reduxjs/toolkit": "^2.8.2", + "@reduxjs/toolkit": "^2.10.1", "@tanstack/react-table": "^8.21.3", - "axios": "^1.11.0", + "axios": "^1.13.2", "client-zip": "^2.5.0", "date-fns": "^4.1.0", "jwt-decode": "^4.0.0", "lodash": "^4.17.21", - "lucide-react": "^0.536.0", + "lucide-react": "^0.553.0", "qrcode.react": "^4.2.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", + "react": "^19.2.0", + "react-dom": "^19.2.0", "react-pdf": "^10.2.0", "react-redux": "^9.2.0", - "react-router-dom": "^7.7.1", + "react-router-dom": "^7.9.6", "react-virtualized": "^9.22.6", - "uuid": "^11.1.0", - "zod": "^4.0.14" + "uuid": "^13.0.0", + "zod": "^4.1.12" }, "devDependencies": { - "@eslint/js": "^9.32.0", + "@eslint/js": "^9.39.1", "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.10", "@tailwindcss/line-clamp": "^0.4.4", - "@tailwindcss/typography": "^0.5.16", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.1.17", "@types/lodash": "^4.17.20", - "@types/react": "^19.1.9", - "@types/react-dom": "^19.1.7", + "@types/react": "^19.2.5", + "@types/react-dom": "^19.2.3", "@types/react-resizable": "^3.0.8", - "@types/react-virtualized": "^9.22.2", - "@vitejs/plugin-react-swc": "^3.11.0", - "eslint": "^9.32.0", + "@types/react-virtualized": "^9.22.3", + "@vitejs/plugin-react-swc": "^4.2.2", + "eslint": "^9.39.1", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "tailwindcss": "^4.1.11", - "typescript": "^5.8.0", - "typescript-eslint": "^8.38.0", - "vite": "^7.0.6" + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "typescript-eslint": "^8.46.4", + "vite": "^7.2.2" } } diff --git a/src/MaksIT.WebUI/public/config.js b/src/MaksIT.WebUI/public/config.js new file mode 100644 index 0000000..6e9b5f4 --- /dev/null +++ b/src/MaksIT.WebUI/public/config.js @@ -0,0 +1,3 @@ +window.RUNTIME_CONFIG = { + API_URL: "http://172.16.0.5:8080/api" +}; \ No newline at end of file diff --git a/src/MaksIT.WebUI/src/AppMap.tsx b/src/MaksIT.WebUI/src/AppMap.tsx index 1bf039e..9b5f2e5 100644 --- a/src/MaksIT.WebUI/src/AppMap.tsx +++ b/src/MaksIT.WebUI/src/AppMap.tsx @@ -13,6 +13,14 @@ import { LetsEncryptTermsOfServicePage } from './pages/LetsEncryptTermsOfService import { UserPage } from './pages/UserPage' +declare global { + interface Window { + RUNTIME_CONFIG?: { + API_URL?: string; + }; + } +} + interface LayoutWrapperProps { children: ReactNode } @@ -250,7 +258,7 @@ interface ApiRoute { } const GetApiRoute = (apiRoute: ApiRoutes): ApiRoute => { - const apiUrl = import.meta.env.VITE_API_URL + const apiUrl = window.RUNTIME_CONFIG?.API_URL || import.meta.env.VITE_API_URL const [method, route] = apiRoute.split('|') diff --git a/src/MaksIT.WebUI/src/components/DataTable/DataTable.tsx b/src/MaksIT.WebUI/src/components/DataTable/DataTable.tsx index 7e447e4..7188f30 100644 --- a/src/MaksIT.WebUI/src/components/DataTable/DataTable.tsx +++ b/src/MaksIT.WebUI/src/components/DataTable/DataTable.tsx @@ -87,7 +87,7 @@ const DataTable = ,>(props: DataTableProps) const gridRef = useRef(null) const [selectedRowIndex, setSelectedRowIndex] = useState(null) - const [filterValues, setFilterValues] = useState>>({}) + const filterValues = useRef>>({}) const [colWidths, setColWidths] = useState(() => { const defaultWidths = [DEFAULT_ACTION_WIDTH, ...columns.map(() => DEFAULT_COL_WIDTH)] @@ -138,28 +138,28 @@ const DataTable = ,>(props: DataTableProps) columnId: string, filters: string ) => { - setFilterValues((prev) => { - const newValues = { - ...prev, - [filterId]: { - ...prev[filterId], - [columnId]: filters, - }, - } + const prev = filterValues.current + + const newValues = { + ...prev, + [filterId]: { + ...prev[filterId], + [columnId]: filters, + }, + } + filterValues.current = newValues - const linqQueries = Object.fromEntries( - Object.entries(newValues).map(([fid, cols]) => { - const q = Object.values(cols) - .filter((v) => v) - .map((v) => `(${v})`) - .join(' && ') - return [fid, q] - }) - ) + const linqQueries = Object.fromEntries( + Object.entries(newValues).map(([fid, cols]) => { + const q = Object.values(cols) + .filter((v) => v) + .map((v) => `(${v})`) + .join(' && ') + return [fid, q] + }) + ) - debouncedOnFilterChange?.(linqQueries) - return newValues - }) + debouncedOnFilterChange?.(linqQueries) } const handlePreviousPage = () => onPreviousPage?.(pageNumber - 1) diff --git a/src/MaksIT.WebUI/src/entities/CacheAccount.ts b/src/MaksIT.WebUI/src/entities/CacheAccount.ts index 034e2bb..e11a036 100644 --- a/src/MaksIT.WebUI/src/entities/CacheAccount.ts +++ b/src/MaksIT.WebUI/src/entities/CacheAccount.ts @@ -1,6 +1,3 @@ - -import { PatchAccountRequest } from '../models/letsEncryptServer/account/requests/PatchAccountRequest' -import { PatchOperation } from '../models/PatchOperation' import { CacheAccountHostname } from './CacheAccountHostname' export interface CacheAccount { @@ -13,29 +10,3 @@ export interface CacheAccount { isEditMode: boolean isStaging: boolean } - -const toPatchAccountRequest = (account: CacheAccount): PatchAccountRequest => { - return { - description: { op: PatchOperation.None, value: account.description }, - isDisabled: { op: PatchOperation.None, value: account.isDisabled }, - contacts: account.contacts.map((contact, index) => ({ - index: index, - op: PatchOperation.None, - value: contact - })), - hostnames: account.hostnames?.map((hostname, index) => ({ - hostname: { - index: index, - op: PatchOperation.None, - value: hostname.hostname - }, - isDisabled: { - index: index, - op: PatchOperation.None, - value: hostname.isDisabled - } - })) - } -} - -export { toPatchAccountRequest } diff --git a/src/MaksIT.WebUI/src/forms/Home.tsx b/src/MaksIT.WebUI/src/forms/Home.tsx index 3540c80..cc7f0fe 100644 --- a/src/MaksIT.WebUI/src/forms/Home.tsx +++ b/src/MaksIT.WebUI/src/forms/Home.tsx @@ -1,7 +1,6 @@ import { FC, useCallback, useEffect, useState } from 'react' import { FormContainer, FormContent, FormFooter, FormHeader } from '../components/FormLayout' import { ButtonComponent, CheckBoxComponent, RadioGroupComponent, SelectBoxComponent } from '../components/editors' -import { CacheAccount } from '../entities/CacheAccount' import { GetAccountResponse } from '../models/letsEncryptServer/account/responses/GetAccountResponse' import { deleteData, getData, postData } from '../axiosConfig' import { ApiRoutes, GetApiRoute } from '../AppMap' @@ -27,16 +26,6 @@ const Home: FC = () => { loadData() }, [loadData]) - const handleAccountUpdate = (updatedAccount: CacheAccount) => { - // setAccounts( - // accounts.map((account) => - // account.accountId === updatedAccount.accountId - // ? updatedAccount - // : account - // ) - // ) - } - const handleDeleteAccount = (accountId: string) => { deleteData( GetApiRoute(ApiRoutes.ACCOUNT_DELETE) diff --git a/src/MaksIT.WebUI/src/forms/Users/EditUser/index.tsx b/src/MaksIT.WebUI/src/forms/Users/EditUser/index.tsx index b65567f..3d3a69d 100644 --- a/src/MaksIT.WebUI/src/forms/Users/EditUser/index.tsx +++ b/src/MaksIT.WebUI/src/forms/Users/EditUser/index.tsx @@ -1,23 +1,16 @@ import { FC, useState } from 'react' import { FormContainer, FormContent, FormHeader } from '../../../components/FormLayout' import { ButtonComponent } from '../../../components/editors' -import { UserResponse } from '../../../models/identity/user/UserResponse' import { ChangePassword } from './ChangePassword' interface EditUserProps { userId: string; - onSubmitted?: (entity: UserResponse) => void - cancelEnabled?: boolean - onCancel?: () => void } const EditUser : FC = (props) => { const { userId, - onSubmitted, - cancelEnabled = false, - onCancel } = props const [showChangePassword, setShowChangePassword] = useState(false) diff --git a/src/MaksIT.WebUI/src/forms/Utilities.tsx b/src/MaksIT.WebUI/src/forms/Utilities.tsx index 00d9927..9f3a6b4 100644 --- a/src/MaksIT.WebUI/src/forms/Utilities.tsx +++ b/src/MaksIT.WebUI/src/forms/Utilities.tsx @@ -6,6 +6,7 @@ import { deleteData, getBinary, getData, postFile } from '../axiosConfig' import { addToast } from '../components/Toast/addToast' import { extractFilenameFromHeaders, saveBinaryToDisk } from '../functions' import { downloadZip } from 'client-zip' +import { HelloWorldResponse } from '../models/Agent/HelloWorldResponse' const Utilities: FC = () => { @@ -13,7 +14,7 @@ const Utilities: FC = () => { const [files, setFiles] = useState([]) const hadnleTestAgent = () => { - getData(GetApiRoute(ApiRoutes.AGENT_TEST).route) + getData(GetApiRoute(ApiRoutes.AGENT_TEST).route) .then((response) => { if (!response) return diff --git a/src/MaksIT.WebUI/src/models/Agent/HelloWorldResponse.ts b/src/MaksIT.WebUI/src/models/Agent/HelloWorldResponse.ts new file mode 100644 index 0000000..7c057d4 --- /dev/null +++ b/src/MaksIT.WebUI/src/models/Agent/HelloWorldResponse.ts @@ -0,0 +1,3 @@ +export interface HelloWorldResponse { + message: string +} \ No newline at end of file diff --git a/src/MaksIT.WebUI/src/models/identity/login/LoginRequest.ts b/src/MaksIT.WebUI/src/models/identity/login/LoginRequest.ts index 961412d..d048274 100644 --- a/src/MaksIT.WebUI/src/models/identity/login/LoginRequest.ts +++ b/src/MaksIT.WebUI/src/models/identity/login/LoginRequest.ts @@ -1,4 +1,4 @@ -import { object, RefinementCtx, Schema, string, ZodIssueCode } from 'zod' +import { object, RefinementCtx, Schema, string } from 'zod' export interface LoginRequest { username: string @@ -8,10 +8,9 @@ export interface LoginRequest { } const LoginRequestSchemaRefine = (data: LoginRequest, ctx: RefinementCtx) => { - if (data.username === '') { ctx.addIssue({ - code: ZodIssueCode.custom, + code: 'custom', message: 'Username cannot be empty', path: ['username'] }) @@ -19,7 +18,7 @@ const LoginRequestSchemaRefine = (data: LoginRequest, ctx: RefinementCtx) => { if (data.password === '') { ctx.addIssue({ - code: ZodIssueCode.custom, + code: 'custom', message: 'Password cannot be empty', path: ['password'] }) @@ -27,13 +26,11 @@ const LoginRequestSchemaRefine = (data: LoginRequest, ctx: RefinementCtx) => { if (data.twoFactorCode && data.twoFactorRecoveryCode) { ctx.addIssue({ - code: ZodIssueCode.custom, + code: 'custom', message: 'Cannot have both twoFactorCode and twoFactorRecoveryCode', path: ['twoFactorCode', 'twoFactorRecoveryCode'] }) } - - return data } export const LoginRequestSchema: Schema = object({ diff --git a/src/MaksIT.Webapi/Controllers/CacheController.cs b/src/MaksIT.Webapi/Controllers/CacheController.cs index 6494e6d..d6f2a7b 100644 --- a/src/MaksIT.Webapi/Controllers/CacheController.cs +++ b/src/MaksIT.Webapi/Controllers/CacheController.cs @@ -24,7 +24,7 @@ public class CacheController(ICacheService cacheService) : ControllerBase { [HttpPost("cache/upload")] //[RequestSizeLimit(200_000_000)] - public async Task PostCache([FromForm] IFormFile file) { + public async Task PostCache(IFormFile file) { if (file is null || file.Length == 0) return BadRequest("No file."); using var ms = new MemoryStream(); diff --git a/src/MaksIT.Webapi/MaksIT.Webapi.csproj b/src/MaksIT.Webapi/MaksIT.Webapi.csproj index b1f4087..9237ed2 100644 --- a/src/MaksIT.Webapi/MaksIT.Webapi.csproj +++ b/src/MaksIT.Webapi/MaksIT.Webapi.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/MaksIT.Webapi/Program.cs b/src/MaksIT.Webapi/Program.cs index 6bead25..9a74f33 100644 --- a/src/MaksIT.Webapi/Program.cs +++ b/src/MaksIT.Webapi/Program.cs @@ -69,16 +69,28 @@ builder.Services.AddHostedService(); builder.Services.AddHostedService(); #endregion +// Add CORS services to the container and configure to allow any origin +builder.Services.AddCors(options => { + options.AddPolicy("AllowAllOrigins", policy => + { + policy.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); +}); + var app = builder.Build(); +app.UseMiddleware(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); - app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); } -app.UseMiddleware(); +// Use CORS policy in the pipeline +app.UseCors("AllowAllOrigins"); app.UseAuthorization(); diff --git a/src/Release-DockerImage.ps1 b/src/Release-DockerImage.ps1 deleted file mode 100644 index 9542412..0000000 --- a/src/Release-DockerImage.ps1 +++ /dev/null @@ -1,59 +0,0 @@ -# Set variables -$projectName = "certs-ui" -$harborUrl = "cr.maks-it.com" # e.g., "harbor.yourdomain.com" -$tag = "latest" # Customize the tag as needed - -# Retrieve and decode username:password from environment variable (Base64 encoded) -try { - $decoded = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Env:CR_MAKS_IT)) -} catch { - throw "Failed to decode CR_MAKS_IT as Base64. Ensure it's base64('username:password'). Error: $_" -} - -# Split decoded credentials -$creds = $decoded -split ':', 2 -if ($creds.Count -ne 2) { - throw "Invalid decoded CR_MAKS_IT format. Expected 'username:password'." -} - -$harborUsername = $creds[0] -$harborPassword = $creds[1] - -# Authenticate with Harbor -Write-Output "Logging into $harborUrl as $harborUsername..." -$loginResult = $harborPassword | docker login $harborUrl -u $harborUsername --password-stdin 2>&1 -if ($LASTEXITCODE -ne 0 -or ($loginResult -notmatch "Login Succeeded")) { - throw "Docker login failed for $harborUrl.`n$loginResult" -} - -# List of services to build and push with the current context -$services = @{ - "reverseproxy" = "ReverseProxy/Dockerfile" - "server" = "LetsEncryptServer/Dockerfile" - "client" = "ClientApp/Dockerfile.prod" -} - -$contextPath = "." - -foreach ($service in $services.Keys) { - $dockerfilePath = $services[$service] - $imageName = "$harborUrl/$projectName/${service}:${tag}" - - # Build the Docker image - Write-Output "Building image $imageName from $dockerfilePath..." - docker build -t $imageName -f $dockerfilePath $contextPath - if ($LASTEXITCODE -ne 0) { - throw "Docker build failed for $imageName" - } - - # Push the Docker image - Write-Output "Pushing image $imageName..." - docker push $imageName - if ($LASTEXITCODE -ne 0) { - throw "Docker push failed for $imageName" - } -} - -# Logout after pushing images -docker logout $harborUrl | Out-Null -Write-Output "Completed successfully." diff --git a/src/Release-DockerImage.bat b/src/Release.bat similarity index 68% rename from src/Release-DockerImage.bat rename to src/Release.bat index 93070d3..10951b4 100644 --- a/src/Release-DockerImage.bat +++ b/src/Release.bat @@ -4,4 +4,6 @@ REM Change directory to the location of the script cd /d %~dp0 REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory -powershell -ExecutionPolicy Bypass -File "%~dp0Release-DockerImage.ps1" +powershell -ExecutionPolicy Bypass -File "%~dp0Release.ps1" + +pause \ No newline at end of file diff --git a/src/Release.ps1 b/src/Release.ps1 new file mode 100644 index 0000000..3a414ea --- /dev/null +++ b/src/Release.ps1 @@ -0,0 +1,105 @@ +# HINT: To create a tag for the last commit in git, use: +# git tag 1.2.3 +# git push origin 1.2.3 +# Replace '1.2.3' with your desired tag name. + +# Set variables +$projectName = "certs-ui" +$harborUrl = "cr.maks-it.com" # e.g., "harbor.yourdomain.com" + +# Ensure we are on main branch and up to date +git checkout main +git pull + +# Get the latest tag reachable from main +$tag = git describe --tags --abbrev=0 + +if (-not $tag) { + throw "No tags found on main branch." +} + +$tags = @($tag, "latest") +Write-Output "Using tags: $($tags -join ', ')" + +# Retrieve and decode username:password from environment variable (Base64 encoded) +try { + $decoded = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Env:CR_MAKS_IT)) +} catch { + throw "Failed to decode CR_MAKS_IT as Base64. Ensure it's base64('username:password'). Error: $_" +} + +# Split decoded credentials +$creds = $decoded -split ':', 2 +if ($creds.Count -ne 2) { + throw "Invalid decoded CR_MAKS_IT format. Expected 'username:password'." +} + +$harborUsername = $creds[0] +$harborPassword = $creds[1] + +# Authenticate with Harbor +Write-Output "Logging into $harborUrl as $harborUsername..." +$loginResult = $harborPassword | docker login $harborUrl -u $harborUsername --password-stdin 2>&1 +if ($LASTEXITCODE -ne 0 -or ($loginResult -notmatch "Login Succeeded")) { + throw "Docker login failed for $harborUrl.`n$loginResult" +} + +# List of services to build and push with the current context +$services = @{ + "reverseproxy" = "ReverseProxy/Dockerfile" + "server" = "MaksIT.Webapi/Dockerfile" + "client" = "MaksIT.WebUI/Dockerfile.prod" +} + +$contextPath = "." + +foreach ($service in $services.Keys) { + $dockerfilePath = $services[$service] + $baseImageName = "$harborUrl/$projectName/${service}" + + foreach ($t in $tags) { + $imageName = "$baseImageName`:$t" + Write-Output "Building image $imageName from $dockerfilePath..." + docker build -t $imageName -f $dockerfilePath $contextPath + if ($LASTEXITCODE -ne 0) { + throw "Docker build failed for $imageName" + } + + Write-Output "Pushing image $imageName..." + docker push $imageName + if ($LASTEXITCODE -ne 0) { + throw "Docker push failed for $imageName" + } + } +} + +# --- Helm Chart Release Section --- +# Package the Helm chart +$chartDir = "helm" +$chartPackageOutput = helm package $chartDir +$chartPackage = $null +if ($chartPackageOutput -match "Successfully packaged chart and saved it to: (.+\.tgz)") { + $chartPackage = $Matches[1] +} +if (-not $chartPackage) { + throw "Helm chart packaging failed. Output: $chartPackageOutput" +} + +# Push the Helm chart to the same Harbor project/repo as Docker images +$helmRepoUrl = "oci://$harborUrl/$projectName/charts" +Write-Output "Pushing Helm chart $chartPackage to $helmRepoUrl..." +helm push $chartPackage $helmRepoUrl --username $harborUsername --password $harborPassword +if ($LASTEXITCODE -ne 0) { + throw "Helm chart push failed." +} + +if ($chartPackage) { + Remove-Item $chartPackage -Force + Write-Output "Cleaned up $chartPackage" +} + +docker logout $harborUrl | Out-Null +Write-Output "Completed successfully." + + +# Logout after pushing images diff --git a/src/ReleaseAndDeploy.bat b/src/ReleaseAndDeploy.bat index 64fb452..c4a103f 100644 --- a/src/ReleaseAndDeploy.bat +++ b/src/ReleaseAndDeploy.bat @@ -4,11 +4,11 @@ setlocal REM Get the directory of the current script set "SCRIPT_DIR=%~dp0" -REM Run the first batch file -call "%SCRIPT_DIR%Release-DockerImage.bat" +REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory +powershell -ExecutionPolicy Bypass -File "%~dp0Release.ps1" -REM Run the second batch file -call "%SCRIPT_DIR%Deploy-Helm.bat" +REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory +powershell -ExecutionPolicy Bypass -File "%~dp0Deploy-Helm.ps1" echo All scripts completed. pause \ No newline at end of file diff --git a/src/docker-compose.final.yml b/src/docker-compose.final.yml deleted file mode 100644 index c2e4faf..0000000 --- a/src/docker-compose.final.yml +++ /dev/null @@ -1,46 +0,0 @@ -services: - letsencrypt-app: - image: ${DOCKER_REGISTRY-}letsencrypt-app - build: - context: . - dockerfile: ClientApp/Dockerfile - container_name: letsencrypt-app - environment: - - ASPNETCORE_ENVIRONMENT=Production - - LETSENCRYPT_SERVER=http://websrv0001.corp.maks-it.com - ports: - - "3000:3000" - network_mode: "host" - - - letsencrypt-server: - image: ${DOCKER_REGISTRY-}letsencrypt-server - build: - context: . - dockerfile: LetsEncryptServer/Dockerfile - container_name: letsencrypt-server - environment: - - ASPNETCORE_ENVIRONMENT=Production - - ASPNETCORE_HTTP_PORTS=9000 - - LETSENCRYPT_SERVER_PRODUCTION=https://acme-v02.api.letsencrypt.org/directory - - LETSENCRYPT_SERVER_STAGING=https://acme-staging-v02.api.letsencrypt.org/directory - - MAKS_IT_AGENT_HOSTNAME=http://websrv0001.corp.maks-it.com - - MAKS-IT_AGENT_PORT=5000 - - MAKS-IT_AGENT_KEY=UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I= - - MAKS-IT_AGENT_SERVICE=haproxy - volumes: - - ./docker-compose/LetsEncryptServer/acme:/app/acme - - ./docker-compose/LetsEncryptServer/cache:/app/cache - ports: - - "9000:9000" - network_mode: "host" - - - curl-test: - image: curlimages/curl:latest - container_name: curl-test - command: > - curl --location http://websrv0001.corp.maks-it.com:5000/HelloWorld - --header "x-api-key: UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=" - restart: "no" - network_mode: "host" diff --git a/src/helm/templates/deployments.yaml b/src/helm/templates/deployments.yaml index 5b2b3c8..9f290d7 100644 --- a/src/helm/templates/deployments.yaml +++ b/src/helm/templates/deployments.yaml @@ -11,7 +11,7 @@ metadata: {{- include "certs-ui.labels" $root | nindent 4 }} app.kubernetes.io/component: {{ $compName }} spec: - replicas: {{ default 1 $comp.replicas }} + replicas: 1 selector: matchLabels: app.kubernetes.io/instance: {{ $root.Release.Name }} @@ -46,6 +46,15 @@ spec: value: {{ .value | quote }} {{- end }} {{- end }} + {{- if eq $compName "client" }} + - name: VITE_API_URL + value: > + {{- if eq $root.Values.components.reverseproxy.service.type "LoadBalancer" -}} + http://{{ $root.Values.components.reverseproxy.service.loadBalancerIP }}:{{ $root.Values.components.reverseproxy.service.port }} + {{- else -}} + http://{{ include "certs-ui.fullname" $root }}-reverseproxy:{{ $root.Values.components.reverseproxy.service.port }} + {{- end }} + {{- end }} {{- $p := default dict $comp.persistence -}} {{- $vols := default (list) $p.volumes -}} {{- $hasVols := gt (len $vols) 0 -}} diff --git a/src/helm/templates/pvc.yaml b/src/helm/templates/pvc.yaml index f263783..233754d 100644 --- a/src/helm/templates/pvc.yaml +++ b/src/helm/templates/pvc.yaml @@ -17,7 +17,7 @@ spec: resources: requests: storage: {{ default "1Gi" $vol.pvc.size }} - storageClassName: {{ default "local-path" $vol.pvc.storageClass }} + storageClassName: {{ default $.Values.components.server.persistence.storageClass $vol.pvc.storageClass | quote }} {{- end }} {{- end }} {{- end }} diff --git a/src/helm/values.yaml b/src/helm/values.yaml index 35be399..178da35 100644 --- a/src/helm/values.yaml +++ b/src/helm/values.yaml @@ -4,7 +4,6 @@ global: components: server: - replicas: 1 image: registry: cr.maks-it.com repository: certs-ui/server @@ -21,13 +20,13 @@ components: port: 5000 targetPort: 5000 persistence: + storageClass: local-path volumes: - name: acme mountPath: /acme type: pvc pvc: create: true - storageClass: local-path size: 50Mi accessModes: [ReadWriteOnce] - name: cache @@ -35,7 +34,6 @@ components: type: pvc pvc: create: true - storageClass: local-path size: 50Mi accessModes: [ReadWriteOnce] - name: data @@ -43,7 +41,6 @@ components: type: pvc pvc: create: true - storageClass: local-path size: 50Mi accessModes: [ReadWriteOnce] secretsFile: @@ -99,7 +96,6 @@ components: forceUpdate: false client: - replicas: 1 image: registry: cr.maks-it.com repository: certs-ui/client @@ -108,16 +104,14 @@ components: env: - name: ASPNETCORE_ENVIRONMENT value: Development - - name: NEXT_PUBLIC_API_BASE_URL - value: http://certs-ui-server:5000 service: enabled: true type: ClusterIP - port: 3000 - targetPort: 3000 + port: 5173 + targetPort: 5173 + reverseproxy: - replicas: 1 image: registry: cr.maks-it.com repository: certs-ui/reverseproxy